1
The following changes since commit 4cc10cae64c51e17844dc4358481c393d7bf1ed4:
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
2
3
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-05-06 18:56:17 +0100)
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210510
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
8
8
9
for you to fetch changes up to 8f96812baa53005f32aece3e30b140826c20aa19:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
10
10
11
hw/arm/xlnx: Fix PHY address for xilinx-zynq-a9 (2021-05-10 13:24:09 +0100)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
target-arm queue:
14
target-arm queue:
15
* docs: fix link in sbsa description
15
* Implement FEAT_ECV
16
* linux-user/aarch64: Enable hwcap for RND, BTI, and MTE
16
* STM32L4x5: Implement GPIO device
17
* target/arm: Fix tlbbits calculation in tlbi_aa64_vae2is_write()
17
* Fix 32-bit SMOPA
18
* target/arm: Split neon and vfp translation to their own
18
* Refactor v7m related code from cpu32.c into its own file
19
compilation units
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
20
* target/arm: Make WFI a NOP for userspace emulators
21
* hw/sd/omap_mmc: Use device_cold_reset() instead of
22
device_legacy_reset()
23
* include: More fixes for 'extern "C"' block use
24
* hw/arm/imx25_pdk: Fix error message for invalid RAM size
25
* hw/arm/mps2-tz: Implement AN524 memory remapping via machine property
26
* hw/arm/xlnx: Fix PHY address for xilinx-zynq-a9
27
20
28
----------------------------------------------------------------
21
----------------------------------------------------------------
29
Alex Bennée (1):
22
Inès Varhol (3):
30
docs: fix link in sbsa description
23
hw/gpio: Implement STM32L4x5 GPIO
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
31
26
32
Guenter Roeck (1):
27
Peter Maydell (9):
33
hw/arm/xlnx: Fix PHY address for xilinx-zynq-a9
28
target/arm: Move some register related defines to internals.h
34
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
35
Peter Maydell (22):
30
target/arm: use FIELD macro for CNTHCTL bit definitions
36
target/arm: Fix tlbbits calculation in tlbi_aa64_vae2is_write()
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
37
target/arm: Move constant expanders to translate.h
32
target/arm: Implement new FEAT_ECV trap bits
38
target/arm: Share unallocated_encoding() and gen_exception_insn()
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
39
target/arm: Make functions used by m-nocp global
34
target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling
40
target/arm: Split m-nocp trans functions into their own file
35
target/arm: Enable FEAT_ECV for 'max' CPU
41
target/arm: Move gen_aa32 functions to translate-a32.h
36
hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
42
target/arm: Move vfp_{load, store}_reg{32, 64} to translate-vfp.c.inc
43
target/arm: Make functions used by translate-vfp global
44
target/arm: Make translate-vfp.c.inc its own compilation unit
45
target/arm: Move vfp_reg_ptr() to translate-neon.c.inc
46
target/arm: Delete unused typedef
47
target/arm: Move NeonGenThreeOpEnvFn typedef to translate.h
48
target/arm: Make functions used by translate-neon global
49
target/arm: Make translate-neon.c.inc its own compilation unit
50
target/arm: Make WFI a NOP for userspace emulators
51
hw/sd/omap_mmc: Use device_cold_reset() instead of device_legacy_reset()
52
osdep: Make os-win32.h and os-posix.h handle 'extern "C"' themselves
53
include/qemu/bswap.h: Handle being included outside extern "C" block
54
include/disas/dis-asm.h: Handle being included outside 'extern "C"'
55
hw/misc/mps2-scc: Add "QEMU interface" comment
56
hw/misc/mps2-scc: Support using CFG0 bit 0 for remapping
57
hw/arm/mps2-tz: Implement AN524 memory remapping via machine property
58
59
Philippe Mathieu-Daudé (1):
60
hw/arm/imx25_pdk: Fix error message for invalid RAM size
61
37
62
Richard Henderson (1):
38
Richard Henderson (1):
63
linux-user/aarch64: Enable hwcap for RND, BTI, and MTE
39
target/arm: Fix 32-bit SMOPA
64
40
65
docs/system/arm/mps2.rst | 10 +
41
Thomas Huth (1):
66
docs/system/arm/sbsa.rst | 2 +-
42
target/arm: Move v7m-related code from cpu32.c into a separate file
67
include/disas/dis-asm.h | 12 +-
68
include/hw/misc/mps2-scc.h | 21 ++
69
include/qemu/bswap.h | 26 ++-
70
include/qemu/osdep.h | 8 +-
71
include/sysemu/os-posix.h | 8 +
72
include/sysemu/os-win32.h | 8 +
73
target/arm/translate-a32.h | 144 +++++++++++++
74
target/arm/translate-a64.h | 2 -
75
target/arm/translate.h | 29 +++
76
hw/arm/imx25_pdk.c | 5 +-
77
hw/arm/mps2-tz.c | 108 +++++++++-
78
hw/arm/xilinx_zynq.c | 2 +-
79
hw/misc/mps2-scc.c | 13 +-
80
hw/sd/omap_mmc.c | 2 +-
81
linux-user/elfload.c | 13 ++
82
target/arm/helper.c | 2 +-
83
target/arm/op_helper.c | 12 ++
84
target/arm/translate-a64.c | 15 --
85
target/arm/translate-m-nocp.c | 221 ++++++++++++++++++++
86
.../arm/{translate-neon.c.inc => translate-neon.c} | 19 +-
87
.../arm/{translate-vfp.c.inc => translate-vfp.c} | 230 +++------------------
88
target/arm/translate.c | 200 ++++--------------
89
disas/arm-a64.cc | 2 -
90
disas/nanomips.cpp | 2 -
91
target/arm/meson.build | 15 +-
92
27 files changed, 718 insertions(+), 413 deletions(-)
93
create mode 100644 target/arm/translate-a32.h
94
create mode 100644 target/arm/translate-m-nocp.c
95
rename target/arm/{translate-neon.c.inc => translate-neon.c} (99%)
96
rename target/arm/{translate-vfp.c.inc => translate-vfp.c} (94%)
97
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
Deleted patch
1
From: Alex Bennée <alex.bennee@linaro.org>
2
1
3
A trailing _ makes all the difference to the rendered link.
4
5
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20210428131316.31390-1-alex.bennee@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
docs/system/arm/sbsa.rst | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/docs/system/arm/sbsa.rst b/docs/system/arm/sbsa.rst
14
index XXXXXXX..XXXXXXX 100644
15
--- a/docs/system/arm/sbsa.rst
16
+++ b/docs/system/arm/sbsa.rst
17
@@ -XXX,XX +XXX,XX @@ Arm Server Base System Architecture Reference board (``sbsa-ref``)
18
While the `virt` board is a generic board platform that doesn't match
19
any real hardware the `sbsa-ref` board intends to look like real
20
hardware. The `Server Base System Architecture
21
-<https://developer.arm.com/documentation/den0029/latest>` defines a
22
+<https://developer.arm.com/documentation/den0029/latest>`_ defines a
23
minimum base line of hardware support and importantly how the firmware
24
reports that to any operating system. It is a static system that
25
reports a very minimal DT to the firmware for non-discoverable
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
1
On some boards, SCC config register CFG0 bit 0 controls whether
1
cpu.h has a lot of #defines relating to CPU register fields.
2
parts of the board memory map are remapped. Support this with:
2
Most of these aren't actually used outside target/arm code,
3
* a device property scc-cfg0 so the board can specify the
3
so there's no point in cluttering up the cpu.h file with them.
4
initial value of the CFG0 register
4
Move some easy ones to internals.h.
5
* an outbound GPIO line which tracks bit 0 and which the board
6
can wire up to provide the remapping
7
5
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>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
11
Message-id: 20210504120912.23094-3-peter.maydell@linaro.org
12
---
10
---
13
include/hw/misc/mps2-scc.h | 9 +++++++++
11
target/arm/cpu.h | 128 -----------------------------------------
14
hw/misc/mps2-scc.c | 13 ++++++++++---
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 19 insertions(+), 3 deletions(-)
13
2 files changed, 128 insertions(+), 128 deletions(-)
16
14
17
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/misc/mps2-scc.h
17
--- a/target/arm/cpu.h
20
+++ b/include/hw/misc/mps2-scc.h
18
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
22
* + QOM property "scc-cfg4": value of the read-only CFG4 register
20
uint64_t ctl; /* Timer Control register */
23
* + QOM property "scc-aid": value of the read-only SCC_AID register
21
} ARMGenericTimer;
24
* + QOM property "scc-id": value of the read-only SCC_ID register
22
25
+ * + QOM property "scc-cfg0": reset value of the CFG0 register
23
-#define VTCR_NSW (1u << 29)
26
* + QOM property array "oscclk": reset values of the OSCCLK registers
24
-#define VTCR_NSA (1u << 30)
27
* (which are accessed via the SYS_CFG channel provided by this device)
25
-#define VSTCR_SW VTCR_NSW
28
+ * + named GPIO output "remap": this tracks the value of CFG0 register
26
-#define VSTCR_SA VTCR_NSA
29
+ * bit 0. Boards where this bit controls memory remapping should
27
-
30
+ * connect this GPIO line to a function performing that mapping.
28
/* Define a maximum sized vector register.
31
+ * Boards where bit 0 has no special function should leave the GPIO
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
32
+ * output disconnected.
30
* For 64-bit, this is a 2048-bit SVE register.
33
*/
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
34
#ifndef MPS2_SCC_H
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
35
#define MPS2_SCC_H
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
36
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
34
37
uint32_t num_oscclk;
35
-/* Bit definitions for CPACR (AArch32 only) */
38
uint32_t *oscclk;
36
-FIELD(CPACR, CP10, 20, 2)
39
uint32_t *oscclk_reset;
37
-FIELD(CPACR, CP11, 22, 2)
40
+ uint32_t cfg0_reset;
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
41
+
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
42
+ qemu_irq remap;
40
-FIELD(CPACR, ASEDIS, 31, 1)
43
};
41
-
44
42
-/* Bit definitions for CPACR_EL1 (AArch64 only) */
45
#endif
43
-FIELD(CPACR_EL1, ZEN, 16, 2)
46
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
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
47
index XXXXXXX..XXXXXXX 100644
183
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/misc/mps2-scc.c
184
--- a/target/arm/internals.h
49
+++ b/hw/misc/mps2-scc.c
185
+++ b/target/arm/internals.h
50
@@ -XXX,XX +XXX,XX @@
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
51
#include "qemu/bitops.h"
187
FIELD(DBGWCR, MASK, 24, 5)
52
#include "trace.h"
188
FIELD(DBGWCR, SSCE, 29, 1)
53
#include "hw/sysbus.h"
189
54
+#include "hw/irq.h"
190
+#define VTCR_NSW (1u << 29)
55
#include "migration/vmstate.h"
191
+#define VTCR_NSA (1u << 30)
56
#include "hw/registerfields.h"
192
+#define VSTCR_SW VTCR_NSW
57
#include "hw/misc/mps2-scc.h"
193
+#define VSTCR_SA VTCR_NSA
58
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
194
+
59
switch (offset) {
195
+/* Bit definitions for CPACR (AArch32 only) */
60
case A_CFG0:
196
+FIELD(CPACR, CP10, 20, 2)
61
/*
197
+FIELD(CPACR, CP11, 22, 2)
62
- * TODO on some boards bit 0 controls RAM remapping;
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
63
- * on others bit 1 is CPU_WAIT.
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
64
+ * On some boards bit 0 controls board-specific remapping;
200
+FIELD(CPACR, ASEDIS, 31, 1)
65
+ * we always reflect bit 0 in the 'remap' GPIO output line,
201
+
66
+ * and let the board wire it up or not as it chooses.
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
67
+ * TODO on some boards bit 1 is CPU_WAIT.
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
68
*/
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
69
s->cfg0 = value;
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
70
+ qemu_set_irq(s->remap, s->cfg0 & 1);
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
71
break;
207
+
72
case A_CFG1:
208
+/* Bit definitions for HCPTR (AArch32 only) */
73
s->cfg1 = value;
209
+FIELD(HCPTR, TCP10, 10, 1)
74
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
210
+FIELD(HCPTR, TCP11, 11, 1)
75
int i;
211
+FIELD(HCPTR, TASE, 15, 1)
76
212
+FIELD(HCPTR, TTA, 20, 1)
77
trace_mps2_scc_reset();
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
78
- s->cfg0 = 0;
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
79
+ s->cfg0 = s->cfg0_reset;
215
+
80
s->cfg1 = 0;
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
81
s->cfg2 = 0;
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
82
s->cfg5 = 0;
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
83
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_init(Object *obj)
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
84
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
85
memory_region_init_io(&s->iomem, obj, &mps2_scc_ops, s, "mps2-scc", 0x1000);
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
86
sysbus_init_mmio(sbd, &s->iomem);
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
87
+ qdev_init_gpio_out_named(DEVICE(obj), &s->remap, "remap", 1);
223
+FIELD(CPTR_EL2, TTA, 28, 1)
88
}
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
89
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
90
static void mps2_scc_realize(DeviceState *dev, Error **errp)
226
+
91
@@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = {
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
92
DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0),
228
+FIELD(CPTR_EL3, EZ, 8, 1)
93
DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
229
+FIELD(CPTR_EL3, TFP, 10, 1)
94
DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0),
230
+FIELD(CPTR_EL3, ESM, 12, 1)
95
+ /* Reset value for CFG0 register */
231
+FIELD(CPTR_EL3, TTA, 20, 1)
96
+ DEFINE_PROP_UINT32("scc-cfg0", MPS2SCC, cfg0_reset, 0),
232
+FIELD(CPTR_EL3, TAM, 30, 1)
97
/*
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
98
* These are the initial settings for the source clocks on the board.
234
+
99
* In hardware they can be configured via a config file read by the
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
100
--
321
--
101
2.20.1
322
2.34.1
102
323
103
324
diff view generated by jsdifflib
1
In tlbi_aa64_vae2is_write() the calculation
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_E2 : ARMMMUIdx_SE2,
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
pageaddr)
3
delivering the exception to EL2 with the wrong syndrome.
4
4
5
has the two arms of the ?: expression reversed. Fix the bug.
6
7
Fixes: b6ad6062f1e5
8
Reported-by: Rebecca Cran <rebecca@nuviainc.com>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
12
Reviewed-by: Rebecca Cran <rebecca@nuviainc.com>
13
Message-id: 20210420123106.10861-1-peter.maydell@linaro.org
14
---
8
---
15
target/arm/helper.c | 2 +-
9
target/arm/helper.c | 2 +-
16
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
17
11
18
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
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
14
--- a/target/arm/helper.c
21
+++ b/target/arm/helper.c
15
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
23
uint64_t pageaddr = sextract64(value << 12, 0, 56);
17
return CP_ACCESS_OK;
24
bool secure = arm_is_secure_below_el3(env);
18
}
25
int mask = secure ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2;
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
26
- int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_E2 : ARMMMUIdx_SE2,
20
- return CP_ACCESS_TRAP;
27
+ int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2,
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
28
pageaddr);
22
}
29
23
return CP_ACCESS_OK;
30
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
24
}
31
--
25
--
32
2.20.1
26
2.34.1
33
34
diff view generated by jsdifflib
1
The unallocated_encoding() function is the same in both
1
We prefer the FIELD macro over ad-hoc #defines for register bits;
2
translate-a64.c and translate.c; make the translate.c function global
2
switch CNTHCTL to that style before we add any more bits.
3
and drop the translate-a64.c version. To do this we need to also
4
share gen_exception_insn(), which currently exists in two slightly
5
different versions for A32 and A64: merge those into a single
6
function that can work for both.
7
8
This will be useful for splitting up translate.c, which will require
9
unallocated_encoding() to no longer be file-local. It's also
10
hopefully less confusing to have only one version of the function
11
rather than two.
12
3
13
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>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210430132740.10391-3-peter.maydell@linaro.org
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
16
---
8
---
17
target/arm/translate-a64.h | 2 --
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
18
target/arm/translate.h | 3 +++
10
target/arm/helper.c | 9 ++++-----
19
target/arm/translate-a64.c | 15 ---------------
11
2 files changed, 29 insertions(+), 7 deletions(-)
20
target/arm/translate.c | 14 +++++++++-----
21
4 files changed, 12 insertions(+), 22 deletions(-)
22
12
23
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate-a64.h
15
--- a/target/arm/internals.h
26
+++ b/target/arm/translate-a64.h
16
+++ b/target/arm/internals.h
27
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
28
#ifndef TARGET_ARM_TRANSLATE_A64_H
18
#define HSTR_TTEE (1 << 16)
29
#define TARGET_ARM_TRANSLATE_A64_H
19
#define HSTR_TJDBX (1 << 17)
30
20
31
-void unallocated_encoding(DisasContext *s);
21
-#define CNTHCTL_CNTVMASK (1 << 18)
22
-#define CNTHCTL_CNTPMASK (1 << 19)
23
+/*
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
25
+ * have different bit definitions, and EL1PCTEN might be
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
27
+ * disambiguate if necessary.
28
+ */
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
40
+FIELD(CNTHCTL, ECV, 12, 1)
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
47
+FIELD(CNTHCTL, CNTPMASK, 19, 1)
48
49
/* We use a few fake FSR values for internal purposes in M profile.
50
* M profile cores don't have A/R format FSRs, but currently our
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
56
* It is RES0 in Secure and NonSecure state.
57
*/
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
63
irqstate = 0;
64
}
65
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
{
68
ARMCPU *cpu = env_archcpu(env);
69
uint32_t oldval = env->cp15.cnthctl_el2;
32
-
70
-
33
#define unsupported_encoding(s, insn) \
71
raw_write(env, ri, value);
34
do { \
72
35
qemu_log_mask(LOG_UNIMP, \
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
36
diff --git a/target/arm/translate.h b/target/arm/translate.h
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
37
index XXXXXXX..XXXXXXX 100644
75
gt_update_irq(cpu, GTIMER_VIRT);
38
--- a/target/arm/translate.h
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
39
+++ b/target/arm/translate.h
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
40
@@ -XXX,XX +XXX,XX @@ void arm_free_cc(DisasCompare *cmp);
78
gt_update_irq(cpu, GTIMER_PHYS);
41
void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
42
void arm_gen_test_cc(int cc, TCGLabel *label);
43
MemOp pow2_align(unsigned i);
44
+void unallocated_encoding(DisasContext *s);
45
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
46
+ uint32_t syn, uint32_t target_el);
47
48
/* Return state of Alternate Half-precision flag, caller frees result */
49
static inline TCGv_i32 get_ahp_flag(void)
50
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-a64.c
53
+++ b/target/arm/translate-a64.c
54
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal_insn(DisasContext *s, uint64_t pc, int excp)
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
58
-static void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
59
- uint32_t syndrome, uint32_t target_el)
60
-{
61
- gen_a64_set_pc_im(pc);
62
- gen_exception(excp, syndrome, target_el);
63
- s->base.is_jmp = DISAS_NORETURN;
64
-}
65
-
66
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syndrome)
67
{
68
TCGv_i32 tcg_syn;
69
@@ -XXX,XX +XXX,XX @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
70
}
79
}
71
}
80
}
72
73
-void unallocated_encoding(DisasContext *s)
74
-{
75
- /* Unallocated and reserved encodings are uncategorized */
76
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
77
- default_exception_el(s));
78
-}
79
-
80
static void init_tmp_a64_array(DisasContext *s)
81
{
82
#ifdef CONFIG_DEBUG_TCG
83
diff --git a/target/arm/translate.c b/target/arm/translate.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/translate.c
86
+++ b/target/arm/translate.c
87
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
88
s->base.is_jmp = DISAS_NORETURN;
89
}
90
91
-static void gen_exception_insn(DisasContext *s, uint32_t pc, int excp,
92
- int syn, uint32_t target_el)
93
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
94
+ uint32_t syn, uint32_t target_el)
95
{
96
- gen_set_condexec(s);
97
- gen_set_pc_im(s, pc);
98
+ if (s->aarch64) {
99
+ gen_a64_set_pc_im(pc);
100
+ } else {
101
+ gen_set_condexec(s);
102
+ gen_set_pc_im(s, pc);
103
+ }
104
gen_exception(excp, syn, target_el);
105
s->base.is_jmp = DISAS_NORETURN;
106
}
107
@@ -XXX,XX +XXX,XX @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
108
s->base.is_jmp = DISAS_NORETURN;
109
}
110
111
-static void unallocated_encoding(DisasContext *s)
112
+void unallocated_encoding(DisasContext *s)
113
{
114
/* Unallocated and reserved encodings are uncategorized */
115
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
116
--
81
--
117
2.20.1
82
2.34.1
118
83
119
84
diff view generated by jsdifflib
1
Make dis-asm.h handle being included outside an 'extern "C"' block;
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
this allows us to remove the 'extern "C"' blocks that our two C++
2
This is not strictly architecturally required, but it is how we've
3
files that include it are using.
3
tended to implement registers more recently.
4
5
In particular, bits [19:18] are only present with FEAT_RME,
6
and bits [17:12] will only be present with FEAT_ECV.
4
7
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
7
---
11
---
8
include/disas/dis-asm.h | 12 ++++++++++--
12
target/arm/helper.c | 18 ++++++++++++++++++
9
disas/arm-a64.cc | 2 --
13
1 file changed, 18 insertions(+)
10
disas/nanomips.cpp | 2 --
11
3 files changed, 10 insertions(+), 6 deletions(-)
12
14
13
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/include/disas/dis-asm.h
17
--- a/target/arm/helper.c
16
+++ b/include/disas/dis-asm.h
18
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
18
#ifndef DISAS_DIS_ASM_H
20
{
19
#define DISAS_DIS_ASM_H
21
ARMCPU *cpu = env_archcpu(env);
20
22
uint32_t oldval = env->cp15.cnthctl_el2;
21
+#include "qemu/bswap.h"
23
+ uint32_t valid_mask =
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
26
+ R_CNTHCTL_EVNTEN_MASK |
27
+ R_CNTHCTL_EVNTDIR_MASK |
28
+ R_CNTHCTL_EVNTI_MASK |
29
+ R_CNTHCTL_EL0VTEN_MASK |
30
+ R_CNTHCTL_EL0PTEN_MASK |
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
32
+ R_CNTHCTL_EL1PTEN_MASK;
22
+
33
+
23
+#ifdef __cplusplus
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
24
+extern "C" {
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
25
+#endif
36
+ }
26
+
37
+
27
typedef void *PTR;
38
+ /* Clear RES0 bits */
28
typedef uint64_t bfd_vma;
39
+ value &= valid_mask;
29
typedef int64_t bfd_signed_vma;
30
@@ -XXX,XX +XXX,XX @@ bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size);
31
32
/* from libbfd */
33
34
-#include "qemu/bswap.h"
35
-
36
static inline bfd_vma bfd_getl64(const bfd_byte *addr)
37
{
38
return ldq_le_p(addr);
39
@@ -XXX,XX +XXX,XX @@ static inline bfd_vma bfd_getb16(const bfd_byte *addr)
40
41
typedef bool bfd_boolean;
42
43
+#ifdef __cplusplus
44
+}
45
+#endif
46
+
40
+
47
#endif /* DISAS_DIS_ASM_H */
41
raw_write(env, ri, value);
48
diff --git a/disas/arm-a64.cc b/disas/arm-a64.cc
42
49
index XXXXXXX..XXXXXXX 100644
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
50
--- a/disas/arm-a64.cc
51
+++ b/disas/arm-a64.cc
52
@@ -XXX,XX +XXX,XX @@
53
*/
54
55
#include "qemu/osdep.h"
56
-extern "C" {
57
#include "disas/dis-asm.h"
58
-}
59
60
#include "vixl/a64/disasm-a64.h"
61
62
diff --git a/disas/nanomips.cpp b/disas/nanomips.cpp
63
index XXXXXXX..XXXXXXX 100644
64
--- a/disas/nanomips.cpp
65
+++ b/disas/nanomips.cpp
66
@@ -XXX,XX +XXX,XX @@
67
*/
68
69
#include "qemu/osdep.h"
70
-extern "C" {
71
#include "disas/dis-asm.h"
72
-}
73
74
#include <cstring>
75
#include <stdexcept>
76
--
44
--
77
2.20.1
45
2.34.1
78
79
diff view generated by jsdifflib
1
Some of the constant expanders defined in translate.c are generically
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
useful and will be used by the separate C files for VFP and Neon once
2
* four new trap bits for various counter and timer registers
3
they are created; move the expander definitions to translate.h.
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.
15
16
In this commit we implement the trap handling and permit the new
17
CNTHCTL_EL2 bits to be written.
4
18
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210430132740.10391-2-peter.maydell@linaro.org
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
9
---
22
---
10
target/arm/translate.h | 24 ++++++++++++++++++++++++
23
target/arm/cpu-features.h | 5 ++++
11
target/arm/translate.c | 24 ------------------------
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
12
2 files changed, 24 insertions(+), 24 deletions(-)
25
2 files changed, 51 insertions(+), 5 deletions(-)
13
26
14
diff --git a/target/arm/translate.h b/target/arm/translate.h
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/target/arm/translate.h
29
--- a/target/arm/cpu-features.h
17
+++ b/target/arm/translate.h
30
+++ b/target/arm/cpu-features.h
18
@@ -XXX,XX +XXX,XX @@ extern TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
19
extern TCGv_i64 cpu_exclusive_addr;
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
20
extern TCGv_i64 cpu_exclusive_val;
33
}
21
34
22
+/*
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
23
+ * Constant expanders for the decoders.
24
+ */
25
+
26
+static inline int negate(DisasContext *s, int x)
27
+{
36
+{
28
+ return -x;
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
29
+}
38
+}
30
+
39
+
31
+static inline int plus_2(DisasContext *s, int x)
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
41
{
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
49
return CP_ACCESS_TRAP_EL2;
50
}
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ }
56
break;
57
}
58
return CP_ACCESS_OK;
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
60
}
61
}
62
}
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
87
{
88
if (arm_current_el(env) == 1) {
89
/* This must be a FEAT_NV access */
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
91
return CP_ACCESS_OK;
92
}
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
96
}
97
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
32
+{
100
+{
33
+ return x + 2;
101
+ if (arm_current_el(env) == 1) {
102
+ /* This must be a FEAT_NV access with NVx == 101 */
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
104
+ return CP_ACCESS_TRAP_EL2;
105
+ }
106
+ }
107
+ return e2h_access(env, ri, isread);
34
+}
108
+}
35
+
109
+
36
+static inline int times_2(DisasContext *s, int x)
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
111
+ bool isread)
37
+{
112
+{
38
+ return x * 2;
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);
39
+}
120
+}
40
+
121
+
41
+static inline int times_4(DisasContext *s, int x)
122
/* Test if system register redirection is to occur in the current state. */
42
+{
123
static bool redirect_for_e2h(CPUARMState *env)
43
+ return x * 4;
44
+}
45
+
46
static inline int arm_dc_feature(DisasContext *dc, int feature)
47
{
124
{
48
return (dc->features & (1ULL << feature)) != 0;
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
49
diff --git a/target/arm/translate.c b/target/arm/translate.c
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
50
index XXXXXXX..XXXXXXX 100644
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
51
--- a/target/arm/translate.c
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
52
+++ b/target/arm/translate.c
129
- .access = PL2_RW, .accessfn = e2h_access,
53
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
54
}
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
55
}
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
56
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
57
-/*
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
58
- * Constant expanders for the decoders.
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
59
- */
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
60
-
137
- .access = PL2_RW, .accessfn = e2h_access,
61
-static int negate(DisasContext *s, int x)
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
62
-{
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
63
- return -x;
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
64
-}
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
65
-
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
66
-static int plus_2(DisasContext *s, int x)
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
67
-{
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
68
- return x + 2;
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
69
-}
146
- .access = PL2_RW, .accessfn = e2h_access,
70
-
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
71
-static int times_2(DisasContext *s, int x)
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
72
-{
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
73
- return x * 2;
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
74
-}
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
75
-
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
76
-static int times_4(DisasContext *s, int x)
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
77
-{
154
- .access = PL2_RW, .accessfn = e2h_access,
78
- return x * 4;
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
79
-}
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
80
-
157
#endif
81
/* Flags for the disas_set_da_iss info argument:
158
};
82
* lower bits hold the Rt register number, higher bits are flags.
83
*/
84
--
159
--
85
2.20.1
160
2.34.1
86
87
diff view generated by jsdifflib
1
Both os-win32.h and os-posix.h include system header files. Instead
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
of having osdep.h include them inside its 'extern "C"' block, make
2
defined, which are "self-synchronized" views of the physical and
3
these headers handle that themselves, so that we don't include the
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
system headers inside 'extern "C"'.
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).
5
7
6
This doesn't fix any current problems, but it's conceptually the
8
For QEMU, all our system registers are self-synchronized, so we can
7
right way to handle system headers.
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
10
to the new register encodings.
11
12
This means we now implement all the functionality required for
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
8
14
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
11
---
18
---
12
include/qemu/osdep.h | 8 ++++----
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
13
include/sysemu/os-posix.h | 8 ++++++++
20
1 file changed, 43 insertions(+)
14
include/sysemu/os-win32.h | 8 ++++++++
15
3 files changed, 20 insertions(+), 4 deletions(-)
16
21
17
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
19
--- a/include/qemu/osdep.h
24
--- a/target/arm/helper.c
20
+++ b/include/qemu/osdep.h
25
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ QEMU_EXTERN_C int daemon(int, int);
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
22
*/
27
},
23
#include "glib-compat.h"
28
};
24
29
25
-#ifdef __cplusplus
30
+/*
26
-extern "C" {
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
27
-#endif
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
28
-
33
+ * so our implementations here are identical to the normal registers.
29
#ifdef _WIN32
34
+ */
30
#include "sysemu/os-win32.h"
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
31
#endif
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
32
@@ -XXX,XX +XXX,XX @@ extern "C" {
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
33
#include "sysemu/os-posix.h"
38
+ .accessfn = gt_vct_access,
34
#endif
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
35
40
+ },
36
+#ifdef __cplusplus
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
37
+extern "C" {
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
38
+#endif
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
+};
39
+
57
+
40
#include "qemu/typedefs.h"
58
#else
41
59
42
/*
60
/*
43
diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
44
index XXXXXXX..XXXXXXX 100644
62
},
45
--- a/include/sysemu/os-posix.h
63
};
46
+++ b/include/sysemu/os-posix.h
64
47
@@ -XXX,XX +XXX,XX @@
65
+/*
48
#include <sys/sysmacros.h>
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
49
#endif
67
+ * is exposed to userspace by Linux.
50
68
+ */
51
+#ifdef __cplusplus
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
52
+extern "C" {
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
53
+#endif
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
54
+
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
55
void os_set_line_buffering(void);
73
+ .readfn = gt_virt_cnt_read,
56
void os_set_proc_name(const char *s);
74
+ },
57
void os_setup_signal_handling(void);
75
+};
58
@@ -XXX,XX +XXX,XX @@ static inline void qemu_funlockfile(FILE *f)
59
funlockfile(f);
60
}
61
62
+#ifdef __cplusplus
63
+}
64
+#endif
65
+
76
+
66
#endif
77
#endif
67
diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
78
68
index XXXXXXX..XXXXXXX 100644
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
69
--- a/include/sysemu/os-win32.h
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
70
+++ b/include/sysemu/os-win32.h
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
71
@@ -XXX,XX +XXX,XX @@
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
72
#include <windows.h>
83
}
73
#include <ws2tcpip.h>
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
74
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
75
+#ifdef __cplusplus
86
+ }
76
+extern "C" {
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
77
+#endif
88
ARMCPRegInfo vapa_cp_reginfo[] = {
78
+
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
79
#if defined(_WIN64)
80
/* On w64, setjmp is implemented by _setjmp which needs a second parameter.
81
* If this parameter is NULL, longjump does no stack unwinding.
82
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags);
83
ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
84
struct sockaddr *addr, socklen_t *addrlen);
85
86
+#ifdef __cplusplus
87
+}
88
+#endif
89
+
90
#endif
91
--
90
--
92
2.20.1
91
2.34.1
93
94
diff view generated by jsdifflib
1
The functions vfp_load_reg32(), vfp_load_reg64(), vfp_store_reg32()
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
and vfp_store_reg64() are used only in translate-vfp.c.inc. Move
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
them to that file.
3
that it controls a hypervisor-adjustable offset made to the physical
4
counter and timer.
5
6
Implement the handling for this register, which includes control/trap
7
bits in SCR_EL3 and CNTHCTL_EL2.
4
8
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210430132740.10391-7-peter.maydell@linaro.org
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
9
---
12
---
10
target/arm/translate.c | 20 --------------------
13
target/arm/cpu-features.h | 5 +++
11
target/arm/translate-vfp.c.inc | 20 ++++++++++++++++++++
14
target/arm/cpu.h | 1 +
12
2 files changed, 20 insertions(+), 20 deletions(-)
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
13
18
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
21
--- a/target/arm/cpu-features.h
17
+++ b/target/arm/translate.c
22
+++ b/target/arm/cpu-features.h
18
@@ -XXX,XX +XXX,XX @@ static long vfp_reg_offset(bool dp, unsigned reg)
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
19
}
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
20
}
25
}
21
26
22
-static inline void vfp_load_reg64(TCGv_i64 var, int reg)
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
23
-{
24
- tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(true, reg));
25
-}
26
-
27
-static inline void vfp_store_reg64(TCGv_i64 var, int reg)
28
-{
29
- tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(true, reg));
30
-}
31
-
32
-static inline void vfp_load_reg32(TCGv_i32 var, int reg)
33
-{
34
- tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
35
-}
36
-
37
-static inline void vfp_store_reg32(TCGv_i32 var, int reg)
38
-{
39
- tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
40
-}
41
-
42
void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop)
43
{
44
long off = neon_element_offset(reg, ele, memop);
45
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate-vfp.c.inc
48
+++ b/target/arm/translate-vfp.c.inc
49
@@ -XXX,XX +XXX,XX @@
50
#include "decode-vfp.c.inc"
51
#include "decode-vfp-uncond.c.inc"
52
53
+static inline void vfp_load_reg64(TCGv_i64 var, int reg)
54
+{
28
+{
55
+ tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(true, reg));
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
56
+}
30
+}
57
+
31
+
58
+static inline void vfp_store_reg64(TCGv_i64 var, int reg)
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
33
{
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
40
uint64_t c14_cntkctl; /* Timer Control register */
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
63
}
64
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
59
+{
66
+{
60
+ tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(true, reg));
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;
61
+}
74
+}
62
+
75
+
63
+static inline void vfp_load_reg32(TCGv_i32 var, int reg)
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
64
+{
77
+{
65
+ tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
78
+ if (arm_current_el(env) >= 2) {
79
+ return 0;
80
+ }
81
+ return gt_phys_raw_cnt_offset(env);
66
+}
82
+}
67
+
83
+
68
+static inline void vfp_store_reg32(TCGv_i32 var, int reg)
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
85
{
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
88
* reset timer to when ISTATUS next has to change
89
*/
90
uint64_t offset = timeridx == GTIMER_VIRT ?
91
- cpu->env.cp15.cntvoff_el2 : 0;
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
102
}
103
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
112
}
113
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
case GTIMER_HYPVIRT:
117
offset = gt_virt_cnt_offset(env);
118
break;
119
+ case GTIMER_PHYS:
120
+ offset = gt_phys_cnt_offset(env);
121
+ break;
122
}
123
124
trace_arm_gt_tval_write(timeridx, value);
125
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
R_CNTHCTL_EL1NVVCT_MASK |
127
R_CNTHCTL_EVNTIS_MASK;
128
}
129
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
130
+ valid_mask |= R_CNTHCTL_ECV_MASK;
131
+ }
132
133
/* Clear RES0 bits */
134
value &= valid_mask;
135
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
136
},
137
};
138
139
+static CPAccessResult gt_cntpoff_access(CPUARMState *env,
140
+ const ARMCPRegInfo *ri,
141
+ bool isread)
69
+{
142
+{
70
+ tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
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;
71
+}
147
+}
72
+
148
+
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
150
+ uint64_t value)
151
+{
152
+ ARMCPU *cpu = env_archcpu(env);
153
+
154
+ trace_arm_gt_cntpoff_write(value);
155
+ raw_write(env, ri, value);
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
157
+}
158
+
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
164
+ .nv2_redirect_offset = 0x1a8,
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
166
+};
167
#else
168
73
/*
169
/*
74
* The imm8 encodes the sign bit, enough bits to represent an exponent in
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
75
* the range 01....1xx to 10....0xx, and the most significant 4 bits of
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
76
--
194
--
77
2.20.1
195
2.34.1
78
79
diff view generated by jsdifflib
1
Make bswap.h handle being included outside an 'extern "C"' block:
1
Enable all FEAT_ECV features on the 'max' CPU.
2
all system headers are included first, then all declarations are
3
put inside an 'extern "C"' block.
4
5
This requires a little rearrangement as currently we have an ifdef
6
ladder that has some system includes and some local declarations
7
or definitions, and we need to separate those out.
8
9
We want to do this because dis-asm.h includes bswap.h, dis-asm.h
10
may need to be included from C++ files, and system headers should
11
not be included within 'extern "C"' blocks.
12
2
13
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>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
15
---
7
---
16
include/qemu/bswap.h | 26 ++++++++++++++++++++++----
8
docs/system/arm/emulation.rst | 1 +
17
1 file changed, 22 insertions(+), 4 deletions(-)
9
target/arm/tcg/cpu64.c | 1 +
10
2 files changed, 2 insertions(+)
18
11
19
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/include/qemu/bswap.h
14
--- a/docs/system/arm/emulation.rst
22
+++ b/include/qemu/bswap.h
15
+++ b/docs/system/arm/emulation.rst
23
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
24
#ifndef BSWAP_H
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
25
#define BSWAP_H
18
- FEAT_DoubleFault (Double Fault Extension)
26
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
27
-#include "fpu/softfloat-types.h"
20
+- FEAT_ECV (Enhanced Counter Virtualization)
28
-
21
- FEAT_EPAC (Enhanced pointer authentication)
29
#ifdef CONFIG_MACHINE_BSWAP_H
22
- FEAT_ETS (Enhanced Translation Synchronization)
30
# include <sys/endian.h>
23
- FEAT_EVT (Enhanced Virtualization Traps)
31
# include <machine/bswap.h>
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
32
@@ -XXX,XX +XXX,XX @@
25
index XXXXXXX..XXXXXXX 100644
33
# include <endian.h>
26
--- a/target/arm/tcg/cpu64.c
34
#elif defined(CONFIG_BYTESWAP_H)
27
+++ b/target/arm/tcg/cpu64.c
35
# include <byteswap.h>
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
36
+#define BSWAP_FROM_BYTESWAP
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
37
+# else
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
38
+#define BSWAP_FROM_FALLBACKS
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
39
+#endif /* ! CONFIG_MACHINE_BSWAP_H */
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
40
33
cpu->isar.id_aa64mmfr0 = t;
41
+#ifdef __cplusplus
34
42
+extern "C" {
35
t = cpu->isar.id_aa64mmfr1;
43
+#endif
44
+
45
+#include "fpu/softfloat-types.h"
46
+
47
+#ifdef BSWAP_FROM_BYTESWAP
48
static inline uint16_t bswap16(uint16_t x)
49
{
50
return bswap_16(x);
51
@@ -XXX,XX +XXX,XX @@ static inline uint64_t bswap64(uint64_t x)
52
{
53
return bswap_64(x);
54
}
55
-# else
56
+#endif
57
+
58
+#ifdef BSWAP_FROM_FALLBACKS
59
static inline uint16_t bswap16(uint16_t x)
60
{
61
return (((x & 0x00ff) << 8) |
62
@@ -XXX,XX +XXX,XX @@ static inline uint64_t bswap64(uint64_t x)
63
((x & 0x00ff000000000000ULL) >> 40) |
64
((x & 0xff00000000000000ULL) >> 56));
65
}
66
-#endif /* ! CONFIG_MACHINE_BSWAP_H */
67
+#endif
68
+
69
+#undef BSWAP_FROM_BYTESWAP
70
+#undef BSWAP_FROM_FALLBACKS
71
72
static inline void bswap16s(uint16_t *s)
73
{
74
@@ -XXX,XX +XXX,XX @@ DO_STN_LDN_P(be)
75
#undef le_bswaps
76
#undef be_bswaps
77
78
+#ifdef __cplusplus
79
+}
80
+#endif
81
+
82
#endif /* BSWAP_H */
83
--
36
--
84
2.20.1
37
2.34.1
85
38
86
39
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Commit dfc388797cc4 ("hw/arm: xlnx: Set all boards' GEM 'phy-addr'
3
Features supported :
4
property value to 23") configured the PHY address for xilinx-zynq-a9
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
to 23. When trying to boot xilinx-zynq-a9 with zynq-zc702.dtb or
5
(except IDR, see below)
6
zynq-zc706.dtb, this results in the following error message when
6
- input mode : setting a pin in input mode "externally" (using input
7
trying to use the Ethernet interface.
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
8
12
9
macb e000b000.ethernet eth0: Could not attach PHY (-19)
13
Difference with the real GPIOs :
14
- Alternate Function and Analog mode aren't implemented :
15
pins in AF/Analog behave like pins in input mode
16
- floating pins stay at their last value
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
10
25
11
The devicetree files for ZC702 and ZC706 configure PHY address 7. The
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
12
documentation for the ZC702 and ZC706 evaluation boards suggest that the
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
13
PHY address is 7, not 23. Other boards use PHY address 0, 1, 3, or 7.
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
I was unable to find a documentation or a devicetree file suggesting
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
15
or using PHY address 23. The Ethernet interface starts working with
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
16
zynq-zc702.dtb and zynq-zc706.dtb when setting the PHY address to 7,
17
so let's use it.
18
19
Cc: Bin Meng <bin.meng@windriver.com>
20
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
21
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
22
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
23
Message-id: 20210504124140.1100346-1-linux@roeck-us.net
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
32
---
26
hw/arm/xilinx_zynq.c | 2 +-
33
MAINTAINERS | 1 +
27
1 file changed, 1 insertion(+), 1 deletion(-)
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
37
hw/gpio/Kconfig | 3 +
38
hw/gpio/meson.build | 1 +
39
hw/gpio/trace-events | 6 +
40
7 files changed, 559 insertions(+), 1 deletion(-)
41
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
42
create mode 100644 hw/gpio/stm32l4x5_gpio.c
28
43
29
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
44
diff --git a/MAINTAINERS b/MAINTAINERS
30
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/xilinx_zynq.c
46
--- a/MAINTAINERS
32
+++ b/hw/arm/xilinx_zynq.c
47
+++ b/MAINTAINERS
33
@@ -XXX,XX +XXX,XX @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
34
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
49
F: hw/misc/stm32l4x5_exti.c
35
qdev_set_nic_properties(dev, nd);
50
F: hw/misc/stm32l4x5_syscfg.c
36
}
51
F: hw/misc/stm32l4x5_rcc.c
37
- object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
52
+F: hw/gpio/stm32l4x5_gpio.c
38
+ object_property_set_int(OBJECT(dev), "phy-addr", 7, &error_abort);
53
F: include/hw/*/stm32l4x5_*.h
39
s = SYS_BUS_DEVICE(dev);
54
40
sysbus_realize_and_unref(s, &error_fatal);
55
B-L475E-IOT01A IoT Node
41
sysbus_mmio_map(s, 0, base);
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
57
index XXXXXXX..XXXXXXX 100644
58
--- a/docs/system/arm/b-l475e-iot01a.rst
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
62
- STM32L4x5 SYSCFG (System configuration controller)
63
- STM32L4x5 RCC (Reset and clock control)
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
65
66
Missing devices
67
"""""""""""""""
68
@@ -XXX,XX +XXX,XX @@ Missing devices
69
The B-L475E-IOT01A does *not* support the following devices:
70
71
- Serial ports (UART)
72
-- General-purpose I/Os (GPIO)
73
- Analog to Digital Converter (ADC)
74
- SPI controller
75
- Timer controller (TIMER)
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
77
new file mode 100644
78
index XXXXXXX..XXXXXXX
79
--- /dev/null
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
81
@@ -XXX,XX +XXX,XX @@
82
+/*
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
84
+ *
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
87
+ *
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
92
+ */
93
+
94
+/*
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
98
+ */
99
+
100
+#ifndef HW_STM32L4X5_GPIO_H
101
+#define HW_STM32L4X5_GPIO_H
102
+
103
+#include "hw/sysbus.h"
104
+#include "qom/object.h"
105
+
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
108
+
109
+#define GPIO_NUM_PINS 16
110
+
111
+struct Stm32l4x5GpioState {
112
+ SysBusDevice parent_obj;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ /* GPIO registers */
117
+ uint32_t moder;
118
+ uint32_t otyper;
119
+ uint32_t ospeedr;
120
+ uint32_t pupdr;
121
+ uint32_t idr;
122
+ uint32_t odr;
123
+ uint32_t lckr;
124
+ uint32_t afrl;
125
+ uint32_t afrh;
126
+ uint32_t ascr;
127
+
128
+ /* GPIO registers reset values */
129
+ uint32_t moder_reset;
130
+ uint32_t ospeedr_reset;
131
+ uint32_t pupdr_reset;
132
+
133
+ /*
134
+ * External driving of pins.
135
+ * The pins can be set externally through the device
136
+ * anonymous input GPIOs lines under certain conditions.
137
+ * The pin must not be in push-pull output mode,
138
+ * and can't be set high in open-drain mode.
139
+ * Pins driven externally and configured to
140
+ * output mode will in general be "disconnected"
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
142
+ */
143
+ uint16_t disconnected_pins;
144
+ uint16_t pins_connected_high;
145
+
146
+ char *name;
147
+ Clock *clk;
148
+ qemu_irq pin[GPIO_NUM_PINS];
149
+};
150
+
151
+#endif
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
153
new file mode 100644
154
index XXXXXXX..XXXXXXX
155
--- /dev/null
156
+++ b/hw/gpio/stm32l4x5_gpio.c
157
@@ -XXX,XX +XXX,XX @@
158
+/*
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
160
+ *
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
163
+ *
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
165
+ *
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
167
+ * See the COPYING file in the top-level directory.
168
+ */
169
+
170
+/*
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
174
+ */
175
+
176
+#include "qemu/osdep.h"
177
+#include "qemu/log.h"
178
+#include "hw/gpio/stm32l4x5_gpio.h"
179
+#include "hw/irq.h"
180
+#include "hw/qdev-clock.h"
181
+#include "hw/qdev-properties.h"
182
+#include "qapi/visitor.h"
183
+#include "qapi/error.h"
184
+#include "migration/vmstate.h"
185
+#include "trace.h"
186
+
187
+#define GPIO_MODER 0x00
188
+#define GPIO_OTYPER 0x04
189
+#define GPIO_OSPEEDR 0x08
190
+#define GPIO_PUPDR 0x0C
191
+#define GPIO_IDR 0x10
192
+#define GPIO_ODR 0x14
193
+#define GPIO_BSRR 0x18
194
+#define GPIO_LCKR 0x1C
195
+#define GPIO_AFRL 0x20
196
+#define GPIO_AFRH 0x24
197
+#define GPIO_BRR 0x28
198
+#define GPIO_ASCR 0x2C
199
+
200
+/* 0b11111111_11111111_00000000_00000000 */
201
+#define RESERVED_BITS_MASK 0xFFFF0000
202
+
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
204
+
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
206
+{
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
208
+}
209
+
210
+static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
211
+{
212
+ return extract32(s->pupdr, 2 * pin, 2) == 2;
213
+}
214
+
215
+static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
216
+{
217
+ return extract32(s->moder, 2 * pin, 2) == 1;
218
+}
219
+
220
+static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
221
+{
222
+ return extract32(s->otyper, pin, 1) == 1;
223
+}
224
+
225
+static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
226
+{
227
+ return extract32(s->otyper, pin, 1) == 0;
228
+}
229
+
230
+static void stm32l4x5_gpio_reset_hold(Object *obj)
231
+{
232
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
233
+
234
+ s->moder = s->moder_reset;
235
+ s->otyper = 0x00000000;
236
+ s->ospeedr = s->ospeedr_reset;
237
+ s->pupdr = s->pupdr_reset;
238
+ s->idr = 0x00000000;
239
+ s->odr = 0x00000000;
240
+ s->lckr = 0x00000000;
241
+ s->afrl = 0x00000000;
242
+ s->afrh = 0x00000000;
243
+ s->ascr = 0x00000000;
244
+
245
+ s->disconnected_pins = 0xFFFF;
246
+ s->pins_connected_high = 0x0000;
247
+ update_gpio_idr(s);
248
+}
249
+
250
+static void stm32l4x5_gpio_set(void *opaque, int line, int level)
251
+{
252
+ Stm32l4x5GpioState *s = opaque;
253
+ /*
254
+ * The pin isn't set if line is configured in output mode
255
+ * except if level is 0 and the output is open-drain.
256
+ * This way there will be no short-circuit prone situations.
257
+ */
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
260
+ line);
261
+ return;
262
+ }
263
+
264
+ s->disconnected_pins &= ~(1 << line);
265
+ if (level) {
266
+ s->pins_connected_high |= (1 << line);
267
+ } else {
268
+ s->pins_connected_high &= ~(1 << line);
269
+ }
270
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
271
+ s->pins_connected_high);
272
+ update_gpio_idr(s);
273
+}
274
+
275
+
276
+static void update_gpio_idr(Stm32l4x5GpioState *s)
277
+{
278
+ uint32_t new_idr_mask = 0;
279
+ uint32_t new_idr = s->odr;
280
+ uint32_t old_idr = s->idr;
281
+ int new_pin_state, old_pin_state;
282
+
283
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
284
+ if (is_output(s, i)) {
285
+ if (is_push_pull(s, i)) {
286
+ new_idr_mask |= (1 << i);
287
+ } else if (!(s->odr & (1 << i))) {
288
+ /* open-drain ODR 0 */
289
+ new_idr_mask |= (1 << i);
290
+ /* open-drain ODR 1 */
291
+ } else if (!(s->disconnected_pins & (1 << i)) &&
292
+ !(s->pins_connected_high & (1 << i))) {
293
+ /* open-drain ODR 1 with pin connected low */
294
+ new_idr_mask |= (1 << i);
295
+ new_idr &= ~(1 << i);
296
+ /* open-drain ODR 1 with unactive pin */
297
+ } else if (is_pull_up(s, i)) {
298
+ new_idr_mask |= (1 << i);
299
+ } else if (is_pull_down(s, i)) {
300
+ new_idr_mask |= (1 << i);
301
+ new_idr &= ~(1 << i);
302
+ }
303
+ /*
304
+ * The only case left is for open-drain ODR 1
305
+ * with unactive pin without pull-up or pull-down :
306
+ * the value is floating.
307
+ */
308
+ /* input or analog mode with connected pin */
309
+ } else if (!(s->disconnected_pins & (1 << i))) {
310
+ if (s->pins_connected_high & (1 << i)) {
311
+ /* pin high */
312
+ new_idr_mask |= (1 << i);
313
+ new_idr |= (1 << i);
314
+ } else {
315
+ /* pin low */
316
+ new_idr_mask |= (1 << i);
317
+ new_idr &= ~(1 << i);
318
+ }
319
+ /* input or analog mode with disconnected pin */
320
+ } else {
321
+ if (is_pull_up(s, i)) {
322
+ /* pull-up */
323
+ new_idr_mask |= (1 << i);
324
+ new_idr |= (1 << i);
325
+ } else if (is_pull_down(s, i)) {
326
+ /* pull-down */
327
+ new_idr_mask |= (1 << i);
328
+ new_idr &= ~(1 << i);
329
+ }
330
+ /*
331
+ * The only case left is for a disconnected pin
332
+ * without pull-up or pull-down :
333
+ * the value is floating.
334
+ */
335
+ }
336
+ }
337
+
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
340
+
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
342
+ if (new_idr_mask & (1 << i)) {
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
345
+ if (new_pin_state > old_pin_state) {
346
+ qemu_irq_raise(s->pin[i]);
347
+ } else if (new_pin_state < old_pin_state) {
348
+ qemu_irq_lower(s->pin[i]);
349
+ }
350
+ }
351
+ }
352
+}
353
+
354
+/*
355
+ * Return mask of pins that are both configured in output
356
+ * mode and externally driven (except pins in open-drain
357
+ * mode externally set to 0).
358
+ */
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
360
+{
361
+ uint32_t pins_to_disconnect = 0;
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
363
+ /* for each connected pin in output mode */
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
365
+ /* if either push-pull or high level */
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
367
+ pins_to_disconnect |= (1 << i);
368
+ qemu_log_mask(LOG_GUEST_ERROR,
369
+ "Line %d can't be driven externally\n",
370
+ i);
371
+ }
372
+ }
373
+ }
374
+ return pins_to_disconnect;
375
+}
376
+
377
+/*
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
379
+ */
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
381
+{
382
+ s->disconnected_pins |= lines;
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
384
+ s->pins_connected_high);
385
+ update_gpio_idr(s);
386
+}
387
+
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
389
+ const char *name, void *opaque, Error **errp)
390
+{
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
392
+ uint16_t value;
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
394
+ return;
395
+ }
396
+ disconnect_gpio_pins(s, value);
397
+}
398
+
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
400
+ const char *name, void *opaque, Error **errp)
401
+{
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
403
+}
404
+
405
+static void clock_freq_get(Object *obj, Visitor *v,
406
+ const char *name, void *opaque, Error **errp)
407
+{
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
411
+}
412
+
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
414
+ uint64_t val64, unsigned int size)
415
+{
416
+ Stm32l4x5GpioState *s = opaque;
417
+
418
+ uint32_t value = val64;
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
420
+
421
+ switch (addr) {
422
+ case GPIO_MODER:
423
+ s->moder = value;
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
425
+ qemu_log_mask(LOG_UNIMP,
426
+ "%s: Analog and AF modes aren't supported\n\
427
+ Analog and AF mode behave like input mode\n",
428
+ __func__);
429
+ return;
430
+ case GPIO_OTYPER:
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
433
+ return;
434
+ case GPIO_OSPEEDR:
435
+ qemu_log_mask(LOG_UNIMP,
436
+ "%s: Changing I/O output speed isn't supported\n\
437
+ I/O speed is already maximal\n",
438
+ __func__);
439
+ s->ospeedr = value;
440
+ return;
441
+ case GPIO_PUPDR:
442
+ s->pupdr = value;
443
+ update_gpio_idr(s);
444
+ return;
445
+ case GPIO_IDR:
446
+ qemu_log_mask(LOG_UNIMP,
447
+ "%s: GPIO->IDR is read-only\n",
448
+ __func__);
449
+ return;
450
+ case GPIO_ODR:
451
+ s->odr = value & ~RESERVED_BITS_MASK;
452
+ update_gpio_idr(s);
453
+ return;
454
+ case GPIO_BSRR: {
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
457
+ /* If both BSx and BRx are set, BSx has priority.*/
458
+ s->odr &= ~bits_to_reset;
459
+ s->odr |= bits_to_set;
460
+ update_gpio_idr(s);
461
+ return;
462
+ }
463
+ case GPIO_LCKR:
464
+ qemu_log_mask(LOG_UNIMP,
465
+ "%s: Locking port bits configuration isn't supported\n",
466
+ __func__);
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
468
+ return;
469
+ case GPIO_AFRL:
470
+ qemu_log_mask(LOG_UNIMP,
471
+ "%s: Alternate functions aren't supported\n",
472
+ __func__);
473
+ s->afrl = value;
474
+ return;
475
+ case GPIO_AFRH:
476
+ qemu_log_mask(LOG_UNIMP,
477
+ "%s: Alternate functions aren't supported\n",
478
+ __func__);
479
+ s->afrh = value;
480
+ return;
481
+ case GPIO_BRR: {
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
483
+ s->odr &= ~bits_to_reset;
484
+ update_gpio_idr(s);
485
+ return;
486
+ }
487
+ case GPIO_ASCR:
488
+ qemu_log_mask(LOG_UNIMP,
489
+ "%s: ADC function isn't supported\n",
490
+ __func__);
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
492
+ return;
493
+ default:
494
+ qemu_log_mask(LOG_GUEST_ERROR,
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
496
+ }
497
+}
498
+
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
500
+ unsigned int size)
501
+{
502
+ Stm32l4x5GpioState *s = opaque;
503
+
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
505
+
506
+ switch (addr) {
507
+ case GPIO_MODER:
508
+ return s->moder;
509
+ case GPIO_OTYPER:
510
+ return s->otyper;
511
+ case GPIO_OSPEEDR:
512
+ return s->ospeedr;
513
+ case GPIO_PUPDR:
514
+ return s->pupdr;
515
+ case GPIO_IDR:
516
+ return s->idr;
517
+ case GPIO_ODR:
518
+ return s->odr;
519
+ case GPIO_BSRR:
520
+ return 0;
521
+ case GPIO_LCKR:
522
+ return s->lckr;
523
+ case GPIO_AFRL:
524
+ return s->afrl;
525
+ case GPIO_AFRH:
526
+ return s->afrh;
527
+ case GPIO_BRR:
528
+ return 0;
529
+ case GPIO_ASCR:
530
+ return s->ascr;
531
+ default:
532
+ qemu_log_mask(LOG_GUEST_ERROR,
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
534
+ return 0;
535
+ }
536
+}
537
+
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
539
+ .read = stm32l4x5_gpio_read,
540
+ .write = stm32l4x5_gpio_write,
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
542
+ .impl = {
543
+ .min_access_size = 4,
544
+ .max_access_size = 4,
545
+ .unaligned = false,
546
+ },
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
552
+};
553
+
554
+static void stm32l4x5_gpio_init(Object *obj)
555
+{
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
557
+
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
559
+ TYPE_STM32L4X5_GPIO, 0x400);
560
+
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
562
+
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
565
+
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
567
+
568
+ object_property_add(obj, "disconnected-pins", "uint16",
569
+ disconnected_pins_get, disconnected_pins_set,
570
+ NULL, &s->disconnected_pins);
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
572
+ clock_freq_get, NULL, NULL, NULL);
573
+}
574
+
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
576
+{
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
578
+ if (!clock_has_source(s->clk)) {
579
+ error_setg(errp, "GPIO: clk input must be connected");
580
+ return;
581
+ }
582
+}
583
+
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
585
+ .name = TYPE_STM32L4X5_GPIO,
586
+ .version_id = 1,
587
+ .minimum_version_id = 1,
588
+ .fields = (VMStateField[]){
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
601
+ VMSTATE_END_OF_LIST()
602
+ }
603
+};
604
+
605
+static Property stm32l4x5_gpio_properties[] = {
606
+ DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
607
+ DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
608
+ DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
609
+ DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
610
+ DEFINE_PROP_END_OF_LIST(),
611
+};
612
+
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
614
+{
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
617
+
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
620
+ dc->realize = stm32l4x5_gpio_realize;
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
622
+}
623
+
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
625
+ {
626
+ .name = TYPE_STM32L4X5_GPIO,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
631
+ },
632
+};
633
+
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
636
index XXXXXXX..XXXXXXX 100644
637
--- a/hw/gpio/Kconfig
638
+++ b/hw/gpio/Kconfig
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
640
641
config SIFIVE_GPIO
642
bool
643
+
644
+config STM32L4X5_GPIO
645
+ bool
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
647
index XXXXXXX..XXXXXXX 100644
648
--- a/hw/gpio/meson.build
649
+++ b/hw/gpio/meson.build
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
651
'bcm2835_gpio.c',
652
'bcm2838_gpio.c'
653
))
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
658
index XXXXXXX..XXXXXXX 100644
659
--- a/hw/gpio/trace-events
660
+++ b/hw/gpio/trace-events
661
@@ -XXX,XX +XXX,XX @@ sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " val
662
# aspeed_gpio.c
663
aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
664
aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
665
+
666
+# stm32l4x5_gpio.c
667
+stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
668
+stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
669
+stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
670
+stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
42
--
671
--
43
2.20.1
672
2.34.1
44
673
45
674
diff view generated by jsdifflib
1
The AN524 FPGA image supports two memory maps, which differ in where
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
the QSPI and BRAM are. In the default map, the BRAM is at
2
3
0x0000_0000, and the QSPI at 0x2800_0000. In the second map, they
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
are the other way around.
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
In hardware, the initial mapping can be selected by the user by
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
writing either "REMAP: BRAM" (the default) or "REMAP: QSPI" in the
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
board configuration file. The board config file is acted on by the
9
"Motherboard Configuration Controller", which is an entirely separate
10
microcontroller on the dev board but outside the FPGA.
11
12
The guest can also dynamically change the mapping via the SCC
13
CFG_REG0 register.
14
15
Implement this functionality for QEMU, using a machine property
16
"remap" with valid values "BRAM" and "QSPI" to allow the user to set
17
the initial mapping, in the same way they can on the FPGA, and
18
wiring up the bit from the SCC register to also switch the mapping.
19
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Message-id: 20210504120912.23094-4-peter.maydell@linaro.org
24
---
9
---
25
docs/system/arm/mps2.rst | 10 ++++
10
include/hw/arm/stm32l4x5_soc.h | 2 +
26
hw/arm/mps2-tz.c | 108 ++++++++++++++++++++++++++++++++++++++-
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
27
2 files changed, 117 insertions(+), 1 deletion(-)
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
28
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
29
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
14
hw/misc/stm32l4x5_syscfg.c | 1 +
30
index XXXXXXX..XXXXXXX 100644
15
hw/arm/Kconfig | 3 +-
31
--- a/docs/system/arm/mps2.rst
16
6 files changed, 63 insertions(+), 18 deletions(-)
32
+++ b/docs/system/arm/mps2.rst
17
33
@@ -XXX,XX +XXX,XX @@ Differences between QEMU and real hardware:
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
34
flash, but only as simple ROM, so attempting to rewrite the flash
19
index XXXXXXX..XXXXXXX 100644
35
from the guest will fail
20
--- a/include/hw/arm/stm32l4x5_soc.h
36
- QEMU does not model the USB controller in MPS3 boards
21
+++ b/include/hw/arm/stm32l4x5_soc.h
37
+
22
@@ -XXX,XX +XXX,XX @@
38
+Machine-specific options
23
#include "hw/misc/stm32l4x5_syscfg.h"
39
+""""""""""""""""""""""""
24
#include "hw/misc/stm32l4x5_exti.h"
40
+
25
#include "hw/misc/stm32l4x5_rcc.h"
41
+The following machine-specific options are supported:
26
+#include "hw/gpio/stm32l4x5_gpio.h"
42
+
27
#include "qom/object.h"
43
+remap
28
44
+ Supported for ``mps3-an524`` only.
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
45
+ Set ``BRAM``/``QSPI`` to select the initial memory mapping. The
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
46
+ default is ``BRAM``.
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
47
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
32
Stm32l4x5SyscfgState syscfg;
48
index XXXXXXX..XXXXXXX 100644
33
Stm32l4x5RccState rcc;
49
--- a/hw/arm/mps2-tz.c
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
50
+++ b/hw/arm/mps2-tz.c
35
51
@@ -XXX,XX +XXX,XX @@
36
MemoryRegion sram1;
52
#include "hw/boards.h"
37
MemoryRegion sram2;
53
#include "exec/address-spaces.h"
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
42
@@ -XXX,XX +XXX,XX @@
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
45
46
+#define NUM_GPIOS 8
47
#define GPIO_NUM_PINS 16
48
49
struct Stm32l4x5GpioState {
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
54
@@ -XXX,XX +XXX,XX @@
55
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 @@
54
#include "sysemu/sysemu.h"
73
#include "sysemu/sysemu.h"
55
+#include "sysemu/reset.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"
56
#include "hw/misc/unimp.h"
78
#include "hw/misc/unimp.h"
57
#include "hw/char/cmsdk-apb-uart.h"
79
58
#include "hw/timer/cmsdk-apb-timer.h"
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
59
@@ -XXX,XX +XXX,XX @@
81
16, 35, 36, 37, 38,
60
#include "hw/core/split-irq.h"
61
#include "hw/qdev-clock.h"
62
#include "qom/object.h"
63
+#include "hw/irq.h"
64
65
#define MPS2TZ_NUMIRQ_MAX 96
66
#define MPS2TZ_RAM_MAX 5
67
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
68
SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX];
69
Clock *sysclk;
70
Clock *s32kclk;
71
+
72
+ bool remap;
73
+ qemu_irq remap_irq;
74
};
82
};
75
83
76
#define TYPE_MPS2TZ_MACHINE "mps2tz"
84
+static const struct {
77
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an505_raminfo[] = { {
85
+ uint32_t addr;
78
},
86
+ uint32_t moder_reset;
79
};
87
+ uint32_t ospeedr_reset;
80
88
+ uint32_t pupdr_reset;
81
+/*
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
82
+ * Note that the addresses and MPC numbering here should match up
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
83
+ * with those used in remap_memory(), which can swap the BRAM and QSPI.
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
84
+ */
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
85
static const RAMInfo an524_raminfo[] = { {
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
86
.name = "bram",
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
87
.base = 0x00000000,
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
88
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
89
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
90
object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC);
98
+};
91
sccdev = DEVICE(scc);
99
+
92
+ qdev_prop_set_uint32(sccdev, "scc-cfg0", mms->remap ? 1 : 0);
100
static void stm32l4x5_soc_initfn(Object *obj)
93
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
101
{
94
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
95
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
96
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
104
}
97
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
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
+ }
98
}
112
}
99
113
100
+static hwaddr boot_mem_base(MPS2TZMachineState *mms)
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
101
+{
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
102
+ /*
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
103
+ * Return the canonical address of the block which will be mapped
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
104
+ * at address 0x0 (i.e. where the vector table is).
118
MemoryRegion *system_memory = get_system_memory();
105
+ * This is usually 0, but if the AN524 alternate memory map is
119
- DeviceState *armv7m;
106
+ * enabled it will be the base address of the QSPI block.
120
+ DeviceState *armv7m, *dev;
107
+ */
121
SysBusDevice *busdev;
108
+ return mms->remap ? 0x28000000 : 0;
122
+ uint32_t pin_index;
109
+}
123
110
+
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
111
+static void remap_memory(MPS2TZMachineState *mms, int map)
125
sc->flash_size, errp)) {
112
+{
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
113
+ /*
127
return;
114
+ * Remap the memory for the AN524. 'map' is the value of
128
}
115
+ * SCC CFG_REG0 bit 0, i.e. 0 for the default map and 1
129
116
+ * for the "option 1" mapping where QSPI is at address 0.
130
+ /* GPIOs */
117
+ *
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
118
+ * Effectively we need to swap around the "upstream" ends of
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
119
+ * MPC 0 and MPC 1.
133
+ dev = DEVICE(&s->gpio[i]);
120
+ */
134
+ qdev_prop_set_string(dev, "name", name);
121
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
135
+ qdev_prop_set_uint32(dev, "mode-reset",
122
+ int i;
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
123
+
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
124
+ if (mmc->fpga_type != FPGA_AN524) {
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
125
+ return;
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
142
+ g_free(name);
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
146
+ if (!sysbus_realize(busdev, errp)) {
147
+ return;
148
+ }
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
126
+ }
150
+ }
127
+
151
+
128
+ memory_region_transaction_begin();
152
/* System configuration controller */
129
+ for (i = 0; i < 2; i++) {
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
130
+ TZMPC *mpc = &mms->mpc[i];
154
if (!sysbus_realize(busdev, errp)) {
131
+ MemoryRegion *upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
155
return;
132
+ hwaddr addr = (i ^ map) ? 0x28000000 : 0;
156
}
133
+
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
134
+ memory_region_set_address(upstream, addr);
158
- /*
159
- * TODO: when the GPIO device is implemented, connect it
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
161
- * GPIO_NUM_PINS.
162
- */
163
+
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
166
+ pin_index = GPIO_NUM_PINS * i + j;
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
169
+ pin_index));
170
+ }
135
+ }
171
+ }
136
+ memory_region_transaction_commit();
172
137
+}
173
/* EXTI device */
138
+
174
busdev = SYS_BUS_DEVICE(&s->exti);
139
+static void remap_irq_fn(void *opaque, int n, int level)
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
140
+{
141
+ MPS2TZMachineState *mms = opaque;
142
+
143
+ remap_memory(mms, level);
144
+}
145
+
146
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
147
const char *name, hwaddr size,
148
const int *irqs)
149
@@ -XXX,XX +XXX,XX @@ static uint32_t boot_ram_size(MPS2TZMachineState *mms)
150
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
151
152
for (p = mmc->raminfo; p->name; p++) {
153
- if (p->base == 0) {
154
+ if (p->base == boot_mem_base(mms)) {
155
return p->size;
156
}
176
}
157
}
177
}
158
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
178
159
179
- for (unsigned i = 0; i < 16; i++) {
160
create_non_mpc_ram(mms);
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
161
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
162
+ if (mmc->fpga_type == FPGA_AN524) {
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
163
+ /*
183
}
164
+ * Connect the line from the SCC so that we can remap when the
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
165
+ * guest updates that register.
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
166
+ */
186
167
+ mms->remap_irq = qemu_allocate_irq(remap_irq_fn, mms, 0);
187
/* AHB2 BUS */
168
+ qdev_connect_gpio_out_named(DEVICE(&mms->scc), "remap", 0,
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
169
+ mms->remap_irq);
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
170
+ }
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
171
+
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
172
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
173
boot_ram_size(mms));
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
174
}
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
175
@@ -XXX,XX +XXX,XX @@ static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
176
*iregion = region;
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
177
}
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
178
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
179
+static char *mps2_get_remap(Object *obj, Error **errp)
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
180
+{
200
index XXXXXXX..XXXXXXX 100644
181
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj);
201
--- a/hw/misc/stm32l4x5_syscfg.c
182
+ const char *val = mms->remap ? "QSPI" : "BRAM";
202
+++ b/hw/misc/stm32l4x5_syscfg.c
183
+ return g_strdup(val);
203
@@ -XXX,XX +XXX,XX @@
184
+}
204
#include "hw/irq.h"
185
+
205
#include "migration/vmstate.h"
186
+static void mps2_set_remap(Object *obj, const char *value, Error **errp)
206
#include "hw/misc/stm32l4x5_syscfg.h"
187
+{
207
+#include "hw/gpio/stm32l4x5_gpio.h"
188
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj);
208
189
+
209
#define SYSCFG_MEMRMP 0x00
190
+ if (!strcmp(value, "BRAM")) {
210
#define SYSCFG_CFGR1 0x04
191
+ mms->remap = false;
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
192
+ } else if (!strcmp(value, "QSPI")) {
212
index XXXXXXX..XXXXXXX 100644
193
+ mms->remap = true;
213
--- a/hw/arm/Kconfig
194
+ } else {
214
+++ b/hw/arm/Kconfig
195
+ error_setg(errp, "Invalid remap value");
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
196
+ error_append_hint(errp, "Valid values are BRAM and QSPI.\n");
216
bool
197
+ }
217
select ARM_V7M
198
+}
218
select OR_IRQ
199
+
219
- select STM32L4X5_SYSCFG
200
+static void mps2_machine_reset(MachineState *machine)
220
select STM32L4X5_EXTI
201
+{
221
+ select STM32L4X5_SYSCFG
202
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
222
select STM32L4X5_RCC
203
+
223
+ select STM32L4X5_GPIO
204
+ /*
224
205
+ * Set the initial memory mapping before triggering the reset of
225
config XLNX_ZYNQMP_ARM
206
+ * the rest of the system, so that the guest image loader and CPU
226
bool
207
+ * reset see the correct mapping.
208
+ */
209
+ remap_memory(mms, mms->remap);
210
+ qemu_devices_reset();
211
+}
212
+
213
static void mps2tz_class_init(ObjectClass *oc, void *data)
214
{
215
MachineClass *mc = MACHINE_CLASS(oc);
216
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
217
218
mc->init = mps2tz_common_init;
219
+ mc->reset = mps2_machine_reset;
220
iic->check = mps2_tz_idau_check;
221
}
222
223
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
224
mmc->raminfo = an524_raminfo;
225
mmc->armsse_type = TYPE_SSE200;
226
mps2tz_set_default_ram_info(mmc);
227
+
228
+ object_class_property_add_str(oc, "remap", mps2_get_remap, mps2_set_remap);
229
+ object_class_property_set_description(oc, "remap",
230
+ "Set memory mapping. Valid values "
231
+ "are BRAM (default) and QSPI.");
232
}
233
234
static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
235
--
227
--
236
2.20.1
228
2.34.1
237
229
238
230
diff view generated by jsdifflib
1
We want to split out the .c.inc files which are currently included
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
into translate.c so they are separate compilation units. To do this
3
we need to make some functions which are currently file-local to
4
translate.c have global scope; create a translate-a32.h paralleling
5
the existing translate-a64.h as a place for these declarations to
6
live, so that code moved into the new compilation units can call
7
them.
8
2
9
The functions made global here are those required by the
3
The testcase contains :
10
m-nocp.decode functions, except that I have converted the whole
4
- `test_idr_reset_value()` :
11
family of {read,write}_neon_element* and also both the load_cpu and
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
12
store_cpu functions for consistency, even though m-nocp only wants a
6
- `test_gpio_output_mode()` :
13
few functions from each.
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.
14
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
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20210430132740.10391-4-peter.maydell@linaro.org
18
---
30
---
19
target/arm/translate-a32.h | 57 ++++++++++++++++++++++++++++++++++
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
20
target/arm/translate.c | 39 +++++------------------
32
tests/qtest/meson.build | 3 +-
21
target/arm/translate-vfp.c.inc | 2 +-
33
2 files changed, 553 insertions(+), 1 deletion(-)
22
3 files changed, 65 insertions(+), 33 deletions(-)
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
23
create mode 100644 target/arm/translate-a32.h
24
35
25
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
26
new file mode 100644
37
new file mode 100644
27
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
28
--- /dev/null
39
--- /dev/null
29
+++ b/target/arm/translate-a32.h
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
30
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
31
+/*
42
+/*
32
+ * AArch32 translation, common definitions.
43
+ * QTest testcase for STM32L4x5_GPIO
33
+ *
44
+ *
34
+ * Copyright (c) 2021 Linaro, Ltd.
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
35
+ *
47
+ *
36
+ * This library is free software; you can redistribute it and/or
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
37
+ * modify it under the terms of the GNU Lesser General Public
49
+ * See the COPYING file in the top-level directory.
38
+ * License as published by the Free Software Foundation; either
39
+ * version 2.1 of the License, or (at your option) any later version.
40
+ *
41
+ * This library is distributed in the hope that it will be useful,
42
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
43
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44
+ * Lesser General Public License for more details.
45
+ *
46
+ * You should have received a copy of the GNU Lesser General Public
47
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
48
+ */
50
+ */
49
+
51
+
50
+#ifndef TARGET_ARM_TRANSLATE_A64_H
52
+#include "qemu/osdep.h"
51
+#define TARGET_ARM_TRANSLATE_A64_H
53
+#include "libqtest-single.h"
52
+
54
+
53
+void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
55
+#define GPIO_BASE_ADDR 0x48000000
54
+void arm_gen_condlabel(DisasContext *s);
56
+#define GPIO_SIZE 0x400
55
+bool vfp_access_check(DisasContext *s);
57
+#define NUM_GPIOS 8
56
+void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
58
+#define NUM_GPIO_PINS 16
57
+void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
59
+
58
+void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
60
+#define GPIO_A 0x48000000
59
+void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop);
61
+#define GPIO_B 0x48000400
60
+
62
+#define GPIO_C 0x48000800
61
+static inline TCGv_i32 load_cpu_offset(int offset)
63
+#define GPIO_D 0x48000C00
62
+{
64
+#define GPIO_E 0x48001000
63
+ TCGv_i32 tmp = tcg_temp_new_i32();
65
+#define GPIO_F 0x48001400
64
+ tcg_gen_ld_i32(tmp, cpu_env, offset);
66
+#define GPIO_G 0x48001800
65
+ return tmp;
67
+#define GPIO_H 0x48001C00
66
+}
68
+
67
+
69
+#define MODER 0x00
68
+#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
70
+#define OTYPER 0x04
69
+
71
+#define PUPDR 0x0C
70
+static inline void store_cpu_offset(TCGv_i32 var, int offset)
72
+#define IDR 0x10
71
+{
73
+#define ODR 0x14
72
+ tcg_gen_st_i32(var, cpu_env, offset);
74
+#define BSRR 0x18
73
+ tcg_temp_free_i32(var);
75
+#define BRR 0x28
74
+}
76
+
75
+
77
+#define MODER_INPUT 0
76
+#define store_cpu_field(var, name) \
78
+#define MODER_OUTPUT 1
77
+ store_cpu_offset(var, offsetof(CPUARMState, name))
79
+
78
+
80
+#define PUPDR_NONE 0
79
+/* Create a new temporary and set it to the value of a CPU register. */
81
+#define PUPDR_PULLUP 1
80
+static inline TCGv_i32 load_reg(DisasContext *s, int reg)
82
+#define PUPDR_PULLDOWN 2
81
+{
83
+
82
+ TCGv_i32 tmp = tcg_temp_new_i32();
84
+#define OTYPER_PUSH_PULL 0
83
+ load_reg_var(s, tmp, reg);
85
+#define OTYPER_OPEN_DRAIN 1
84
+ return tmp;
86
+
85
+}
87
+const uint32_t moder_reset[NUM_GPIOS] = {
86
+
88
+ 0xABFFFFFF,
87
+#endif
89
+ 0xFFFFFEBF,
88
diff --git a/target/arm/translate.c b/target/arm/translate.c
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
89
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/translate.c
595
--- a/tests/qtest/meson.build
91
+++ b/target/arm/translate.c
596
+++ b/tests/qtest/meson.build
92
@@ -XXX,XX +XXX,XX @@
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
93
#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
598
qtests_stm32l4x5 = \
94
599
['stm32l4x5_exti-test',
95
#include "translate.h"
600
'stm32l4x5_syscfg-test',
96
+#include "translate-a32.h"
601
- 'stm32l4x5_rcc-test']
97
602
+ 'stm32l4x5_rcc-test',
98
#if defined(CONFIG_USER_ONLY)
603
+ 'stm32l4x5_gpio-test']
99
#define IS_USER(s) 1
604
100
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
605
qtests_arm = \
101
}
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
102
103
/* Generate a label used for skipping this instruction */
104
-static void arm_gen_condlabel(DisasContext *s)
105
+void arm_gen_condlabel(DisasContext *s)
106
{
107
if (!s->condjmp) {
108
s->condlabel = gen_new_label();
109
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
110
}
111
}
112
113
-static inline TCGv_i32 load_cpu_offset(int offset)
114
-{
115
- TCGv_i32 tmp = tcg_temp_new_i32();
116
- tcg_gen_ld_i32(tmp, cpu_env, offset);
117
- return tmp;
118
-}
119
-
120
-#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
121
-
122
-static inline void store_cpu_offset(TCGv_i32 var, int offset)
123
-{
124
- tcg_gen_st_i32(var, cpu_env, offset);
125
- tcg_temp_free_i32(var);
126
-}
127
-
128
-#define store_cpu_field(var, name) \
129
- store_cpu_offset(var, offsetof(CPUARMState, name))
130
-
131
/* The architectural value of PC. */
132
static uint32_t read_pc(DisasContext *s)
133
{
134
@@ -XXX,XX +XXX,XX @@ static uint32_t read_pc(DisasContext *s)
135
}
136
137
/* Set a variable to the value of a CPU register. */
138
-static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
139
+void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
140
{
141
if (reg == 15) {
142
tcg_gen_movi_i32(var, read_pc(s));
143
@@ -XXX,XX +XXX,XX @@ static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
144
}
145
}
146
147
-/* Create a new temporary and set it to the value of a CPU register. */
148
-static inline TCGv_i32 load_reg(DisasContext *s, int reg)
149
-{
150
- TCGv_i32 tmp = tcg_temp_new_i32();
151
- load_reg_var(s, tmp, reg);
152
- return tmp;
153
-}
154
-
155
/*
156
* Create a new temp, REG + OFS, except PC is ALIGN(PC, 4).
157
* This is used for load/store for which use of PC implies (literal),
158
@@ -XXX,XX +XXX,XX @@ static inline void vfp_store_reg32(TCGv_i32 var, int reg)
159
tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
160
}
161
162
-static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop)
163
+void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop)
164
{
165
long off = neon_element_offset(reg, ele, memop);
166
167
@@ -XXX,XX +XXX,XX @@ static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop)
168
}
169
}
170
171
-static void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop)
172
+void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop)
173
{
174
long off = neon_element_offset(reg, ele, memop);
175
176
@@ -XXX,XX +XXX,XX @@ static void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop)
177
}
178
}
179
180
-static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop)
181
+void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop)
182
{
183
long off = neon_element_offset(reg, ele, memop);
184
185
@@ -XXX,XX +XXX,XX @@ static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop)
186
}
187
}
188
189
-static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
190
+void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
191
{
192
long off = neon_element_offset(reg, ele, memop);
193
194
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
195
index XXXXXXX..XXXXXXX 100644
196
--- a/target/arm/translate-vfp.c.inc
197
+++ b/target/arm/translate-vfp.c.inc
198
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
199
* The most usual kind of VFP access check, for everything except
200
* FMXR/FMRX to the always-available special registers.
201
*/
202
-static bool vfp_access_check(DisasContext *s)
203
+bool vfp_access_check(DisasContext *s)
204
{
205
return full_vfp_access_check(s, false);
206
}
207
--
607
--
208
2.20.1
608
2.34.1
209
609
210
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
These three features are already enabled by TCG, but are missing
3
While the 8-bit input elements are sequential in the input vector,
4
their hwcap bits. Update HWCAP2 from linux v5.12.
4
the 32-bit output elements are not sequential in the output matrix.
5
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
Cc: qemu-stable@nongnu.org (for 6.0.1)
6
7
Buglink: https://bugs.launchpad.net/bugs/1926044
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: 20210427214108.88503-1-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
linux-user/elfload.c | 13 +++++++++++++
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
13
1 file changed, 13 insertions(+)
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
14
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.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/linux-user/elfload.c
25
--- a/target/arm/tcg/sme_helper.c
18
+++ b/linux-user/elfload.c
26
+++ b/target/arm/tcg/sme_helper.c
19
@@ -XXX,XX +XXX,XX @@ enum {
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
20
ARM_HWCAP2_A64_SVESM4 = 1 << 6,
28
}
21
ARM_HWCAP2_A64_FLAGM2 = 1 << 7,
22
ARM_HWCAP2_A64_FRINT = 1 << 8,
23
+ ARM_HWCAP2_A64_SVEI8MM = 1 << 9,
24
+ ARM_HWCAP2_A64_SVEF32MM = 1 << 10,
25
+ ARM_HWCAP2_A64_SVEF64MM = 1 << 11,
26
+ ARM_HWCAP2_A64_SVEBF16 = 1 << 12,
27
+ ARM_HWCAP2_A64_I8MM = 1 << 13,
28
+ ARM_HWCAP2_A64_BF16 = 1 << 14,
29
+ ARM_HWCAP2_A64_DGH = 1 << 15,
30
+ ARM_HWCAP2_A64_RNG = 1 << 16,
31
+ ARM_HWCAP2_A64_BTI = 1 << 17,
32
+ ARM_HWCAP2_A64_MTE = 1 << 18,
33
};
34
35
#define ELF_HWCAP get_elf_hwcap()
36
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap2(void)
37
GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
38
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
39
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
40
+ GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
41
+ GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
42
+ GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
43
44
return hwcaps;
45
}
29
}
30
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
34
+ uint8_t *pn, uint8_t *pm,
35
+ uint32_t desc, IMOPFn32 *fn)
36
+{
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
38
+ bool neg = simd_data(desc);
39
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
41
- uint8_t *pn, uint8_t *pm,
42
- uint32_t desc, IMOPFn *fn)
43
+ for (row = 0; row < oprsz; ++row) {
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
46
+ uint32_t n = zn[H4(row)];
47
+
48
+ for (col = 0; col < oprsz; ++col) {
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
50
+ uint32_t *a = &za_row[H4(col)];
51
+
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
53
+ }
54
+ }
55
+}
56
+
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
59
+ uint8_t *pn, uint8_t *pm,
60
+ uint32_t desc, IMOPFn64 *fn)
61
{
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
63
bool neg = simd_data(desc);
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
65
}
66
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
70
{ \
71
- uint32_t sum0 = 0, sum1 = 0; \
72
+ uint32_t sum = 0; \
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
74
n &= expand_pred_b(p); \
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
83
- if (neg) { \
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
85
- } else { \
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
87
- } \
88
- return ((uint64_t)sum1 << 32) | sum0; \
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
93
+ return neg ? a - sum : a + sum; \
94
}
95
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
100
101
-#define DEF_IMOPH(NAME) \
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
103
- void *vpm, uint32_t desc) \
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
105
+#define DEF_IMOPH(NAME, S) \
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
107
+ void *vpn, void *vpm, uint32_t desc) \
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
109
110
-DEF_IMOPH(smopa_s)
111
-DEF_IMOPH(umopa_s)
112
-DEF_IMOPH(sumopa_s)
113
-DEF_IMOPH(usmopa_s)
114
-DEF_IMOPH(smopa_d)
115
-DEF_IMOPH(umopa_d)
116
-DEF_IMOPH(sumopa_d)
117
-DEF_IMOPH(usmopa_d)
118
+DEF_IMOPH(smopa, s)
119
+DEF_IMOPH(umopa, s)
120
+DEF_IMOPH(sumopa, s)
121
+DEF_IMOPH(usmopa, s)
122
+
123
+DEF_IMOPH(smopa, d)
124
+DEF_IMOPH(umopa, d)
125
+DEF_IMOPH(sumopa, d)
126
+DEF_IMOPH(usmopa, d)
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
128
new file mode 100644
129
index XXXXXXX..XXXXXXX
130
--- /dev/null
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
132
@@ -XXX,XX +XXX,XX @@
133
+#include <stdio.h>
134
+#include <string.h>
135
+
136
+int main()
137
+{
138
+ static const int cmp[4][4] = {
139
+ { 110, 134, 158, 182 },
140
+ { 390, 478, 566, 654 },
141
+ { 670, 822, 974, 1126 },
142
+ { 950, 1166, 1382, 1598 }
143
+ };
144
+ int dst[4][4];
145
+ int *tmp = &dst[0][0];
146
+
147
+ asm volatile(
148
+ ".arch armv8-r+sme\n\t"
149
+ "smstart\n\t"
150
+ "index z0.b, #0, #1\n\t"
151
+ "movprfx z1, z0\n\t"
152
+ "add z1.b, z1.b, #16\n\t"
153
+ "ptrue p0.b\n\t"
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
155
+ "ptrue p0.s, vl4\n\t"
156
+ "mov w12, #0\n\t"
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
158
+ "add %0, %0, #16\n\t"
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
160
+ "add %0, %0, #16\n\t"
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
162
+ "add %0, %0, #16\n\t"
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
164
+ "smstop"
165
+ : "+r"(tmp) : : "memory");
166
+
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
168
+ return 0;
169
+ }
170
+
171
+ /* See above for correct results. */
172
+ for (int i = 0; i < 4; ++i) {
173
+ for (int j = 0; j < 4; ++j) {
174
+ printf("%6d", dst[i][j]);
175
+ }
176
+ printf("\n");
177
+ }
178
+ return 1;
179
+}
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
181
new file mode 100644
182
index XXXXXXX..XXXXXXX
183
--- /dev/null
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
185
@@ -XXX,XX +XXX,XX @@
186
+#include <stdio.h>
187
+#include <string.h>
188
+
189
+int main()
190
+{
191
+ static const long cmp[4][4] = {
192
+ { 110, 134, 158, 182 },
193
+ { 390, 478, 566, 654 },
194
+ { 670, 822, 974, 1126 },
195
+ { 950, 1166, 1382, 1598 }
196
+ };
197
+ long dst[4][4];
198
+ long *tmp = &dst[0][0];
199
+ long svl;
200
+
201
+ /* Validate that we have a wide enough vector for 4 elements. */
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
203
+ if (svl < 32) {
204
+ return 0;
205
+ }
206
+
207
+ asm volatile(
208
+ "smstart\n\t"
209
+ "index z0.h, #0, #1\n\t"
210
+ "movprfx z1, z0\n\t"
211
+ "add z1.h, z1.h, #16\n\t"
212
+ "ptrue p0.b\n\t"
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
214
+ "ptrue p0.d, vl4\n\t"
215
+ "mov w12, #0\n\t"
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
217
+ "add %0, %0, #32\n\t"
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
219
+ "mov w12, #2\n\t"
220
+ "add %0, %0, #32\n\t"
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
222
+ "add %0, %0, #32\n\t"
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
224
+ "smstop"
225
+ : "+r"(tmp) : : "memory");
226
+
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
228
+ return 0;
229
+ }
230
+
231
+ /* See above for correct results. */
232
+ for (int i = 0; i < 4; ++i) {
233
+ for (int j = 0; j < 4; ++j) {
234
+ printf("%6ld", dst[i][j]);
235
+ }
236
+ printf("\n");
237
+ }
238
+ return 1;
239
+}
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
241
index XXXXXXX..XXXXXXX 100644
242
--- a/tests/tcg/aarch64/Makefile.target
243
+++ b/tests/tcg/aarch64/Makefile.target
244
@@ -XXX,XX +XXX,XX @@ endif
245
246
# SME Tests
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
248
-AARCH64_TESTS += sme-outprod1
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
250
endif
251
252
# System Registers Tests
46
--
253
--
47
2.20.1
254
2.34.1
48
255
49
256
diff view generated by jsdifflib
1
The MPS2 SCC device doesn't have any documentation of its properties;
1
The sun4v RTC device model added under commit a0e893039cf2ce0 in 2016
2
add a "QEMU interface" format comment describing them.
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.
3
4
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
6
to make it compatible with the rest of QEMU.
7
8
Cc: qemu-stable@nongnu.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
6
Message-id: 20210504120912.23094-2-peter.maydell@linaro.org
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
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
19
---
8
include/hw/misc/mps2-scc.h | 12 ++++++++++++
20
include/hw/rtc/sun4v-rtc.h | 2 +-
9
1 file changed, 12 insertions(+)
21
hw/rtc/sun4v-rtc.c | 2 +-
22
2 files changed, 2 insertions(+), 2 deletions(-)
10
23
11
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
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/include/hw/misc/mps2-scc.h
26
--- a/include/hw/rtc/sun4v-rtc.h
14
+++ b/include/hw/misc/mps2-scc.h
27
+++ b/include/hw/rtc/sun4v-rtc.h
15
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
16
* (at your option) any later version.
29
*
30
* Copyright (c) 2016 Artyom Tarasenko
31
*
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
34
* version.
17
*/
35
*/
18
36
19
+/*
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
20
+ * This is a model of the Serial Communication Controller (SCC)
38
index XXXXXXX..XXXXXXX 100644
21
+ * block found in most MPS FPGA images.
39
--- a/hw/rtc/sun4v-rtc.c
22
+ *
40
+++ b/hw/rtc/sun4v-rtc.c
23
+ * QEMU interface:
41
@@ -XXX,XX +XXX,XX @@
24
+ * + sysbus MMIO region 0: the register bank
42
*
25
+ * + QOM property "scc-cfg4": value of the read-only CFG4 register
43
* Copyright (c) 2016 Artyom Tarasenko
26
+ * + QOM property "scc-aid": value of the read-only SCC_AID register
44
*
27
+ * + QOM property "scc-id": value of the read-only SCC_ID register
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
28
+ * + QOM property array "oscclk": reset values of the OSCCLK registers
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
29
+ * (which are accessed via the SYS_CFG channel provided by this device)
47
* version.
30
+ */
48
*/
31
#ifndef MPS2_SCC_H
32
#define MPS2_SCC_H
33
49
34
--
50
--
35
2.20.1
51
2.34.1
36
52
37
53
diff view generated by jsdifflib
1
Currently the trans functions for m-nocp.decode all live in
1
From: Thomas Huth <thuth@redhat.com>
2
translate-vfp.inc.c; move them out into their own translation unit,
3
translate-m-nocp.c.
4
2
5
The trans_* functions here are pure code motion with no changes.
3
Move the code to a separate file so that we do not have to compile
4
it anymore if CONFIG_ARM_V7M is not set.
6
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210430132740.10391-5-peter.maydell@linaro.org
10
---
10
---
11
target/arm/translate-a32.h | 3 +
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
12
target/arm/translate-m-nocp.c | 221 +++++++++++++++++++++++++++++++++
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
13
target/arm/translate.c | 1 -
13
target/arm/meson.build | 3 +
14
target/arm/translate-vfp.c.inc | 196 -----------------------------
14
target/arm/tcg/meson.build | 3 +
15
target/arm/meson.build | 3 +-
15
4 files changed, 296 insertions(+), 261 deletions(-)
16
5 files changed, 226 insertions(+), 198 deletions(-)
16
create mode 100644 target/arm/tcg/cpu-v7m.c
17
create mode 100644 target/arm/translate-m-nocp.c
18
17
19
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate-a32.h
22
+++ b/target/arm/translate-a32.h
23
@@ -XXX,XX +XXX,XX @@
24
#ifndef TARGET_ARM_TRANSLATE_A64_H
25
#define TARGET_ARM_TRANSLATE_A64_H
26
27
+/* Prototypes for autogenerated disassembler functions */
28
+bool disas_m_nocp(DisasContext *dc, uint32_t insn);
29
+
30
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
31
void arm_gen_condlabel(DisasContext *s);
32
bool vfp_access_check(DisasContext *s);
33
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
34
new file mode 100644
19
new file mode 100644
35
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
36
--- /dev/null
21
--- /dev/null
37
+++ b/target/arm/translate-m-nocp.c
22
+++ b/target/arm/tcg/cpu-v7m.c
38
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
39
+/*
24
+/*
40
+ * ARM translation: M-profile NOCP special-case instructions
25
+ * QEMU ARMv7-M TCG-only CPUs.
41
+ *
26
+ *
42
+ * Copyright (c) 2020 Linaro, Ltd.
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
43
+ *
28
+ *
44
+ * This library is free software; you can redistribute it and/or
29
+ * This code is licensed under the GNU GPL v2 or later.
45
+ * modify it under the terms of the GNU Lesser General Public
46
+ * License as published by the Free Software Foundation; either
47
+ * version 2.1 of the License, or (at your option) any later version.
48
+ *
30
+ *
49
+ * This library is distributed in the hope that it will be useful,
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
50
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
52
+ * Lesser General Public License for more details.
53
+ *
54
+ * You should have received a copy of the GNU Lesser General Public
55
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
56
+ */
32
+ */
57
+
33
+
58
+#include "qemu/osdep.h"
34
+#include "qemu/osdep.h"
59
+#include "tcg/tcg-op.h"
35
+#include "cpu.h"
60
+#include "translate.h"
36
+#include "hw/core/tcg-cpu-ops.h"
61
+#include "translate-a32.h"
37
+#include "internals.h"
62
+
38
+
63
+#include "decode-m-nocp.c.inc"
39
+#if !defined(CONFIG_USER_ONLY)
64
+
40
+
65
+/*
41
+#include "hw/intc/armv7m_nvic.h"
66
+ * Decode VLLDM and VLSTM are nonstandard because:
42
+
67
+ * * if there is no FPU then these insns must NOP in
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
68
+ * Secure state and UNDEF in Nonsecure state
44
+{
69
+ * * if there is an FPU then these insns do not have
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
70
+ * the usual behaviour that vfp_access_check() provides of
46
+ ARMCPU *cpu = ARM_CPU(cs);
71
+ * being controlled by CPACR/NSACR enable bits or the
47
+ CPUARMState *env = &cpu->env;
72
+ * lazy-stacking logic.
48
+ bool ret = false;
73
+ */
49
+
74
+static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
50
+ /*
75
+{
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
76
+ TCGv_i32 fptr;
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
77
+
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
78
+ if (!arm_dc_feature(s, ARM_FEATURE_M) ||
54
+ * if it is higher priority than the current execution priority
79
+ !arm_dc_feature(s, ARM_FEATURE_V8)) {
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
80
+ return false;
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;
81
+ }
63
+ }
82
+
64
+ return ret;
83
+ if (a->op) {
65
+}
84
+ /*
66
+
85
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
67
+#endif /* !CONFIG_USER_ONLY */
86
+ * to take the IMPDEF option to make memory accesses to the stack
68
+
87
+ * slots that correspond to the D16-D31 registers (discarding
69
+static void cortex_m0_initfn(Object *obj)
88
+ * read data and writing UNKNOWN values), so for us the T2
70
+{
89
+ * encoding behaves identically to the T1 encoding.
71
+ ARMCPU *cpu = ARM_CPU(obj);
90
+ */
72
+ set_feature(&cpu->env, ARM_FEATURE_V6);
91
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
73
+ set_feature(&cpu->env, ARM_FEATURE_M);
92
+ return false;
74
+
93
+ }
75
+ cpu->midr = 0x410cc200;
94
+ } else {
76
+
95
+ /*
77
+ /*
96
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
78
+ * These ID register values are not guest visible, because
97
+ * This is currently architecturally impossible, but we add the
79
+ * we do not implement the Main Extension. They must be set
98
+ * check to stay in line with the pseudocode. Note that we must
80
+ * to values corresponding to the Cortex-M0's implemented
99
+ * emit code for the UNDEF so it takes precedence over the NOCP.
81
+ * features, because QEMU generally controls its emulation
100
+ */
82
+ * by looking at ID register fields. We use the same values as
101
+ if (dc_isar_feature(aa32_simd_r32, s)) {
83
+ * for the M3.
102
+ unallocated_encoding(s);
84
+ */
103
+ return true;
85
+ cpu->isar.id_pfr0 = 0x00000030;
104
+ }
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]);
105
+ }
310
+ }
106
+
311
+}
107
+ /*
312
+
108
+ * If not secure, UNDEF. We must emit code for this
313
+type_init(arm_v7m_cpu_register_types)
109
+ * rather than returning false so that this takes
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
110
+ * precedence over the m-nocp.decode NOCP fallback.
111
+ */
112
+ if (!s->v8m_secure) {
113
+ unallocated_encoding(s);
114
+ return true;
115
+ }
116
+ /* If no fpu, NOP. */
117
+ if (!dc_isar_feature(aa32_vfp, s)) {
118
+ return true;
119
+ }
120
+
121
+ fptr = load_reg(s, a->rn);
122
+ if (a->l) {
123
+ gen_helper_v7m_vlldm(cpu_env, fptr);
124
+ } else {
125
+ gen_helper_v7m_vlstm(cpu_env, fptr);
126
+ }
127
+ tcg_temp_free_i32(fptr);
128
+
129
+ /* End the TB, because we have updated FP control bits */
130
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
131
+ return true;
132
+}
133
+
134
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
135
+{
136
+ int btmreg, topreg;
137
+ TCGv_i64 zero;
138
+ TCGv_i32 aspen, sfpa;
139
+
140
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
141
+ /* Before v8.1M, fall through in decode to NOCP check */
142
+ return false;
143
+ }
144
+
145
+ /* Explicitly UNDEF because this takes precedence over NOCP */
146
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
147
+ unallocated_encoding(s);
148
+ return true;
149
+ }
150
+
151
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
152
+ /* NOP if we have neither FP nor MVE */
153
+ return true;
154
+ }
155
+
156
+ /*
157
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
158
+ * active floating point context so we must NOP (without doing
159
+ * any lazy state preservation or the NOCP check).
160
+ */
161
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
162
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
163
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
164
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
165
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
166
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
167
+ arm_gen_condlabel(s);
168
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
169
+
170
+ if (s->fp_excp_el != 0) {
171
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
172
+ syn_uncategorized(), s->fp_excp_el);
173
+ return true;
174
+ }
175
+
176
+ topreg = a->vd + a->imm - 1;
177
+ btmreg = a->vd;
178
+
179
+ /* Convert to Sreg numbers if the insn specified in Dregs */
180
+ if (a->size == 3) {
181
+ topreg = topreg * 2 + 1;
182
+ btmreg *= 2;
183
+ }
184
+
185
+ if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
186
+ /* UNPREDICTABLE: we choose to undef */
187
+ unallocated_encoding(s);
188
+ return true;
189
+ }
190
+
191
+ /* Silently ignore requests to clear D16-D31 if they don't exist */
192
+ if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
193
+ topreg = 31;
194
+ }
195
+
196
+ if (!vfp_access_check(s)) {
197
+ return true;
198
+ }
199
+
200
+ /* Zero the Sregs from btmreg to topreg inclusive. */
201
+ zero = tcg_const_i64(0);
202
+ if (btmreg & 1) {
203
+ write_neon_element64(zero, btmreg >> 1, 1, MO_32);
204
+ btmreg++;
205
+ }
206
+ for (; btmreg + 1 <= topreg; btmreg += 2) {
207
+ write_neon_element64(zero, btmreg >> 1, 0, MO_64);
208
+ }
209
+ if (btmreg == topreg) {
210
+ write_neon_element64(zero, btmreg >> 1, 0, MO_32);
211
+ btmreg++;
212
+ }
213
+ assert(btmreg == topreg + 1);
214
+ /* TODO: when MVE is implemented, zero VPR here */
215
+ return true;
216
+}
217
+
218
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
219
+{
220
+ /*
221
+ * Handle M-profile early check for disabled coprocessor:
222
+ * all we need to do here is emit the NOCP exception if
223
+ * the coprocessor is disabled. Otherwise we return false
224
+ * and the real VFP/etc decode will handle the insn.
225
+ */
226
+ assert(arm_dc_feature(s, ARM_FEATURE_M));
227
+
228
+ if (a->cp == 11) {
229
+ a->cp = 10;
230
+ }
231
+ if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
232
+ (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) {
233
+ /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
234
+ a->cp = 10;
235
+ }
236
+
237
+ if (a->cp != 10) {
238
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
239
+ syn_uncategorized(), default_exception_el(s));
240
+ return true;
241
+ }
242
+
243
+ if (s->fp_excp_el != 0) {
244
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
245
+ syn_uncategorized(), s->fp_excp_el);
246
+ return true;
247
+ }
248
+
249
+ return false;
250
+}
251
+
252
+static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a)
253
+{
254
+ /* This range needs a coprocessor check for v8.1M and later only */
255
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
256
+ return false;
257
+ }
258
+ return trans_NOCP(s, a);
259
+}
260
diff --git a/target/arm/translate.c b/target/arm/translate.c
261
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
262
--- a/target/arm/translate.c
316
--- a/target/arm/tcg/cpu32.c
263
+++ b/target/arm/translate.c
317
+++ b/target/arm/tcg/cpu32.c
264
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
318
@@ -XXX,XX +XXX,XX @@
265
#define ARM_CP_RW_BIT (1 << 20)
319
#include "hw/boards.h"
266
320
#endif
267
/* Include the VFP and Neon decoders */
321
#include "cpregs.h"
268
-#include "decode-m-nocp.c.inc"
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
269
#include "translate-vfp.c.inc"
323
-#include "hw/intc/armv7m_nvic.h"
270
#include "translate-neon.c.inc"
324
-#endif
271
325
272
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
326
273
index XXXXXXX..XXXXXXX 100644
327
/* Share AArch32 -cpu max features with AArch64. */
274
--- a/target/arm/translate-vfp.c.inc
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
275
+++ b/target/arm/translate-vfp.c.inc
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
276
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
277
return true;
331
332
-#if !defined(CONFIG_USER_ONLY)
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
334
-{
335
- CPUClass *cc = CPU_GET_CLASS(cs);
336
- ARMCPU *cpu = ARM_CPU(cs);
337
- CPUARMState *env = &cpu->env;
338
- bool ret = false;
339
-
340
- /*
341
- * ARMv7-M interrupt masking works differently than -A or -R.
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
343
- * masking FIQ and IRQ interrupts, an exception is taken only
344
- * if it is higher priority than the current execution priority
345
- * (which depends on state like BASEPRI, FAULTMASK and the
346
- * currently active exception).
347
- */
348
- if (interrupt_request & CPU_INTERRUPT_HARD
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
350
- cs->exception_index = EXCP_IRQ;
351
- cc->tcg_ops->do_interrupt(cs);
352
- ret = true;
353
- }
354
- return ret;
355
-}
356
-#endif /* !CONFIG_USER_ONLY */
357
-
358
static void arm926_initfn(Object *obj)
359
{
360
ARMCPU *cpu = ARM_CPU(obj);
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
278
}
363
}
279
364
280
-/*
365
-static void cortex_m0_initfn(Object *obj)
281
- * Decode VLLDM and VLSTM are nonstandard because:
366
-{
282
- * * if there is no FPU then these insns must NOP in
367
- ARMCPU *cpu = ARM_CPU(obj);
283
- * Secure state and UNDEF in Nonsecure state
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
284
- * * if there is an FPU then these insns do not have
369
- set_feature(&cpu->env, ARM_FEATURE_M);
285
- * the usual behaviour that vfp_access_check() provides of
370
-
286
- * being controlled by CPACR/NSACR enable bits or the
371
- cpu->midr = 0x410cc200;
287
- * lazy-stacking logic.
288
- */
289
-static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
290
-{
291
- TCGv_i32 fptr;
292
-
293
- if (!arm_dc_feature(s, ARM_FEATURE_M) ||
294
- !arm_dc_feature(s, ARM_FEATURE_V8)) {
295
- return false;
296
- }
297
-
298
- if (a->op) {
299
- /*
300
- * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
301
- * to take the IMPDEF option to make memory accesses to the stack
302
- * slots that correspond to the D16-D31 registers (discarding
303
- * read data and writing UNKNOWN values), so for us the T2
304
- * encoding behaves identically to the T1 encoding.
305
- */
306
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
307
- return false;
308
- }
309
- } else {
310
- /*
311
- * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
312
- * This is currently architecturally impossible, but we add the
313
- * check to stay in line with the pseudocode. Note that we must
314
- * emit code for the UNDEF so it takes precedence over the NOCP.
315
- */
316
- if (dc_isar_feature(aa32_simd_r32, s)) {
317
- unallocated_encoding(s);
318
- return true;
319
- }
320
- }
321
-
372
-
322
- /*
373
- /*
323
- * If not secure, UNDEF. We must emit code for this
374
- * These ID register values are not guest visible, because
324
- * rather than returning false so that this takes
375
- * we do not implement the Main Extension. They must be set
325
- * precedence over the m-nocp.decode NOCP fallback.
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.
326
- */
380
- */
327
- if (!s->v8m_secure) {
381
- cpu->isar.id_pfr0 = 0x00000030;
328
- unallocated_encoding(s);
382
- cpu->isar.id_pfr1 = 0x00000200;
329
- return true;
383
- cpu->isar.id_dfr0 = 0x00100000;
330
- }
384
- cpu->id_afr0 = 0x00000000;
331
- /* If no fpu, NOP. */
385
- cpu->isar.id_mmfr0 = 0x00000030;
332
- if (!dc_isar_feature(aa32_vfp, s)) {
386
- cpu->isar.id_mmfr1 = 0x00000000;
333
- return true;
387
- cpu->isar.id_mmfr2 = 0x00000000;
334
- }
388
- cpu->isar.id_mmfr3 = 0x00000000;
335
-
389
- cpu->isar.id_isar0 = 0x01141110;
336
- fptr = load_reg(s, a->rn);
390
- cpu->isar.id_isar1 = 0x02111000;
337
- if (a->l) {
391
- cpu->isar.id_isar2 = 0x21112231;
338
- gen_helper_v7m_vlldm(cpu_env, fptr);
392
- cpu->isar.id_isar3 = 0x01111110;
339
- } else {
393
- cpu->isar.id_isar4 = 0x01310102;
340
- gen_helper_v7m_vlstm(cpu_env, fptr);
394
- cpu->isar.id_isar5 = 0x00000000;
341
- }
395
- cpu->isar.id_isar6 = 0x00000000;
342
- tcg_temp_free_i32(fptr);
396
-}
343
-
397
-
344
- /* End the TB, because we have updated FP control bits */
398
-static void cortex_m3_initfn(Object *obj)
345
- s->base.is_jmp = DISAS_UPDATE_EXIT;
399
-{
346
- return true;
400
- ARMCPU *cpu = ARM_CPU(obj);
347
-}
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
348
-
402
- set_feature(&cpu->env, ARM_FEATURE_M);
349
-static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
350
-{
404
- cpu->midr = 0x410fc231;
351
- int btmreg, topreg;
405
- cpu->pmsav7_dregion = 8;
352
- TCGv_i64 zero;
406
- cpu->isar.id_pfr0 = 0x00000030;
353
- TCGv_i32 aspen, sfpa;
407
- cpu->isar.id_pfr1 = 0x00000200;
354
-
408
- cpu->isar.id_dfr0 = 0x00100000;
355
- if (!dc_isar_feature(aa32_m_sec_state, s)) {
409
- cpu->id_afr0 = 0x00000000;
356
- /* Before v8.1M, fall through in decode to NOCP check */
410
- cpu->isar.id_mmfr0 = 0x00000030;
357
- return false;
411
- cpu->isar.id_mmfr1 = 0x00000000;
358
- }
412
- cpu->isar.id_mmfr2 = 0x00000000;
359
-
413
- cpu->isar.id_mmfr3 = 0x00000000;
360
- /* Explicitly UNDEF because this takes precedence over NOCP */
414
- cpu->isar.id_isar0 = 0x01141110;
361
- if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
415
- cpu->isar.id_isar1 = 0x02111000;
362
- unallocated_encoding(s);
416
- cpu->isar.id_isar2 = 0x21112231;
363
- return true;
417
- cpu->isar.id_isar3 = 0x01111110;
364
- }
418
- cpu->isar.id_isar4 = 0x01310102;
365
-
419
- cpu->isar.id_isar5 = 0x00000000;
366
- if (!dc_isar_feature(aa32_vfp_simd, s)) {
420
- cpu->isar.id_isar6 = 0x00000000;
367
- /* NOP if we have neither FP nor MVE */
421
-}
368
- return true;
422
-
369
- }
423
-static void cortex_m4_initfn(Object *obj)
370
-
424
-{
371
- /*
425
- ARMCPU *cpu = ARM_CPU(obj);
372
- * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
426
-
373
- * active floating point context so we must NOP (without doing
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
374
- * any lazy state preservation or the NOCP check).
428
- set_feature(&cpu->env, ARM_FEATURE_M);
375
- */
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
376
- aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
377
- sfpa = load_cpu_field(v7m.control[M_REG_S]);
431
- cpu->midr = 0x410fc240; /* r0p0 */
378
- tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
432
- cpu->pmsav7_dregion = 8;
379
- tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
433
- cpu->isar.mvfr0 = 0x10110021;
380
- tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
434
- cpu->isar.mvfr1 = 0x11000011;
381
- tcg_gen_or_i32(sfpa, sfpa, aspen);
435
- cpu->isar.mvfr2 = 0x00000000;
382
- arm_gen_condlabel(s);
436
- cpu->isar.id_pfr0 = 0x00000030;
383
- tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
437
- cpu->isar.id_pfr1 = 0x00000200;
384
-
438
- cpu->isar.id_dfr0 = 0x00100000;
385
- if (s->fp_excp_el != 0) {
439
- cpu->id_afr0 = 0x00000000;
386
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
440
- cpu->isar.id_mmfr0 = 0x00000030;
387
- syn_uncategorized(), s->fp_excp_el);
441
- cpu->isar.id_mmfr1 = 0x00000000;
388
- return true;
442
- cpu->isar.id_mmfr2 = 0x00000000;
389
- }
443
- cpu->isar.id_mmfr3 = 0x00000000;
390
-
444
- cpu->isar.id_isar0 = 0x01141110;
391
- topreg = a->vd + a->imm - 1;
445
- cpu->isar.id_isar1 = 0x02111000;
392
- btmreg = a->vd;
446
- cpu->isar.id_isar2 = 0x21112231;
393
-
447
- cpu->isar.id_isar3 = 0x01111110;
394
- /* Convert to Sreg numbers if the insn specified in Dregs */
448
- cpu->isar.id_isar4 = 0x01310102;
395
- if (a->size == 3) {
449
- cpu->isar.id_isar5 = 0x00000000;
396
- topreg = topreg * 2 + 1;
450
- cpu->isar.id_isar6 = 0x00000000;
397
- btmreg *= 2;
451
-}
398
- }
452
-
399
-
453
-static void cortex_m7_initfn(Object *obj)
400
- if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
454
-{
401
- /* UNPREDICTABLE: we choose to undef */
455
- ARMCPU *cpu = ARM_CPU(obj);
402
- unallocated_encoding(s);
456
-
403
- return true;
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
404
- }
458
- set_feature(&cpu->env, ARM_FEATURE_M);
405
-
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
406
- /* Silently ignore requests to clear D16-D31 if they don't exist */
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
407
- if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
461
- cpu->midr = 0x411fc272; /* r1p2 */
408
- topreg = 31;
462
- cpu->pmsav7_dregion = 8;
409
- }
463
- cpu->isar.mvfr0 = 0x10110221;
410
-
464
- cpu->isar.mvfr1 = 0x12000011;
411
- if (!vfp_access_check(s)) {
465
- cpu->isar.mvfr2 = 0x00000040;
412
- return true;
466
- cpu->isar.id_pfr0 = 0x00000030;
413
- }
467
- cpu->isar.id_pfr1 = 0x00000200;
414
-
468
- cpu->isar.id_dfr0 = 0x00100000;
415
- /* Zero the Sregs from btmreg to topreg inclusive. */
469
- cpu->id_afr0 = 0x00000000;
416
- zero = tcg_const_i64(0);
470
- cpu->isar.id_mmfr0 = 0x00100030;
417
- if (btmreg & 1) {
471
- cpu->isar.id_mmfr1 = 0x00000000;
418
- write_neon_element64(zero, btmreg >> 1, 1, MO_32);
472
- cpu->isar.id_mmfr2 = 0x01000000;
419
- btmreg++;
473
- cpu->isar.id_mmfr3 = 0x00000000;
420
- }
474
- cpu->isar.id_isar0 = 0x01101110;
421
- for (; btmreg + 1 <= topreg; btmreg += 2) {
475
- cpu->isar.id_isar1 = 0x02112000;
422
- write_neon_element64(zero, btmreg >> 1, 0, MO_64);
476
- cpu->isar.id_isar2 = 0x20232231;
423
- }
477
- cpu->isar.id_isar3 = 0x01111131;
424
- if (btmreg == topreg) {
478
- cpu->isar.id_isar4 = 0x01310132;
425
- write_neon_element64(zero, btmreg >> 1, 0, MO_32);
479
- cpu->isar.id_isar5 = 0x00000000;
426
- btmreg++;
480
- cpu->isar.id_isar6 = 0x00000000;
427
- }
481
-}
428
- assert(btmreg == topreg + 1);
482
-
429
- /* TODO: when MVE is implemented, zero VPR here */
483
-static void cortex_m33_initfn(Object *obj)
430
- return true;
484
-{
431
-}
485
- ARMCPU *cpu = ARM_CPU(obj);
432
-
486
-
433
-static bool trans_NOCP(DisasContext *s, arg_nocp *a)
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
434
-{
488
- set_feature(&cpu->env, ARM_FEATURE_M);
435
- /*
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
436
- * Handle M-profile early check for disabled coprocessor:
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
437
- * all we need to do here is emit the NOCP exception if
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
438
- * the coprocessor is disabled. Otherwise we return false
492
- cpu->midr = 0x410fd213; /* r0p3 */
439
- * and the real VFP/etc decode will handle the insn.
493
- cpu->pmsav7_dregion = 16;
440
- */
494
- cpu->sau_sregion = 8;
441
- assert(arm_dc_feature(s, ARM_FEATURE_M));
495
- cpu->isar.mvfr0 = 0x10110021;
442
-
496
- cpu->isar.mvfr1 = 0x11000011;
443
- if (a->cp == 11) {
497
- cpu->isar.mvfr2 = 0x00000040;
444
- a->cp = 10;
498
- cpu->isar.id_pfr0 = 0x00000030;
445
- }
499
- cpu->isar.id_pfr1 = 0x00000210;
446
- if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
500
- cpu->isar.id_dfr0 = 0x00200000;
447
- (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) {
501
- cpu->id_afr0 = 0x00000000;
448
- /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
502
- cpu->isar.id_mmfr0 = 0x00101F40;
449
- a->cp = 10;
503
- cpu->isar.id_mmfr1 = 0x00000000;
450
- }
504
- cpu->isar.id_mmfr2 = 0x01000000;
451
-
505
- cpu->isar.id_mmfr3 = 0x00000000;
452
- if (a->cp != 10) {
506
- cpu->isar.id_isar0 = 0x01101110;
453
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
507
- cpu->isar.id_isar1 = 0x02212000;
454
- syn_uncategorized(), default_exception_el(s));
508
- cpu->isar.id_isar2 = 0x20232232;
455
- return true;
509
- cpu->isar.id_isar3 = 0x01111131;
456
- }
510
- cpu->isar.id_isar4 = 0x01310132;
457
-
511
- cpu->isar.id_isar5 = 0x00000000;
458
- if (s->fp_excp_el != 0) {
512
- cpu->isar.id_isar6 = 0x00000000;
459
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
513
- cpu->clidr = 0x00000000;
460
- syn_uncategorized(), s->fp_excp_el);
514
- cpu->ctr = 0x8000c000;
461
- return true;
515
-}
462
- }
516
-
463
-
517
-static void cortex_m55_initfn(Object *obj)
464
- return false;
518
-{
465
-}
519
- ARMCPU *cpu = ARM_CPU(obj);
466
-
520
-
467
-static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a)
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
468
-{
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
469
- /* This range needs a coprocessor check for v8.1M and later only */
523
- set_feature(&cpu->env, ARM_FEATURE_M);
470
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
471
- return false;
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
472
- }
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
473
- return trans_NOCP(s, a);
527
- cpu->midr = 0x410fd221; /* r0p1 */
474
-}
528
- cpu->revidr = 0;
475
-
529
- cpu->pmsav7_dregion = 16;
476
static bool trans_VINS(DisasContext *s, arg_VINS *a)
530
- cpu->sau_sregion = 8;
477
{
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
478
TCGv_i32 rd, rm;
532
- cpu->isar.mvfr0 = 0x10110221;
533
- cpu->isar.mvfr1 = 0x12100211;
534
- cpu->isar.mvfr2 = 0x00000040;
535
- cpu->isar.id_pfr0 = 0x20000030;
536
- cpu->isar.id_pfr1 = 0x00000230;
537
- cpu->isar.id_dfr0 = 0x10200000;
538
- cpu->id_afr0 = 0x00000000;
539
- cpu->isar.id_mmfr0 = 0x00111040;
540
- cpu->isar.id_mmfr1 = 0x00000000;
541
- cpu->isar.id_mmfr2 = 0x01000000;
542
- cpu->isar.id_mmfr3 = 0x00000011;
543
- cpu->isar.id_isar0 = 0x01103110;
544
- cpu->isar.id_isar1 = 0x02212000;
545
- cpu->isar.id_isar2 = 0x20232232;
546
- cpu->isar.id_isar3 = 0x01111131;
547
- cpu->isar.id_isar4 = 0x01310132;
548
- cpu->isar.id_isar5 = 0x00000000;
549
- cpu->isar.id_isar6 = 0x00000000;
550
- cpu->clidr = 0x00000000; /* caches not implemented */
551
- cpu->ctr = 0x8303c003;
552
-}
553
-
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
555
/* Dummy the TCM region regs for the moment */
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
558
cpu->reset_sctlr = 0x00000078;
559
}
560
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
562
- .initialize = arm_translate_init,
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
564
- .debug_excp_handler = arm_debug_excp_handler,
565
- .restore_state_to_opc = arm_restore_state_to_opc,
566
-
567
-#ifdef CONFIG_USER_ONLY
568
- .record_sigsegv = arm_cpu_record_sigsegv,
569
- .record_sigbus = arm_cpu_record_sigbus,
570
-#else
571
- .tlb_fill = arm_cpu_tlb_fill,
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
579
-#endif /* !CONFIG_USER_ONLY */
580
-};
581
-
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
583
-{
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
585
- CPUClass *cc = CPU_CLASS(oc);
586
-
587
- acc->info = data;
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
590
-}
591
-
592
#ifndef TARGET_AARCH64
593
/*
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
600
- .class_init = arm_v7m_class_init },
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
602
- .class_init = arm_v7m_class_init },
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
604
- .class_init = arm_v7m_class_init },
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
606
- .class_init = arm_v7m_class_init },
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
608
- .class_init = arm_v7m_class_init },
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
610
- .class_init = arm_v7m_class_init },
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
479
diff --git a/target/arm/meson.build b/target/arm/meson.build
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
480
index XXXXXXX..XXXXXXX 100644
615
index XXXXXXX..XXXXXXX 100644
481
--- a/target/arm/meson.build
616
--- a/target/arm/meson.build
482
+++ b/target/arm/meson.build
617
+++ b/target/arm/meson.build
483
@@ -XXX,XX +XXX,XX @@ gen = [
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
484
decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'),
619
'ptw.c',
485
decodetree.process('vfp.decode', extra_args: '--static-decode=disas_vfp'),
620
))
486
decodetree.process('vfp-uncond.decode', extra_args: '--static-decode=disas_vfp_uncond'),
621
487
- decodetree.process('m-nocp.decode', extra_args: '--static-decode=disas_m_nocp'),
622
+arm_user_ss = ss.source_set()
488
+ decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'),
623
+
489
decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'),
624
subdir('hvf')
490
decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
625
491
decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
626
if 'CONFIG_TCG' in config_all_accel
492
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
627
@@ -XXX,XX +XXX,XX @@ endif
493
'op_helper.c',
628
494
'tlb_helper.c',
629
target_arch += {'arm': arm_ss}
495
'translate.c',
630
target_system_arch += {'arm': arm_system_ss}
496
+ 'translate-m-nocp.c',
631
+target_user_arch += {'arm': arm_user_ss}
497
'vec_helper.c',
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
498
'vfp_helper.c',
633
index XXXXXXX..XXXXXXX 100644
499
'cpu_tcg.c',
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'))
500
--
643
--
501
2.20.1
644
2.34.1
502
503
diff view generated by jsdifflib
Deleted patch
1
Move the various gen_aa32* functions and macros out of translate.c
2
and into translate-a32.h.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210430132740.10391-6-peter.maydell@linaro.org
8
---
9
target/arm/translate-a32.h | 53 ++++++++++++++++++++++++++++++++++++++
10
target/arm/translate.c | 51 ++++++++++++------------------------
11
2 files changed, 69 insertions(+), 35 deletions(-)
12
13
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a32.h
16
+++ b/target/arm/translate-a32.h
17
@@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg)
18
return tmp;
19
}
20
21
+void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val,
22
+ TCGv_i32 a32, int index, MemOp opc);
23
+void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val,
24
+ TCGv_i32 a32, int index, MemOp opc);
25
+void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val,
26
+ TCGv_i32 a32, int index, MemOp opc);
27
+void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val,
28
+ TCGv_i32 a32, int index, MemOp opc);
29
+void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
30
+ int index, MemOp opc);
31
+void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
32
+ int index, MemOp opc);
33
+void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
34
+ int index, MemOp opc);
35
+void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
36
+ int index, MemOp opc);
37
+
38
+#define DO_GEN_LD(SUFF, OPC) \
39
+ static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
40
+ TCGv_i32 a32, int index) \
41
+ { \
42
+ gen_aa32_ld_i32(s, val, a32, index, OPC); \
43
+ }
44
+
45
+#define DO_GEN_ST(SUFF, OPC) \
46
+ static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
47
+ TCGv_i32 a32, int index) \
48
+ { \
49
+ gen_aa32_st_i32(s, val, a32, index, OPC); \
50
+ }
51
+
52
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
53
+ TCGv_i32 a32, int index)
54
+{
55
+ gen_aa32_ld_i64(s, val, a32, index, MO_Q);
56
+}
57
+
58
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
59
+ TCGv_i32 a32, int index)
60
+{
61
+ gen_aa32_st_i64(s, val, a32, index, MO_Q);
62
+}
63
+
64
+DO_GEN_LD(8u, MO_UB)
65
+DO_GEN_LD(16u, MO_UW)
66
+DO_GEN_LD(32u, MO_UL)
67
+DO_GEN_ST(8, MO_UB)
68
+DO_GEN_ST(16, MO_UW)
69
+DO_GEN_ST(32, MO_UL)
70
+
71
+#undef DO_GEN_LD
72
+#undef DO_GEN_ST
73
+
74
#endif
75
diff --git a/target/arm/translate.c b/target/arm/translate.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/translate.c
78
+++ b/target/arm/translate.c
79
@@ -XXX,XX +XXX,XX @@ static TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op)
80
* Internal routines are used for NEON cases where the endianness
81
* and/or alignment has already been taken into account and manipulated.
82
*/
83
-static void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val,
84
- TCGv_i32 a32, int index, MemOp opc)
85
+void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val,
86
+ TCGv_i32 a32, int index, MemOp opc)
87
{
88
TCGv addr = gen_aa32_addr(s, a32, opc);
89
tcg_gen_qemu_ld_i32(val, addr, index, opc);
90
tcg_temp_free(addr);
91
}
92
93
-static void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val,
94
- TCGv_i32 a32, int index, MemOp opc)
95
+void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val,
96
+ TCGv_i32 a32, int index, MemOp opc)
97
{
98
TCGv addr = gen_aa32_addr(s, a32, opc);
99
tcg_gen_qemu_st_i32(val, addr, index, opc);
100
tcg_temp_free(addr);
101
}
102
103
-static void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val,
104
- TCGv_i32 a32, int index, MemOp opc)
105
+void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val,
106
+ TCGv_i32 a32, int index, MemOp opc)
107
{
108
TCGv addr = gen_aa32_addr(s, a32, opc);
109
110
@@ -XXX,XX +XXX,XX @@ static void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val,
111
tcg_temp_free(addr);
112
}
113
114
-static void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val,
115
- TCGv_i32 a32, int index, MemOp opc)
116
+void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val,
117
+ TCGv_i32 a32, int index, MemOp opc)
118
{
119
TCGv addr = gen_aa32_addr(s, a32, opc);
120
121
@@ -XXX,XX +XXX,XX @@ static void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val,
122
tcg_temp_free(addr);
123
}
124
125
-static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
126
- int index, MemOp opc)
127
+void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
128
+ int index, MemOp opc)
129
{
130
gen_aa32_ld_internal_i32(s, val, a32, index, finalize_memop(s, opc));
131
}
132
133
-static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
134
- int index, MemOp opc)
135
+void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
136
+ int index, MemOp opc)
137
{
138
gen_aa32_st_internal_i32(s, val, a32, index, finalize_memop(s, opc));
139
}
140
141
-static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
142
- int index, MemOp opc)
143
+void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
144
+ int index, MemOp opc)
145
{
146
gen_aa32_ld_internal_i64(s, val, a32, index, finalize_memop(s, opc));
147
}
148
149
-static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
150
- int index, MemOp opc)
151
+void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
152
+ int index, MemOp opc)
153
{
154
gen_aa32_st_internal_i64(s, val, a32, index, finalize_memop(s, opc));
155
}
156
@@ -XXX,XX +XXX,XX @@ static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
157
gen_aa32_st_i32(s, val, a32, index, OPC); \
158
}
159
160
-static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
161
- TCGv_i32 a32, int index)
162
-{
163
- gen_aa32_ld_i64(s, val, a32, index, MO_Q);
164
-}
165
-
166
-static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
167
- TCGv_i32 a32, int index)
168
-{
169
- gen_aa32_st_i64(s, val, a32, index, MO_Q);
170
-}
171
-
172
-DO_GEN_LD(8u, MO_UB)
173
-DO_GEN_LD(16u, MO_UW)
174
-DO_GEN_LD(32u, MO_UL)
175
-DO_GEN_ST(8, MO_UB)
176
-DO_GEN_ST(16, MO_UW)
177
-DO_GEN_ST(32, MO_UL)
178
-
179
static inline void gen_hvc(DisasContext *s, int imm16)
180
{
181
/* The pre HVC helper handles cases when HVC gets trapped
182
--
183
2.20.1
184
185
diff view generated by jsdifflib
Deleted patch
1
Make the remaining functions which are needed by translate-vfp.c.inc
2
global.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210430132740.10391-8-peter.maydell@linaro.org
8
---
9
target/arm/translate-a32.h | 18 ++++++++++++++++++
10
target/arm/translate.c | 25 ++++++++-----------------
11
2 files changed, 26 insertions(+), 17 deletions(-)
12
13
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a32.h
16
+++ b/target/arm/translate-a32.h
17
@@ -XXX,XX +XXX,XX @@ void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
18
void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
19
void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
20
void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop);
21
+TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs);
22
+void gen_set_cpsr(TCGv_i32 var, uint32_t mask);
23
+void gen_set_condexec(DisasContext *s);
24
+void gen_set_pc_im(DisasContext *s, target_ulong val);
25
+void gen_lookup_tb(DisasContext *s);
26
+long vfp_reg_offset(bool dp, unsigned reg);
27
+long neon_full_reg_offset(unsigned reg);
28
29
static inline TCGv_i32 load_cpu_offset(int offset)
30
{
31
@@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg)
32
return tmp;
33
}
34
35
+void store_reg(DisasContext *s, int reg, TCGv_i32 var);
36
+
37
void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val,
38
TCGv_i32 a32, int index, MemOp opc);
39
void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val,
40
@@ -XXX,XX +XXX,XX @@ DO_GEN_ST(32, MO_UL)
41
#undef DO_GEN_LD
42
#undef DO_GEN_ST
43
44
+#if defined(CONFIG_USER_ONLY)
45
+#define IS_USER(s) 1
46
+#else
47
+#define IS_USER(s) (s->user)
48
+#endif
49
+
50
+/* Set NZCV flags from the high 4 bits of var. */
51
+#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
52
+
53
#endif
54
diff --git a/target/arm/translate.c b/target/arm/translate.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/translate.c
57
+++ b/target/arm/translate.c
58
@@ -XXX,XX +XXX,XX @@
59
#include "translate.h"
60
#include "translate-a32.h"
61
62
-#if defined(CONFIG_USER_ONLY)
63
-#define IS_USER(s) 1
64
-#else
65
-#define IS_USER(s) (s->user)
66
-#endif
67
-
68
/* These are TCG temporaries used only by the legacy iwMMXt decoder */
69
static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
70
/* These are TCG globals which alias CPUARMState fields */
71
@@ -XXX,XX +XXX,XX @@ void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
72
* This is used for load/store for which use of PC implies (literal),
73
* or ADD that implies ADR.
74
*/
75
-static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
76
+TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
77
{
78
TCGv_i32 tmp = tcg_temp_new_i32();
79
80
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
81
82
/* Set a CPU register. The source must be a temporary and will be
83
marked as dead. */
84
-static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
85
+void store_reg(DisasContext *s, int reg, TCGv_i32 var)
86
{
87
if (reg == 15) {
88
/* In Thumb mode, we must ignore bit 0.
89
@@ -XXX,XX +XXX,XX @@ static void store_sp_checked(DisasContext *s, TCGv_i32 var)
90
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
91
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
92
93
-
94
-static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
95
+void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
96
{
97
TCGv_i32 tmp_mask = tcg_const_i32(mask);
98
gen_helper_cpsr_write(cpu_env, var, tmp_mask);
99
tcg_temp_free_i32(tmp_mask);
100
}
101
-/* Set NZCV flags from the high 4 bits of var. */
102
-#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
103
104
static void gen_exception_internal(int excp)
105
{
106
@@ -XXX,XX +XXX,XX @@ void arm_gen_test_cc(int cc, TCGLabel *label)
107
arm_free_cc(&cmp);
108
}
109
110
-static inline void gen_set_condexec(DisasContext *s)
111
+void gen_set_condexec(DisasContext *s)
112
{
113
if (s->condexec_mask) {
114
uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
115
@@ -XXX,XX +XXX,XX @@ static inline void gen_set_condexec(DisasContext *s)
116
}
117
}
118
119
-static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
120
+void gen_set_pc_im(DisasContext *s, target_ulong val)
121
{
122
tcg_gen_movi_i32(cpu_R[15], val);
123
}
124
@@ -XXX,XX +XXX,XX @@ static void gen_exception_el(DisasContext *s, int excp, uint32_t syn,
125
}
126
127
/* Force a TB lookup after an instruction that changes the CPU state. */
128
-static inline void gen_lookup_tb(DisasContext *s)
129
+void gen_lookup_tb(DisasContext *s)
130
{
131
tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
132
s->base.is_jmp = DISAS_EXIT;
133
@@ -XXX,XX +XXX,XX @@ static inline void gen_hlt(DisasContext *s, int imm)
134
/*
135
* Return the offset of a "full" NEON Dreg.
136
*/
137
-static long neon_full_reg_offset(unsigned reg)
138
+long neon_full_reg_offset(unsigned reg)
139
{
140
return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
141
}
142
@@ -XXX,XX +XXX,XX @@ static long neon_element_offset(int reg, int element, MemOp memop)
143
}
144
145
/* Return the offset of a VFP Dreg (dp = true) or VFP Sreg (dp = false). */
146
-static long vfp_reg_offset(bool dp, unsigned reg)
147
+long vfp_reg_offset(bool dp, unsigned reg)
148
{
149
if (dp) {
150
return neon_element_offset(reg, 0, MO_64);
151
--
152
2.20.1
153
154
diff view generated by jsdifflib
Deleted patch
1
Switch translate-vfp.c.inc from being #included into translate.c
2
to being its own compilation unit.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210430132740.10391-9-peter.maydell@linaro.org
8
---
9
target/arm/translate-a32.h | 2 ++
10
target/arm/{translate-vfp.c.inc => translate-vfp.c} | 12 +++++++-----
11
target/arm/translate.c | 3 +--
12
target/arm/meson.build | 5 +++--
13
4 files changed, 13 insertions(+), 9 deletions(-)
14
rename target/arm/{translate-vfp.c.inc => translate-vfp.c} (99%)
15
16
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-a32.h
19
+++ b/target/arm/translate-a32.h
20
@@ -XXX,XX +XXX,XX @@
21
22
/* Prototypes for autogenerated disassembler functions */
23
bool disas_m_nocp(DisasContext *dc, uint32_t insn);
24
+bool disas_vfp(DisasContext *s, uint32_t insn);
25
+bool disas_vfp_uncond(DisasContext *s, uint32_t insn);
26
27
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
28
void arm_gen_condlabel(DisasContext *s);
29
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c
30
similarity index 99%
31
rename from target/arm/translate-vfp.c.inc
32
rename to target/arm/translate-vfp.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate-vfp.c.inc
35
+++ b/target/arm/translate-vfp.c
36
@@ -XXX,XX +XXX,XX @@
37
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
38
*/
39
40
-/*
41
- * This file is intended to be included from translate.c; it uses
42
- * some macros and definitions provided by that file.
43
- * It might be possible to convert it to a standalone .c file eventually.
44
- */
45
+#include "qemu/osdep.h"
46
+#include "tcg/tcg-op.h"
47
+#include "tcg/tcg-op-gvec.h"
48
+#include "exec/exec-all.h"
49
+#include "exec/gen-icount.h"
50
+#include "translate.h"
51
+#include "translate-a32.h"
52
53
/* Include the generated VFP decoder */
54
#include "decode-vfp.c.inc"
55
diff --git a/target/arm/translate.c b/target/arm/translate.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate.c
58
+++ b/target/arm/translate.c
59
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
60
61
#define ARM_CP_RW_BIT (1 << 20)
62
63
-/* Include the VFP and Neon decoders */
64
-#include "translate-vfp.c.inc"
65
+/* Include the Neon decoder */
66
#include "translate-neon.c.inc"
67
68
static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
69
diff --git a/target/arm/meson.build b/target/arm/meson.build
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/meson.build
72
+++ b/target/arm/meson.build
73
@@ -XXX,XX +XXX,XX @@ gen = [
74
decodetree.process('neon-shared.decode', extra_args: '--static-decode=disas_neon_shared'),
75
decodetree.process('neon-dp.decode', extra_args: '--static-decode=disas_neon_dp'),
76
decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'),
77
- decodetree.process('vfp.decode', extra_args: '--static-decode=disas_vfp'),
78
- decodetree.process('vfp-uncond.decode', extra_args: '--static-decode=disas_vfp_uncond'),
79
+ decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'),
80
+ decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'),
81
decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'),
82
decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'),
83
decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
84
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
85
'tlb_helper.c',
86
'translate.c',
87
'translate-m-nocp.c',
88
+ 'translate-vfp.c',
89
'vec_helper.c',
90
'vfp_helper.c',
91
'cpu_tcg.c',
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
Deleted patch
1
The function vfp_reg_ptr() is used only in translate-neon.c.inc;
2
move it there.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210430132740.10391-10-peter.maydell@linaro.org
8
---
9
target/arm/translate.c | 7 -------
10
target/arm/translate-neon.c.inc | 7 +++++++
11
2 files changed, 7 insertions(+), 7 deletions(-)
12
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
16
+++ b/target/arm/translate.c
17
@@ -XXX,XX +XXX,XX @@ void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
18
}
19
}
20
21
-static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
22
-{
23
- TCGv_ptr ret = tcg_temp_new_ptr();
24
- tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
25
- return ret;
26
-}
27
-
28
#define ARM_CP_RW_BIT (1 << 20)
29
30
/* Include the Neon decoder */
31
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-neon.c.inc
34
+++ b/target/arm/translate-neon.c.inc
35
@@ -XXX,XX +XXX,XX @@ static inline int neon_3same_fp_size(DisasContext *s, int x)
36
#include "decode-neon-ls.c.inc"
37
#include "decode-neon-shared.c.inc"
38
39
+static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
40
+{
41
+ TCGv_ptr ret = tcg_temp_new_ptr();
42
+ tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
43
+ return ret;
44
+}
45
+
46
static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop)
47
{
48
long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
49
--
50
2.20.1
51
52
diff view generated by jsdifflib
Deleted patch
1
The VFPGenFixPointFn typedef is unused; delete it.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210430132740.10391-11-peter.maydell@linaro.org
7
---
8
target/arm/translate.c | 2 --
9
1 file changed, 2 deletions(-)
10
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static const char * const regnames[] =
16
/* Function prototypes for gen_ functions calling Neon helpers. */
17
typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
18
TCGv_i32, TCGv_i32);
19
-/* Function prototypes for gen_ functions for fix point conversions */
20
-typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
21
22
/* initialize TCG globals. */
23
void arm_translate_init(void)
24
--
25
2.20.1
26
27
diff view generated by jsdifflib
Deleted patch
1
Move the NeonGenThreeOpEnvFn typedef to translate.h together
2
with the other similar typedefs.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210430132740.10391-12-peter.maydell@linaro.org
8
---
9
target/arm/translate.h | 2 ++
10
target/arm/translate.c | 3 ---
11
2 files changed, 2 insertions(+), 3 deletions(-)
12
13
diff --git a/target/arm/translate.h b/target/arm/translate.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.h
16
+++ b/target/arm/translate.h
17
@@ -XXX,XX +XXX,XX @@ typedef void NeonGenOneOpFn(TCGv_i32, TCGv_i32);
18
typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
19
typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
20
typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
21
+typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
22
+ TCGv_i32, TCGv_i32);
23
typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
24
typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
25
typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
26
diff --git a/target/arm/translate.c b/target/arm/translate.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/translate.c
29
+++ b/target/arm/translate.c
30
@@ -XXX,XX +XXX,XX @@ static const char * const regnames[] =
31
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
32
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
33
34
-/* Function prototypes for gen_ functions calling Neon helpers. */
35
-typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
36
- TCGv_i32, TCGv_i32);
37
38
/* initialize TCG globals. */
39
void arm_translate_init(void)
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
Deleted patch
1
Make the remaining functions needed by the translate-neon code
2
global.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210430132740.10391-13-peter.maydell@linaro.org
8
---
9
target/arm/translate-a32.h | 8 ++++++++
10
target/arm/translate.c | 10 ++--------
11
2 files changed, 10 insertions(+), 8 deletions(-)
12
13
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a32.h
16
+++ b/target/arm/translate-a32.h
17
@@ -XXX,XX +XXX,XX @@ void gen_set_pc_im(DisasContext *s, target_ulong val);
18
void gen_lookup_tb(DisasContext *s);
19
long vfp_reg_offset(bool dp, unsigned reg);
20
long neon_full_reg_offset(unsigned reg);
21
+long neon_element_offset(int reg, int element, MemOp memop);
22
+void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
23
24
static inline TCGv_i32 load_cpu_offset(int offset)
25
{
26
@@ -XXX,XX +XXX,XX @@ DO_GEN_ST(32, MO_UL)
27
/* Set NZCV flags from the high 4 bits of var. */
28
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
29
30
+/* Swap low and high halfwords. */
31
+static inline void gen_swap_half(TCGv_i32 dest, TCGv_i32 var)
32
+{
33
+ tcg_gen_rotri_i32(dest, var, 16);
34
+}
35
+
36
#endif
37
diff --git a/target/arm/translate.c b/target/arm/translate.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate.c
40
+++ b/target/arm/translate.c
41
@@ -XXX,XX +XXX,XX @@ static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
42
}
43
44
/* Byteswap each halfword. */
45
-static void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
46
+void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
47
{
48
TCGv_i32 tmp = tcg_temp_new_i32();
49
TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
50
@@ -XXX,XX +XXX,XX @@ static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
51
tcg_gen_ext16s_i32(dest, var);
52
}
53
54
-/* Swap low and high halfwords. */
55
-static void gen_swap_half(TCGv_i32 dest, TCGv_i32 var)
56
-{
57
- tcg_gen_rotri_i32(dest, var, 16);
58
-}
59
-
60
/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
61
tmp = (t0 ^ t1) & 0x8000;
62
t0 &= ~0x8000;
63
@@ -XXX,XX +XXX,XX @@ long neon_full_reg_offset(unsigned reg)
64
* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
65
* where 0 is the least significant end of the register.
66
*/
67
-static long neon_element_offset(int reg, int element, MemOp memop)
68
+long neon_element_offset(int reg, int element, MemOp memop)
69
{
70
int element_size = 1 << (memop & MO_SIZE);
71
int ofs = element * element_size;
72
--
73
2.20.1
74
75
diff view generated by jsdifflib
Deleted patch
1
Switch translate-neon.c.inc from being #included into translate.c
2
to being its own compilation unit.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210430132740.10391-14-peter.maydell@linaro.org
8
---
9
target/arm/translate-a32.h | 3 +++
10
.../arm/{translate-neon.c.inc => translate-neon.c} | 12 +++++++-----
11
target/arm/translate.c | 3 ---
12
target/arm/meson.build | 7 ++++---
13
4 files changed, 14 insertions(+), 11 deletions(-)
14
rename target/arm/{translate-neon.c.inc => translate-neon.c} (99%)
15
16
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-a32.h
19
+++ b/target/arm/translate-a32.h
20
@@ -XXX,XX +XXX,XX @@
21
bool disas_m_nocp(DisasContext *dc, uint32_t insn);
22
bool disas_vfp(DisasContext *s, uint32_t insn);
23
bool disas_vfp_uncond(DisasContext *s, uint32_t insn);
24
+bool disas_neon_dp(DisasContext *s, uint32_t insn);
25
+bool disas_neon_ls(DisasContext *s, uint32_t insn);
26
+bool disas_neon_shared(DisasContext *s, uint32_t insn);
27
28
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
29
void arm_gen_condlabel(DisasContext *s);
30
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c
31
similarity index 99%
32
rename from target/arm/translate-neon.c.inc
33
rename to target/arm/translate-neon.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-neon.c.inc
36
+++ b/target/arm/translate-neon.c
37
@@ -XXX,XX +XXX,XX @@
38
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
39
*/
40
41
-/*
42
- * This file is intended to be included from translate.c; it uses
43
- * some macros and definitions provided by that file.
44
- * It might be possible to convert it to a standalone .c file eventually.
45
- */
46
+#include "qemu/osdep.h"
47
+#include "tcg/tcg-op.h"
48
+#include "tcg/tcg-op-gvec.h"
49
+#include "exec/exec-all.h"
50
+#include "exec/gen-icount.h"
51
+#include "translate.h"
52
+#include "translate-a32.h"
53
54
static inline int plus1(DisasContext *s, int x)
55
{
56
diff --git a/target/arm/translate.c b/target/arm/translate.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate.c
59
+++ b/target/arm/translate.c
60
@@ -XXX,XX +XXX,XX @@ void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
61
62
#define ARM_CP_RW_BIT (1 << 20)
63
64
-/* Include the Neon decoder */
65
-#include "translate-neon.c.inc"
66
-
67
static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
68
{
69
tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
70
diff --git a/target/arm/meson.build b/target/arm/meson.build
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/meson.build
73
+++ b/target/arm/meson.build
74
@@ -XXX,XX +XXX,XX @@
75
gen = [
76
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
77
- decodetree.process('neon-shared.decode', extra_args: '--static-decode=disas_neon_shared'),
78
- decodetree.process('neon-dp.decode', extra_args: '--static-decode=disas_neon_dp'),
79
- decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'),
80
+ decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
81
+ decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
82
+ decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
83
decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'),
84
decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'),
85
decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'),
86
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
87
'tlb_helper.c',
88
'translate.c',
89
'translate-m-nocp.c',
90
+ 'translate-neon.c',
91
'translate-vfp.c',
92
'vec_helper.c',
93
'vfp_helper.c',
94
--
95
2.20.1
96
97
diff view generated by jsdifflib
Deleted patch
1
The WFI insn is not system-mode only, though it doesn't usually make
2
a huge amount of sense for userspace code to execute it. Currently
3
if you try it in qemu-arm then the helper function will raise an
4
EXCP_HLT exception, which is not covered by the switch in cpu_loop()
5
and results in an abort:
6
1
7
qemu: unhandled CPU exception 0x10001 - aborting
8
R00=00000001 R01=408003e4 R02=408003ec R03=000102ec
9
R04=00010a28 R05=00010158 R06=00087460 R07=00010158
10
R08=00000000 R09=00000000 R10=00085b7c R11=408002a4
11
R12=408002b8 R13=408002a0 R14=0001057c R15=000102f8
12
PSR=60000010 -ZC- A usr32
13
qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x7fcbfa4f0a12
14
15
Make the WFI helper function return immediately in the usermode
16
emulator. This turns WFI into a NOP, which is OK because:
17
* architecturally "WFI is a NOP" is a permitted implementation
18
* aarch64 Linux kernels use the SCTLR_EL1.nTWI bit to trap
19
userspace WFI and NOP it (though aarch32 kernels currently
20
just let WFI do whatever it would do)
21
22
We could in theory make the translate.c code special case user-mode
23
emulation and NOP the insn entirely rather than making the helper
24
do nothing, but because no real world code will be trying to
25
execute WFI we don't care about efficiency and the helper provides
26
a single place where we can make the change rather than having
27
to touch multiple places in translate.c and translate-a64.c.
28
29
Fixes: https://bugs.launchpad.net/qemu/+bug/1926759
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Message-id: 20210430162212.825-1-peter.maydell@linaro.org
33
---
34
target/arm/op_helper.c | 12 ++++++++++++
35
1 file changed, 12 insertions(+)
36
37
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/op_helper.c
40
+++ b/target/arm/op_helper.c
41
@@ -XXX,XX +XXX,XX @@ static inline int check_wfx_trap(CPUARMState *env, bool is_wfe)
42
43
void HELPER(wfi)(CPUARMState *env, uint32_t insn_len)
44
{
45
+#ifdef CONFIG_USER_ONLY
46
+ /*
47
+ * WFI in the user-mode emulator is technically permitted but not
48
+ * something any real-world code would do. AArch64 Linux kernels
49
+ * trap it via SCTRL_EL1.nTWI and make it an (expensive) NOP;
50
+ * AArch32 kernels don't trap it so it will delay a bit.
51
+ * For QEMU, make it NOP here, because trying to raise EXCP_HLT
52
+ * would trigger an abort.
53
+ */
54
+ return;
55
+#else
56
CPUState *cs = env_cpu(env);
57
int target_el = check_wfx_trap(env, false);
58
59
@@ -XXX,XX +XXX,XX @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len)
60
cs->exception_index = EXCP_HLT;
61
cs->halted = 1;
62
cpu_loop_exit(cs);
63
+#endif
64
}
65
66
void HELPER(wfe)(CPUARMState *env)
67
--
68
2.20.1
69
70
diff view generated by jsdifflib
Deleted patch
1
The omap_mmc_reset() function resets its SD card via
2
device_legacy_reset(). We know that the SD card does not have a qbus
3
of its own, so the new device_cold_reset() function (which resets
4
both the device and its child buses) is equivalent here to
5
device_legacy_reset() and we can just switch to the new API.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210430222348.8514-1-peter.maydell@linaro.org
10
---
11
hw/sd/omap_mmc.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/sd/omap_mmc.c
17
+++ b/hw/sd/omap_mmc.c
18
@@ -XXX,XX +XXX,XX @@ void omap_mmc_reset(struct omap_mmc_s *host)
19
* into any bus, and we must reset it manually. When omap_mmc is
20
* QOMified this must move into the QOM reset function.
21
*/
22
- device_legacy_reset(DEVICE(host->card));
23
+ device_cold_reset(DEVICE(host->card));
24
}
25
26
static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
27
--
28
2.20.1
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The i.MX25 PDK board has 2 banks for SDRAM, each can
4
address up to 256 MiB. So the total RAM usable for this
5
board is 512M. When we ask for more we get a misleading
6
error message:
7
8
$ qemu-system-arm -M imx25-pdk -m 513M
9
qemu-system-arm: Invalid RAM size, should be 128 MiB
10
11
Update the error message to better match the reality:
12
13
$ qemu-system-arm -M imx25-pdk -m 513M
14
qemu-system-arm: RAM size more than 512 MiB is not supported
15
16
Fixes: bf350daae02 ("arm/imx25_pdk: drop RAM size fixup")
17
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
20
Message-id: 20210407225608.1882855-1-f4bug@amsat.org
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/arm/imx25_pdk.c | 5 ++---
24
1 file changed, 2 insertions(+), 3 deletions(-)
25
26
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/imx25_pdk.c
29
+++ b/hw/arm/imx25_pdk.c
30
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info imx25_pdk_binfo;
31
32
static void imx25_pdk_init(MachineState *machine)
33
{
34
- MachineClass *mc = MACHINE_GET_CLASS(machine);
35
IMX25PDK *s = g_new0(IMX25PDK, 1);
36
unsigned int ram_size;
37
unsigned int alias_offset;
38
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_init(MachineState *machine)
39
40
/* We need to initialize our memory */
41
if (machine->ram_size > (FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE)) {
42
- char *sz = size_to_str(mc->default_ram_size);
43
- error_report("Invalid RAM size, should be %s", sz);
44
+ char *sz = size_to_str(FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE);
45
+ error_report("RAM size more than %s is not supported", sz);
46
g_free(sz);
47
exit(EXIT_FAILURE);
48
}
49
--
50
2.20.1
51
52
diff view generated by jsdifflib