1
ARM queu; includes all the NVIC rewrite patches.
1
target-arm queue: the big stuff here is the final part of
2
The QOMify-armv7m patchset hasn't got enough review just
2
rth's patches for Cortex-A76 and Neoverse-N1 support;
3
yet but I may be able to sneak it in before freeze
3
also present are Gavin's NUMA series and a few other things.
4
tomorrow if it gets review. Didn't want to hold this lot
5
up waiting, anyway.
6
4
7
thanks
5
thanks
8
-- PMM
6
-- PMM
9
7
8
The following changes since commit 554623226f800acf48a2ed568900c1c968ec9a8b:
10
9
11
The following changes since commit 8f2d7c341184a95d05476ea3c45dbae2b9ddbe51:
10
Merge tag 'qemu-sparc-20220508' of https://github.com/mcayland/qemu into staging (2022-05-08 17:03:26 -0500)
12
11
13
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-02-27-1' into staging (2017-02-27 15:33:21 +0000)
12
are available in the Git repository at:
14
13
15
are available in the git repository at:
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220509
16
15
17
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170227
16
for you to fetch changes up to ae9141d4a3265553503bf07d3574b40f84615a34:
18
17
19
for you to fetch changes up to 94d5bcf5a7f3799660b62098a5183f161aad0601:
18
hw/acpi/aml-build: Use existing CPU topology to build PPTT table (2022-05-09 11:47:55 +0100)
20
21
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID (2017-02-27 17:23:16 +0000)
22
19
23
----------------------------------------------------------------
20
----------------------------------------------------------------
24
target-arm queue:
21
target-arm queue:
25
* raspi2: implement RNG module, GPIO and new SD card controller
22
* MAINTAINERS/.mailmap: update email for Leif Lindholm
26
(sufficient to boot new raspbian kernels)
23
* hw/arm: add version information to sbsa-ref machine DT
27
* sdhci: bugfixes for block transfers
24
* Enable new features for -cpu max:
28
* virt: fix cpu object reference leak
25
FEAT_Debugv8p2, FEAT_Debugv8p4, FEAT_RAS (minimal version only),
29
* Add missing fp_access_check() to aarch64 crypto instructions
26
FEAT_IESB, FEAT_CSV2, FEAT_CSV2_2, FEAT_CSV3, FEAT_DGH
30
* cputlb: Don't assume do_unassigned_access() never returns
27
* Emulate Cortex-A76
31
* virt: Add a user option to disallow ITS instantiation
28
* Emulate Neoverse-N1
32
* i.MX timers: fix reset handling
29
* Fix the virt board default NUMA topology
33
* ARMv7M NVIC: rewrite to fix broken priority handling and masking
34
* exynos: Fix proper mapping of CPUs by providing real cluster ID
35
* exynos: Fix Linux kernel division by zero for PLLs
36
30
37
----------------------------------------------------------------
31
----------------------------------------------------------------
38
Clement Deschamps (4):
32
Gavin Shan (6):
39
bcm2835_sdhost: add bcm2835 sdhost controller
33
qapi/machine.json: Add cluster-id
40
hw/sd: add card-reparenting function
34
qtest/numa-test: Specify CPU topology in aarch64_numa_cpu()
41
bcm2835_gpio: add bcm2835 gpio controller
35
hw/arm/virt: Consider SMP configuration in CPU topology
42
bcm2835: add sdhost and gpio controllers
36
qtest/numa-test: Correct CPU and NUMA association in aarch64_numa_cpu()
37
hw/arm/virt: Fix CPU's default NUMA node ID
38
hw/acpi/aml-build: Use existing CPU topology to build PPTT table
43
39
44
Eric Auger (1):
40
Leif Lindholm (2):
45
hw/arm/virt: Add a user option to disallow ITS instantiation
41
MAINTAINERS/.mailmap: update email for Leif Lindholm
42
hw/arm: add versioning to sbsa-ref machine DT
46
43
47
Igor Mammedov (1):
44
Richard Henderson (24):
48
hw/arm/virt: fix cpu object reference leak
45
target/arm: Handle cpreg registration for missing EL
46
target/arm: Drop EL3 no EL2 fallbacks
47
target/arm: Merge zcr reginfo
48
target/arm: Adjust definition of CONTEXTIDR_EL2
49
target/arm: Move cortex impdef sysregs to cpu_tcg.c
50
target/arm: Update qemu-system-arm -cpu max to cortex-a57
51
target/arm: Set ID_DFR0.PerfMon for qemu-system-arm -cpu max
52
target/arm: Split out aa32_max_features
53
target/arm: Annotate arm_max_initfn with FEAT identifiers
54
target/arm: Use field names for manipulating EL2 and EL3 modes
55
target/arm: Enable FEAT_Debugv8p2 for -cpu max
56
target/arm: Enable FEAT_Debugv8p4 for -cpu max
57
target/arm: Add minimal RAS registers
58
target/arm: Enable SCR and HCR bits for RAS
59
target/arm: Implement virtual SError exceptions
60
target/arm: Implement ESB instruction
61
target/arm: Enable FEAT_RAS for -cpu max
62
target/arm: Enable FEAT_IESB for -cpu max
63
target/arm: Enable FEAT_CSV2 for -cpu max
64
target/arm: Enable FEAT_CSV2_2 for -cpu max
65
target/arm: Enable FEAT_CSV3 for -cpu max
66
target/arm: Enable FEAT_DGH for -cpu max
67
target/arm: Define cortex-a76
68
target/arm: Define neoverse-n1
49
69
50
Krzysztof Kozlowski (2):
70
docs/system/arm/emulation.rst | 10 +
51
hw/arm/exynos: Fix Linux kernel division by zero for PLLs
71
docs/system/arm/virt.rst | 2 +
52
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID
72
qapi/machine.json | 6 +-
53
73
target/arm/cpregs.h | 11 +
54
Kurban Mallachiev (1):
74
target/arm/cpu.h | 23 ++
55
ARM i.MX timers: fix reset handling
75
target/arm/helper.h | 1 +
56
76
target/arm/internals.h | 16 ++
57
Marcin Chojnacki (1):
77
target/arm/syndrome.h | 5 +
58
target-arm: Implement BCM2835 hardware RNG
78
target/arm/a32.decode | 16 +-
59
79
target/arm/t32.decode | 18 +-
60
Michael Davidsaver (5):
80
hw/acpi/aml-build.c | 111 ++++----
61
armv7m: Rewrite NVIC to not use any GIC code
81
hw/arm/sbsa-ref.c | 16 ++
62
arm: gic: Remove references to NVIC
82
hw/arm/virt.c | 21 +-
63
armv7m: Escalate exceptions to HardFault if necessary
83
hw/core/machine-hmp-cmds.c | 4 +
64
armv7m: Simpler and faster exception start
84
hw/core/machine.c | 16 ++
65
armv7m: VECTCLRACTIVE and VECTRESET are UNPREDICTABLE
85
target/arm/cpu.c | 66 ++++-
66
86
target/arm/cpu64.c | 353 ++++++++++++++-----------
67
Nick Reilly (1):
87
target/arm/cpu_tcg.c | 227 +++++++++++-----
68
Add missing fp_access_check() to aarch64 crypto instructions
88
target/arm/helper.c | 600 +++++++++++++++++++++++++-----------------
69
89
target/arm/op_helper.c | 43 +++
70
Peter Maydell (10):
90
target/arm/translate-a64.c | 18 ++
71
bcm2835_rng: Use qcrypto_random_bytes() rather than rand()
91
target/arm/translate.c | 23 ++
72
cputlb: Don't assume do_unassigned_access() never returns
92
tests/qtest/numa-test.c | 19 +-
73
armv7m: Rename nvic_state to NVICState
93
.mailmap | 3 +-
74
armv7m: Implement reading and writing of PRIGROUP
94
MAINTAINERS | 2 +-
75
armv7m: Fix condition check for taking exceptions
95
25 files changed, 1068 insertions(+), 562 deletions(-)
76
armv7m: Remove unused armv7m_nvic_acknowledge_irq() return value
77
armv7m: Extract "exception taken" code into functions
78
armv7m: Check exception return consistency
79
armv7m: Raise correct kind of UsageFault for attempts to execute ARM code
80
armv7m: Allow SHCSR writes to change pending and active bits
81
82
Prasad J Pandit (4):
83
sd: sdhci: mask transfer mode register value
84
sd: sdhci: check transfer mode register in multi block transfer
85
sd: sdhci: conditionally invoke multi block transfer
86
sd: sdhci: Remove block count enable check in single block transfers
87
88
hw/gpio/Makefile.objs | 1 +
89
hw/misc/Makefile.objs | 3 +-
90
hw/sd/Makefile.objs | 1 +
91
hw/intc/gic_internal.h | 7 +-
92
include/hw/arm/bcm2835_peripherals.h | 6 +
93
include/hw/arm/virt.h | 1 +
94
include/hw/gpio/bcm2835_gpio.h | 39 ++
95
include/hw/misc/bcm2835_rng.h | 27 ++
96
include/hw/sd/bcm2835_sdhost.h | 48 ++
97
include/hw/sd/sd.h | 11 +
98
target/arm/cpu.h | 23 +-
99
cputlb.c | 15 +-
100
hw/arm/bcm2835_peripherals.c | 58 ++-
101
hw/arm/exynos4210.c | 18 +
102
hw/arm/virt.c | 32 +-
103
hw/gpio/bcm2835_gpio.c | 353 ++++++++++++++
104
hw/intc/arm_gic.c | 31 +-
105
hw/intc/arm_gic_common.c | 23 +-
106
hw/intc/armv7m_nvic.c | 885 ++++++++++++++++++++++++++++-------
107
hw/misc/bcm2835_rng.c | 149 ++++++
108
hw/misc/exynos4210_clk.c | 164 +++++++
109
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++
110
hw/sd/core.c | 30 ++
111
hw/sd/sdhci.c | 25 +-
112
hw/timer/imx_gpt.c | 33 +-
113
linux-user/main.c | 1 +
114
target/arm/cpu.c | 16 +-
115
target/arm/helper.c | 245 +++++++---
116
target/arm/translate-a64.c | 12 +
117
target/arm/translate.c | 8 +-
118
hw/intc/trace-events | 15 +
119
31 files changed, 2376 insertions(+), 333 deletions(-)
120
create mode 100644 include/hw/gpio/bcm2835_gpio.h
121
create mode 100644 include/hw/misc/bcm2835_rng.h
122
create mode 100644 include/hw/sd/bcm2835_sdhost.h
123
create mode 100644 hw/gpio/bcm2835_gpio.c
124
create mode 100644 hw/misc/bcm2835_rng.c
125
create mode 100644 hw/misc/exynos4210_clk.c
126
create mode 100644 hw/sd/bcm2835_sdhost.c
127
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
This adds the BCM2835 GPIO controller.
3
NUVIA was acquired by Qualcomm in March 2021, but kept functioning on
4
separate infrastructure for a transitional period. We've now switched
5
over to contributing as Qualcomm Innovation Center (quicinc), so update
6
my email address to reflect this.
4
7
5
It currently implements:
8
Signed-off-by: Leif Lindholm <quic_llindhol@quicinc.com>
6
- The 54 GPIOs as outputs (qemu_irq)
9
Message-id: 20220505113740.75565-1-quic_llindhol@quicinc.com
7
- The SD controller selection via alternate function of GPIOs 48-53
10
Cc: Leif Lindholm <leif@nuviainc.com>
8
11
Cc: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20170224164021.9066-4-clement.deschamps@antfield.fr
13
[Fixed commit message typo]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
15
---
14
hw/gpio/Makefile.objs | 1 +
16
.mailmap | 3 ++-
15
include/hw/gpio/bcm2835_gpio.h | 39 +++++
17
MAINTAINERS | 2 +-
16
hw/gpio/bcm2835_gpio.c | 353 +++++++++++++++++++++++++++++++++++++++++
18
2 files changed, 3 insertions(+), 2 deletions(-)
17
3 files changed, 393 insertions(+)
18
create mode 100644 include/hw/gpio/bcm2835_gpio.h
19
create mode 100644 hw/gpio/bcm2835_gpio.c
20
19
21
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
20
diff --git a/.mailmap b/.mailmap
22
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/gpio/Makefile.objs
22
--- a/.mailmap
24
+++ b/hw/gpio/Makefile.objs
23
+++ b/.mailmap
25
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
24
@@ -XXX,XX +XXX,XX @@ Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
26
25
Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
27
obj-$(CONFIG_OMAP) += omap_gpio.o
26
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
28
obj-$(CONFIG_IMX) += imx_gpio.o
27
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
29
+obj-$(CONFIG_RASPI) += bcm2835_gpio.o
28
-Leif Lindholm <leif@nuviainc.com> <leif.lindholm@linaro.org>
30
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
29
+Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
31
new file mode 100644
30
+Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
32
index XXXXXXX..XXXXXXX
31
Radoslaw Biernacki <rad@semihalf.com> <radoslaw.biernacki@linaro.org>
33
--- /dev/null
32
Paul Burton <paulburton@kernel.org> <paul.burton@mips.com>
34
+++ b/include/hw/gpio/bcm2835_gpio.h
33
Paul Burton <paulburton@kernel.org> <paul.burton@imgtec.com>
35
@@ -XXX,XX +XXX,XX @@
34
diff --git a/MAINTAINERS b/MAINTAINERS
36
+/*
35
index XXXXXXX..XXXXXXX 100644
37
+ * Raspberry Pi (BCM2835) GPIO Controller
36
--- a/MAINTAINERS
38
+ *
37
+++ b/MAINTAINERS
39
+ * Copyright (c) 2017 Antfield SAS
38
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
40
+ *
39
SBSA-REF
41
+ * Authors:
40
M: Radoslaw Biernacki <rad@semihalf.com>
42
+ * Clement Deschamps <clement.deschamps@antfield.fr>
41
M: Peter Maydell <peter.maydell@linaro.org>
43
+ * Luc Michel <luc.michel@antfield.fr>
42
-R: Leif Lindholm <leif@nuviainc.com>
44
+ *
43
+R: Leif Lindholm <quic_llindhol@quicinc.com>
45
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
44
L: qemu-arm@nongnu.org
46
+ * See the COPYING file in the top-level directory.
45
S: Maintained
47
+ */
46
F: hw/arm/sbsa-ref.c
48
+
49
+#ifndef BCM2835_GPIO_H
50
+#define BCM2835_GPIO_H
51
+
52
+#include "hw/sd/sd.h"
53
+
54
+typedef struct BCM2835GpioState {
55
+ SysBusDevice parent_obj;
56
+
57
+ MemoryRegion iomem;
58
+
59
+ /* SDBus selector */
60
+ SDBus sdbus;
61
+ SDBus *sdbus_sdhci;
62
+ SDBus *sdbus_sdhost;
63
+
64
+ uint8_t fsel[54];
65
+ uint32_t lev0, lev1;
66
+ uint8_t sd_fsel;
67
+ qemu_irq out[54];
68
+} BCM2835GpioState;
69
+
70
+#define TYPE_BCM2835_GPIO "bcm2835_gpio"
71
+#define BCM2835_GPIO(obj) \
72
+ OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO)
73
+
74
+#endif
75
diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c
76
new file mode 100644
77
index XXXXXXX..XXXXXXX
78
--- /dev/null
79
+++ b/hw/gpio/bcm2835_gpio.c
80
@@ -XXX,XX +XXX,XX @@
81
+/*
82
+ * Raspberry Pi (BCM2835) GPIO Controller
83
+ *
84
+ * Copyright (c) 2017 Antfield SAS
85
+ *
86
+ * Authors:
87
+ * Clement Deschamps <clement.deschamps@antfield.fr>
88
+ * Luc Michel <luc.michel@antfield.fr>
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
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qemu/timer.h"
97
+#include "qapi/error.h"
98
+#include "hw/sysbus.h"
99
+#include "hw/sd/sd.h"
100
+#include "hw/gpio/bcm2835_gpio.h"
101
+
102
+#define GPFSEL0 0x00
103
+#define GPFSEL1 0x04
104
+#define GPFSEL2 0x08
105
+#define GPFSEL3 0x0C
106
+#define GPFSEL4 0x10
107
+#define GPFSEL5 0x14
108
+#define GPSET0 0x1C
109
+#define GPSET1 0x20
110
+#define GPCLR0 0x28
111
+#define GPCLR1 0x2C
112
+#define GPLEV0 0x34
113
+#define GPLEV1 0x38
114
+#define GPEDS0 0x40
115
+#define GPEDS1 0x44
116
+#define GPREN0 0x4C
117
+#define GPREN1 0x50
118
+#define GPFEN0 0x58
119
+#define GPFEN1 0x5C
120
+#define GPHEN0 0x64
121
+#define GPHEN1 0x68
122
+#define GPLEN0 0x70
123
+#define GPLEN1 0x74
124
+#define GPAREN0 0x7C
125
+#define GPAREN1 0x80
126
+#define GPAFEN0 0x88
127
+#define GPAFEN1 0x8C
128
+#define GPPUD 0x94
129
+#define GPPUDCLK0 0x98
130
+#define GPPUDCLK1 0x9C
131
+
132
+static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg)
133
+{
134
+ int i;
135
+ uint32_t value = 0;
136
+ for (i = 0; i < 10; i++) {
137
+ uint32_t index = 10 * reg + i;
138
+ if (index < sizeof(s->fsel)) {
139
+ value |= (s->fsel[index] & 0x7) << (3 * i);
140
+ }
141
+ }
142
+ return value;
143
+}
144
+
145
+static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value)
146
+{
147
+ int i;
148
+ for (i = 0; i < 10; i++) {
149
+ uint32_t index = 10 * reg + i;
150
+ if (index < sizeof(s->fsel)) {
151
+ int fsel = (value >> (3 * i)) & 0x7;
152
+ s->fsel[index] = fsel;
153
+ }
154
+ }
155
+
156
+ /* SD controller selection (48-53) */
157
+ if (s->sd_fsel != 0
158
+ && (s->fsel[48] == 0) /* SD_CLK_R */
159
+ && (s->fsel[49] == 0) /* SD_CMD_R */
160
+ && (s->fsel[50] == 0) /* SD_DATA0_R */
161
+ && (s->fsel[51] == 0) /* SD_DATA1_R */
162
+ && (s->fsel[52] == 0) /* SD_DATA2_R */
163
+ && (s->fsel[53] == 0) /* SD_DATA3_R */
164
+ ) {
165
+ /* SDHCI controller selected */
166
+ sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
167
+ s->sd_fsel = 0;
168
+ } else if (s->sd_fsel != 4
169
+ && (s->fsel[48] == 4) /* SD_CLK_R */
170
+ && (s->fsel[49] == 4) /* SD_CMD_R */
171
+ && (s->fsel[50] == 4) /* SD_DATA0_R */
172
+ && (s->fsel[51] == 4) /* SD_DATA1_R */
173
+ && (s->fsel[52] == 4) /* SD_DATA2_R */
174
+ && (s->fsel[53] == 4) /* SD_DATA3_R */
175
+ ) {
176
+ /* SDHost controller selected */
177
+ sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
178
+ s->sd_fsel = 4;
179
+ }
180
+}
181
+
182
+static int gpfsel_is_out(BCM2835GpioState *s, int index)
183
+{
184
+ if (index >= 0 && index < 54) {
185
+ return s->fsel[index] == 1;
186
+ }
187
+ return 0;
188
+}
189
+
190
+static void gpset(BCM2835GpioState *s,
191
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
192
+{
193
+ uint32_t changes = val & ~*lev;
194
+ uint32_t cur = 1;
195
+
196
+ int i;
197
+ for (i = 0; i < count; i++) {
198
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
199
+ qemu_set_irq(s->out[start + i], 1);
200
+ }
201
+ cur <<= 1;
202
+ }
203
+
204
+ *lev |= val;
205
+}
206
+
207
+static void gpclr(BCM2835GpioState *s,
208
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
209
+{
210
+ uint32_t changes = val & *lev;
211
+ uint32_t cur = 1;
212
+
213
+ int i;
214
+ for (i = 0; i < count; i++) {
215
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
216
+ qemu_set_irq(s->out[start + i], 0);
217
+ }
218
+ cur <<= 1;
219
+ }
220
+
221
+ *lev &= ~val;
222
+}
223
+
224
+static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset,
225
+ unsigned size)
226
+{
227
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
228
+
229
+ switch (offset) {
230
+ case GPFSEL0:
231
+ case GPFSEL1:
232
+ case GPFSEL2:
233
+ case GPFSEL3:
234
+ case GPFSEL4:
235
+ case GPFSEL5:
236
+ return gpfsel_get(s, offset / 4);
237
+ case GPSET0:
238
+ case GPSET1:
239
+ /* Write Only */
240
+ return 0;
241
+ case GPCLR0:
242
+ case GPCLR1:
243
+ /* Write Only */
244
+ return 0;
245
+ case GPLEV0:
246
+ return s->lev0;
247
+ case GPLEV1:
248
+ return s->lev1;
249
+ case GPEDS0:
250
+ case GPEDS1:
251
+ case GPREN0:
252
+ case GPREN1:
253
+ case GPFEN0:
254
+ case GPFEN1:
255
+ case GPHEN0:
256
+ case GPHEN1:
257
+ case GPLEN0:
258
+ case GPLEN1:
259
+ case GPAREN0:
260
+ case GPAREN1:
261
+ case GPAFEN0:
262
+ case GPAFEN1:
263
+ case GPPUD:
264
+ case GPPUDCLK0:
265
+ case GPPUDCLK1:
266
+ /* Not implemented */
267
+ return 0;
268
+ default:
269
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
270
+ __func__, offset);
271
+ break;
272
+ }
273
+
274
+ return 0;
275
+}
276
+
277
+static void bcm2835_gpio_write(void *opaque, hwaddr offset,
278
+ uint64_t value, unsigned size)
279
+{
280
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
281
+
282
+ switch (offset) {
283
+ case GPFSEL0:
284
+ case GPFSEL1:
285
+ case GPFSEL2:
286
+ case GPFSEL3:
287
+ case GPFSEL4:
288
+ case GPFSEL5:
289
+ gpfsel_set(s, offset / 4, value);
290
+ break;
291
+ case GPSET0:
292
+ gpset(s, value, 0, 32, &s->lev0);
293
+ break;
294
+ case GPSET1:
295
+ gpset(s, value, 32, 22, &s->lev1);
296
+ break;
297
+ case GPCLR0:
298
+ gpclr(s, value, 0, 32, &s->lev0);
299
+ break;
300
+ case GPCLR1:
301
+ gpclr(s, value, 32, 22, &s->lev1);
302
+ break;
303
+ case GPLEV0:
304
+ case GPLEV1:
305
+ /* Read Only */
306
+ break;
307
+ case GPEDS0:
308
+ case GPEDS1:
309
+ case GPREN0:
310
+ case GPREN1:
311
+ case GPFEN0:
312
+ case GPFEN1:
313
+ case GPHEN0:
314
+ case GPHEN1:
315
+ case GPLEN0:
316
+ case GPLEN1:
317
+ case GPAREN0:
318
+ case GPAREN1:
319
+ case GPAFEN0:
320
+ case GPAFEN1:
321
+ case GPPUD:
322
+ case GPPUDCLK0:
323
+ case GPPUDCLK1:
324
+ /* Not implemented */
325
+ break;
326
+ default:
327
+ goto err_out;
328
+ }
329
+ return;
330
+
331
+err_out:
332
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
333
+ __func__, offset);
334
+}
335
+
336
+static void bcm2835_gpio_reset(DeviceState *dev)
337
+{
338
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
339
+
340
+ int i;
341
+ for (i = 0; i < 6; i++) {
342
+ gpfsel_set(s, i, 0);
343
+ }
344
+
345
+ s->sd_fsel = 0;
346
+
347
+ /* SDHCI is selected by default */
348
+ sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci);
349
+
350
+ s->lev0 = 0;
351
+ s->lev1 = 0;
352
+}
353
+
354
+static const MemoryRegionOps bcm2835_gpio_ops = {
355
+ .read = bcm2835_gpio_read,
356
+ .write = bcm2835_gpio_write,
357
+ .endianness = DEVICE_NATIVE_ENDIAN,
358
+};
359
+
360
+static const VMStateDescription vmstate_bcm2835_gpio = {
361
+ .name = "bcm2835_gpio",
362
+ .version_id = 1,
363
+ .minimum_version_id = 1,
364
+ .fields = (VMStateField[]) {
365
+ VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54),
366
+ VMSTATE_UINT32(lev0, BCM2835GpioState),
367
+ VMSTATE_UINT32(lev1, BCM2835GpioState),
368
+ VMSTATE_UINT8(sd_fsel, BCM2835GpioState),
369
+ VMSTATE_END_OF_LIST()
370
+ }
371
+};
372
+
373
+static void bcm2835_gpio_init(Object *obj)
374
+{
375
+ BCM2835GpioState *s = BCM2835_GPIO(obj);
376
+ DeviceState *dev = DEVICE(obj);
377
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
378
+
379
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
380
+ TYPE_SD_BUS, DEVICE(s), "sd-bus");
381
+
382
+ memory_region_init_io(&s->iomem, obj,
383
+ &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000);
384
+ sysbus_init_mmio(sbd, &s->iomem);
385
+ qdev_init_gpio_out(dev, s->out, 54);
386
+}
387
+
388
+static void bcm2835_gpio_realize(DeviceState *dev, Error **errp)
389
+{
390
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
391
+ Object *obj;
392
+ Error *err = NULL;
393
+
394
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err);
395
+ if (obj == NULL) {
396
+ error_setg(errp, "%s: required sdhci link not found: %s",
397
+ __func__, error_get_pretty(err));
398
+ return;
399
+ }
400
+ s->sdbus_sdhci = SD_BUS(obj);
401
+
402
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err);
403
+ if (obj == NULL) {
404
+ error_setg(errp, "%s: required sdhost link not found: %s",
405
+ __func__, error_get_pretty(err));
406
+ return;
407
+ }
408
+ s->sdbus_sdhost = SD_BUS(obj);
409
+}
410
+
411
+static void bcm2835_gpio_class_init(ObjectClass *klass, void *data)
412
+{
413
+ DeviceClass *dc = DEVICE_CLASS(klass);
414
+
415
+ dc->vmsd = &vmstate_bcm2835_gpio;
416
+ dc->realize = &bcm2835_gpio_realize;
417
+ dc->reset = &bcm2835_gpio_reset;
418
+}
419
+
420
+static const TypeInfo bcm2835_gpio_info = {
421
+ .name = TYPE_BCM2835_GPIO,
422
+ .parent = TYPE_SYS_BUS_DEVICE,
423
+ .instance_size = sizeof(BCM2835GpioState),
424
+ .instance_init = bcm2835_gpio_init,
425
+ .class_init = bcm2835_gpio_class_init,
426
+};
427
+
428
+static void bcm2835_gpio_register_types(void)
429
+{
430
+ type_register_static(&bcm2835_gpio_info);
431
+}
432
+
433
+type_init(bcm2835_gpio_register_types)
434
--
47
--
435
2.7.4
48
2.25.1
436
49
437
50
diff view generated by jsdifflib
1
Implement the exception return consistency checks
1
From: Richard Henderson <richard.henderson@linaro.org>
2
described in the v7M pseudocode ExceptionReturn().
2
3
3
More gracefully handle cpregs when EL2 and/or EL3 are missing.
4
Inspired by a patch from Michael Davidsaver's series, but
4
If the reg is entirely inaccessible, do not register it at all.
5
this is a reimplementation from scratch based on the
5
If the reg is for EL2, and EL3 is present but EL2 is not,
6
ARM ARM pseudocode.
6
either discard, squash to res0, const, or keep unchanged.
7
7
8
Per rule RJFFP, mark the 4 aarch32 hypervisor access registers
9
with ARM_CP_EL3_NO_EL2_KEEP, and mark all of the EL2 address
10
translation and tlb invalidation "regs" ARM_CP_EL3_NO_EL2_UNDEF.
11
Mark the 2 virtualization processor id regs ARM_CP_EL3_NO_EL2_C_NZ.
12
13
This will simplify cpreg registration for conditional arm features.
14
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20220506180242.216785-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
---
19
---
11
target/arm/cpu.h | 12 +++++-
20
target/arm/cpregs.h | 11 +++
12
hw/intc/armv7m_nvic.c | 12 +++++-
21
target/arm/helper.c | 178 ++++++++++++++++++++++++++++++--------------
13
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++++++-----
22
2 files changed, 133 insertions(+), 56 deletions(-)
14
3 files changed, 123 insertions(+), 13 deletions(-)
23
15
24
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
26
--- a/target/arm/cpregs.h
19
+++ b/target/arm/cpu.h
27
+++ b/target/arm/cpregs.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
28
@@ -XXX,XX +XXX,XX @@ enum {
21
#endif
29
ARM_CP_SVE = 1 << 14,
22
void armv7m_nvic_set_pending(void *opaque, int irq);
30
/* Flag: Do not expose in gdb sysreg xml. */
23
void armv7m_nvic_acknowledge_irq(void *opaque);
31
ARM_CP_NO_GDB = 1 << 15,
24
-void armv7m_nvic_complete_irq(void *opaque, int irq);
32
+ /*
25
+/**
33
+ * Flags: If EL3 but not EL2...
26
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
34
+ * - UNDEF: discard the cpreg,
27
+ * @opaque: the NVIC
35
+ * - KEEP: retain the cpreg as is,
28
+ * @irq: the exception number to complete
36
+ * - C_NZ: set const on the cpreg, but retain resetvalue,
29
+ *
37
+ * - else: set const on the cpreg, zero resetvalue, aka RES0.
30
+ * Returns: -1 if the irq was not active
38
+ * See rule RJFFP in section D1.1.3 of DDI0487H.a.
31
+ * 1 if completing this irq brought us back to base (no active irqs)
39
+ */
32
+ * 0 if there is still an irq active after this one was completed
40
+ ARM_CP_EL3_NO_EL2_UNDEF = 1 << 16,
33
+ * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
41
+ ARM_CP_EL3_NO_EL2_KEEP = 1 << 17,
34
+ */
42
+ ARM_CP_EL3_NO_EL2_C_NZ = 1 << 18,
35
+int armv7m_nvic_complete_irq(void *opaque, int irq);
43
};
36
44
37
/* Interface for defining coprocessor registers.
45
/*
38
* Registers are defined in tables of arm_cp_reginfo structs
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque)
44
nvic_irq_update(s);
45
}
46
47
-void armv7m_nvic_complete_irq(void *opaque, int irq)
48
+int armv7m_nvic_complete_irq(void *opaque, int irq)
49
{
50
NVICState *s = (NVICState *)opaque;
51
VecInfo *vec;
52
+ int ret;
53
54
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
55
56
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
57
58
trace_nvic_complete_irq(irq);
59
60
+ if (!vec->active) {
61
+ /* Tell the caller this was an illegal exception return */
62
+ return -1;
63
+ }
64
+
65
+ ret = nvic_rettobase(s);
66
+
67
vec->active = 0;
68
if (vec->level) {
69
/* Re-pend the exception if it's still held high; only
70
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
71
}
72
73
nvic_irq_update(s);
74
+
75
+ return ret;
76
}
77
78
/* callback when external interrupt line is changed */
79
diff --git a/target/arm/helper.c b/target/arm/helper.c
46
diff --git a/target/arm/helper.c b/target/arm/helper.c
80
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/helper.c
48
--- a/target/arm/helper.c
82
+++ b/target/arm/helper.c
49
+++ b/target/arm/helper.c
83
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
50
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
84
v7m_push(env, env->regs[0]);
51
.access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write },
85
}
52
{ .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64,
86
53
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0,
87
-static void do_v7m_exception_exit(CPUARMState *env)
54
- .access = PL2_RW, .type = ARM_CP_ALIAS | ARM_CP_FPU,
88
+static void do_v7m_exception_exit(ARMCPU *cpu)
55
+ .access = PL2_RW,
56
+ .type = ARM_CP_ALIAS | ARM_CP_FPU | ARM_CP_EL3_NO_EL2_KEEP,
57
.fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) },
58
{ .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64,
59
.opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0,
60
- .access = PL2_RW, .resetvalue = 0,
61
+ .access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
62
.writefn = dacr_write, .raw_writefn = raw_write,
63
.fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) },
64
{ .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64,
65
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1,
66
- .access = PL2_RW, .resetvalue = 0,
67
+ .access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
68
.fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) },
69
{ .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64,
70
.type = ARM_CP_ALIAS,
71
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
72
.writefn = tlbimva_hyp_is_write },
73
{ .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64,
74
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
75
- .type = ARM_CP_NO_RAW, .access = PL2_W,
76
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
77
.writefn = tlbi_aa64_alle2_write },
78
{ .name = "TLBI_VAE2", .state = ARM_CP_STATE_AA64,
79
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
80
- .type = ARM_CP_NO_RAW, .access = PL2_W,
81
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
82
.writefn = tlbi_aa64_vae2_write },
83
{ .name = "TLBI_VALE2", .state = ARM_CP_STATE_AA64,
84
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
85
- .access = PL2_W, .type = ARM_CP_NO_RAW,
86
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
87
.writefn = tlbi_aa64_vae2_write },
88
{ .name = "TLBI_ALLE2IS", .state = ARM_CP_STATE_AA64,
89
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
90
- .access = PL2_W, .type = ARM_CP_NO_RAW,
91
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
92
.writefn = tlbi_aa64_alle2is_write },
93
{ .name = "TLBI_VAE2IS", .state = ARM_CP_STATE_AA64,
94
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
95
- .type = ARM_CP_NO_RAW, .access = PL2_W,
96
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
97
.writefn = tlbi_aa64_vae2is_write },
98
{ .name = "TLBI_VALE2IS", .state = ARM_CP_STATE_AA64,
99
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
100
- .access = PL2_W, .type = ARM_CP_NO_RAW,
101
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
102
.writefn = tlbi_aa64_vae2is_write },
103
#ifndef CONFIG_USER_ONLY
104
/* Unlike the other EL2-related AT operations, these must
105
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
106
{ .name = "AT_S1E2R", .state = ARM_CP_STATE_AA64,
107
.opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0,
108
.access = PL2_W, .accessfn = at_s1e2_access,
109
- .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, .writefn = ats_write64 },
110
+ .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDEF,
111
+ .writefn = ats_write64 },
112
{ .name = "AT_S1E2W", .state = ARM_CP_STATE_AA64,
113
.opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1,
114
.access = PL2_W, .accessfn = at_s1e2_access,
115
- .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, .writefn = ats_write64 },
116
+ .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDEF,
117
+ .writefn = ats_write64 },
118
/* The AArch32 ATS1H* operations are CONSTRAINED UNPREDICTABLE
119
* if EL2 is not implemented; we choose to UNDEF. Behaviour at EL3
120
* with SCR.NS == 0 outside Monitor mode is UNPREDICTABLE; we choose
121
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
122
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
123
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
124
.access = PL2_RW, .accessfn = access_tda,
125
- .type = ARM_CP_NOP },
126
+ .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
127
/* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
128
* Channel but Linux may try to access this register. The 32-bit
129
* alias is DBGDCCINT.
130
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
131
.access = PL2_W, .type = ARM_CP_NOP },
132
{ .name = "TLBI_RVAE2IS", .state = ARM_CP_STATE_AA64,
133
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 1,
134
- .access = PL2_W, .type = ARM_CP_NO_RAW,
135
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
136
.writefn = tlbi_aa64_rvae2is_write },
137
{ .name = "TLBI_RVALE2IS", .state = ARM_CP_STATE_AA64,
138
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 5,
139
- .access = PL2_W, .type = ARM_CP_NO_RAW,
140
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
141
.writefn = tlbi_aa64_rvae2is_write },
142
{ .name = "TLBI_RIPAS2E1", .state = ARM_CP_STATE_AA64,
143
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 2,
144
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
145
.access = PL2_W, .type = ARM_CP_NOP },
146
{ .name = "TLBI_RVAE2OS", .state = ARM_CP_STATE_AA64,
147
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 1,
148
- .access = PL2_W, .type = ARM_CP_NO_RAW,
149
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
150
.writefn = tlbi_aa64_rvae2is_write },
151
{ .name = "TLBI_RVALE2OS", .state = ARM_CP_STATE_AA64,
152
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 5,
153
- .access = PL2_W, .type = ARM_CP_NO_RAW,
154
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
155
.writefn = tlbi_aa64_rvae2is_write },
156
{ .name = "TLBI_RVAE2", .state = ARM_CP_STATE_AA64,
157
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 6, .opc2 = 1,
158
- .access = PL2_W, .type = ARM_CP_NO_RAW,
159
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
160
.writefn = tlbi_aa64_rvae2_write },
161
{ .name = "TLBI_RVALE2", .state = ARM_CP_STATE_AA64,
162
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 6, .opc2 = 5,
163
- .access = PL2_W, .type = ARM_CP_NO_RAW,
164
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
165
.writefn = tlbi_aa64_rvae2_write },
166
{ .name = "TLBI_RVAE3IS", .state = ARM_CP_STATE_AA64,
167
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 2, .opc2 = 1,
168
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = {
169
.writefn = tlbi_aa64_vae1is_write },
170
{ .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64,
171
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0,
172
- .access = PL2_W, .type = ARM_CP_NO_RAW,
173
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
174
.writefn = tlbi_aa64_alle2is_write },
175
{ .name = "TLBI_VAE2OS", .state = ARM_CP_STATE_AA64,
176
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 1,
177
- .access = PL2_W, .type = ARM_CP_NO_RAW,
178
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
179
.writefn = tlbi_aa64_vae2is_write },
180
{ .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64,
181
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4,
182
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = {
183
.writefn = tlbi_aa64_alle1is_write },
184
{ .name = "TLBI_VALE2OS", .state = ARM_CP_STATE_AA64,
185
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 5,
186
- .access = PL2_W, .type = ARM_CP_NO_RAW,
187
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
188
.writefn = tlbi_aa64_vae2is_write },
189
{ .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64,
190
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6,
191
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
192
{ .name = "VPIDR", .state = ARM_CP_STATE_AA32,
193
.cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0,
194
.access = PL2_RW, .accessfn = access_el3_aa32ns,
195
- .resetvalue = cpu->midr, .type = ARM_CP_ALIAS,
196
+ .resetvalue = cpu->midr,
197
+ .type = ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_C_NZ,
198
.fieldoffset = offsetoflow32(CPUARMState, cp15.vpidr_el2) },
199
{ .name = "VPIDR_EL2", .state = ARM_CP_STATE_AA64,
200
.opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0,
201
.access = PL2_RW, .resetvalue = cpu->midr,
202
+ .type = ARM_CP_EL3_NO_EL2_C_NZ,
203
.fieldoffset = offsetof(CPUARMState, cp15.vpidr_el2) },
204
{ .name = "VMPIDR", .state = ARM_CP_STATE_AA32,
205
.cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5,
206
.access = PL2_RW, .accessfn = access_el3_aa32ns,
207
- .resetvalue = vmpidr_def, .type = ARM_CP_ALIAS,
208
+ .resetvalue = vmpidr_def,
209
+ .type = ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_C_NZ,
210
.fieldoffset = offsetoflow32(CPUARMState, cp15.vmpidr_el2) },
211
{ .name = "VMPIDR_EL2", .state = ARM_CP_STATE_AA64,
212
.opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5,
213
- .access = PL2_RW,
214
- .resetvalue = vmpidr_def,
215
+ .access = PL2_RW, .resetvalue = vmpidr_def,
216
+ .type = ARM_CP_EL3_NO_EL2_C_NZ,
217
.fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
218
};
219
define_arm_cp_regs(cpu, vpidr_regs);
220
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
221
int crm, int opc1, int opc2,
222
const char *name)
89
{
223
{
90
+ CPUARMState *env = &cpu->env;
224
+ CPUARMState *env = &cpu->env;
91
uint32_t type;
225
uint32_t key;
92
uint32_t xpsr;
226
ARMCPRegInfo *r2;
93
-
227
bool is64 = r->type & ARM_CP_64BIT;
94
+ bool ufault = false;
228
bool ns = secstate & ARM_CP_SECSTATE_NS;
95
+ bool return_to_sp_process = false;
229
int cp = r->cp;
96
+ bool return_to_handler = false;
230
- bool isbanked;
97
+ bool rettobase = false;
231
size_t name_len;
98
+
232
+ bool make_const;
99
+ /* We can only get here from an EXCP_EXCEPTION_EXIT, and
233
100
+ * arm_v7m_do_unassigned_access() enforces the architectural rule
234
switch (state) {
101
+ * that jumps to magic addresses don't have magic behaviour unless
235
case ARM_CP_STATE_AA32:
102
+ * we're in Handler mode (compare pseudocode BXWritePC()).
236
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
237
}
238
}
239
240
+ /*
241
+ * Eliminate registers that are not present because the EL is missing.
242
+ * Doing this here makes it easier to put all registers for a given
243
+ * feature into the same ARMCPRegInfo array and define them all at once.
103
+ */
244
+ */
104
+ assert(env->v7m.exception != 0);
245
+ make_const = false;
105
+
246
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
106
+ /* In the spec pseudocode ExceptionReturn() is called directly
247
+ /*
107
+ * from BXWritePC() and gets the full target PC value including
248
+ * An EL2 register without EL2 but with EL3 is (usually) RES0.
108
+ * bit zero. In QEMU's implementation we treat it as a normal
249
+ * See rule RJFFP in section D1.1.3 of DDI0487H.a.
109
+ * jump-to-register (which is then caught later on), and so split
250
+ */
110
+ * the target value up between env->regs[15] and env->thumb in
251
+ int min_el = ctz32(r->access) / 2;
111
+ * gen_bx(). Reconstitute it.
252
+ if (min_el == 2 && !arm_feature(env, ARM_FEATURE_EL2)) {
112
+ */
253
+ if (r->type & ARM_CP_EL3_NO_EL2_UNDEF) {
113
type = env->regs[15];
254
+ return;
114
+ if (env->thumb) {
255
+ }
115
+ type |= 1;
256
+ make_const = !(r->type & ARM_CP_EL3_NO_EL2_KEEP);
257
+ }
258
+ } else {
259
+ CPAccessRights max_el = (arm_feature(env, ARM_FEATURE_EL2)
260
+ ? PL2_RW : PL1_RW);
261
+ if ((r->access & max_el) == 0) {
262
+ return;
263
+ }
116
+ }
264
+ }
117
+
265
+
118
+ qemu_log_mask(CPU_LOG_INT, "Exception return: magic PC %" PRIx32
266
/* Combine cpreg and name into one allocation. */
119
+ " previous exception %d\n",
267
name_len = strlen(name) + 1;
120
+ type, env->v7m.exception);
268
r2 = g_malloc(sizeof(*r2) + name_len);
121
+
269
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
122
+ if (extract32(type, 5, 23) != extract32(-1, 5, 23)) {
270
r2->opaque = opaque;
123
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero high bits in exception "
124
+ "exit PC value 0x%" PRIx32 " are UNPREDICTABLE\n", type);
125
+ }
126
+
127
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
128
/* Auto-clear FAULTMASK on return from other than NMI */
129
env->daif &= ~PSTATE_F;
130
}
271
}
131
- if (env->v7m.exception != 0) {
272
132
- armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
273
- isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
133
+
274
- if (isbanked) {
134
+ switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
275
+ if (make_const) {
135
+ case -1:
276
+ /* This should not have been a very special register to begin. */
136
+ /* attempt to exit an exception that isn't active */
277
+ int old_special = r2->type & ARM_CP_SPECIAL_MASK;
137
+ ufault = true;
278
+ assert(old_special == 0 || old_special == ARM_CP_NOP);
138
+ break;
279
/*
139
+ case 0:
280
- * Register is banked (using both entries in array).
140
+ /* still an irq active now */
281
- * Overwriting fieldoffset as the array is only used to define
141
+ break;
282
- * banked registers but later only fieldoffset is used.
142
+ case 1:
283
+ * Set the special function to CONST, retaining the other flags.
143
+ /* we returned to base exception level, no nesting.
284
+ * This is important for e.g. ARM_CP_SVE so that we still
144
+ * (In the pseudocode this is written using "NestedActivation != 1"
285
+ * take the SVE trap if CPTR_EL3.EZ == 0.
145
+ * where we have 'rettobase == false'.)
286
*/
287
- r2->fieldoffset = r->bank_fieldoffsets[ns];
288
- }
289
+ r2->type = (r2->type & ~ARM_CP_SPECIAL_MASK) | ARM_CP_CONST;
290
+ /*
291
+ * Usually, these registers become RES0, but there are a few
292
+ * special cases like VPIDR_EL2 which have a constant non-zero
293
+ * value with writes ignored.
146
+ */
294
+ */
147
+ rettobase = true;
295
+ if (!(r->type & ARM_CP_EL3_NO_EL2_C_NZ)) {
148
+ break;
296
+ r2->resetvalue = 0;
149
+ default:
150
+ g_assert_not_reached();
151
+ }
152
+
153
+ switch (type & 0xf) {
154
+ case 1: /* Return to Handler */
155
+ return_to_handler = true;
156
+ break;
157
+ case 13: /* Return to Thread using Process stack */
158
+ return_to_sp_process = true;
159
+ /* fall through */
160
+ case 9: /* Return to Thread using Main stack */
161
+ if (!rettobase &&
162
+ !(env->v7m.ccr & R_V7M_CCR_NONBASETHRDENA_MASK)) {
163
+ ufault = true;
164
+ }
297
+ }
165
+ break;
298
+ /*
166
+ default:
299
+ * ARM_CP_CONST has precedence, so removing the callbacks and
167
+ ufault = true;
300
+ * offsets are not strictly necessary, but it is potentially
168
+ }
301
+ * less confusing to debug later.
169
+
170
+ if (ufault) {
171
+ /* Bad exception return: instead of popping the exception
172
+ * stack, directly take a usage fault on the current stack.
173
+ */
302
+ */
174
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
303
+ r2->readfn = NULL;
175
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
304
+ r2->writefn = NULL;
176
+ v7m_exception_taken(cpu, type | 0xf0000000);
305
+ r2->raw_readfn = NULL;
177
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
306
+ r2->raw_writefn = NULL;
178
+ "stackframe: failed exception return integrity check\n");
307
+ r2->resetfn = NULL;
179
+ return;
308
+ r2->fieldoffset = 0;
309
+ r2->bank_fieldoffsets[0] = 0;
310
+ r2->bank_fieldoffsets[1] = 0;
311
+ } else {
312
+ bool isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
313
314
- if (state == ARM_CP_STATE_AA32) {
315
if (isbanked) {
316
/*
317
- * If the register is banked then we don't need to migrate or
318
- * reset the 32-bit instance in certain cases:
319
- *
320
- * 1) If the register has both 32-bit and 64-bit instances then we
321
- * can count on the 64-bit instance taking care of the
322
- * non-secure bank.
323
- * 2) If ARMv8 is enabled then we can count on a 64-bit version
324
- * taking care of the secure bank. This requires that separate
325
- * 32 and 64-bit definitions are provided.
326
+ * Register is banked (using both entries in array).
327
+ * Overwriting fieldoffset as the array is only used to define
328
+ * banked registers but later only fieldoffset is used.
329
*/
330
- if ((r->state == ARM_CP_STATE_BOTH && ns) ||
331
- (arm_feature(&cpu->env, ARM_FEATURE_V8) && !ns)) {
332
+ r2->fieldoffset = r->bank_fieldoffsets[ns];
333
+ }
334
+ if (state == ARM_CP_STATE_AA32) {
335
+ if (isbanked) {
336
+ /*
337
+ * If the register is banked then we don't need to migrate or
338
+ * reset the 32-bit instance in certain cases:
339
+ *
340
+ * 1) If the register has both 32-bit and 64-bit instances
341
+ * then we can count on the 64-bit instance taking care
342
+ * of the non-secure bank.
343
+ * 2) If ARMv8 is enabled then we can count on a 64-bit
344
+ * version taking care of the secure bank. This requires
345
+ * that separate 32 and 64-bit definitions are provided.
346
+ */
347
+ if ((r->state == ARM_CP_STATE_BOTH && ns) ||
348
+ (arm_feature(env, ARM_FEATURE_V8) && !ns)) {
349
+ r2->type |= ARM_CP_ALIAS;
350
+ }
351
+ } else if ((secstate != r->secure) && !ns) {
352
+ /*
353
+ * The register is not banked so we only want to allow
354
+ * migration of the non-secure instance.
355
+ */
356
r2->type |= ARM_CP_ALIAS;
357
}
358
- } else if ((secstate != r->secure) && !ns) {
359
- /*
360
- * The register is not banked so we only want to allow migration
361
- * of the non-secure instance.
362
- */
363
- r2->type |= ARM_CP_ALIAS;
364
- }
365
366
- if (HOST_BIG_ENDIAN &&
367
- r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
368
- r2->fieldoffset += sizeof(uint32_t);
369
+ if (HOST_BIG_ENDIAN &&
370
+ r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
371
+ r2->fieldoffset += sizeof(uint32_t);
372
+ }
373
}
180
}
374
}
181
375
182
/* Switch to the target stack. */
376
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
183
- switch_v7m_sp(env, (type & 4) != 0);
377
* multiple times. Special registers (ie NOP/WFI) are
184
+ switch_v7m_sp(env, return_to_sp_process);
378
* never migratable and not even raw-accessible.
185
/* Pop registers. */
379
*/
186
env->regs[0] = v7m_pop(env);
380
- if (r->type & ARM_CP_SPECIAL_MASK) {
187
env->regs[1] = v7m_pop(env);
381
+ if (r2->type & ARM_CP_SPECIAL_MASK) {
188
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(CPUARMState *env)
382
r2->type |= ARM_CP_NO_RAW;
189
/* Undo stack alignment. */
383
}
190
if (xpsr & 0x200)
384
if (((r->crm == CP_ANY) && crm != 0) ||
191
env->regs[13] |= 4;
192
- /* ??? The exception return type specifies Thread/Handler mode. However
193
- this is also implied by the xPSR value. Not sure what to do
194
- if there is a mismatch. */
195
- /* ??? Likewise for mismatches between the CONTROL register and the stack
196
- pointer. */
197
+
198
+ /* The restored xPSR exception field will be zero if we're
199
+ * resuming in Thread mode. If that doesn't match what the
200
+ * exception return type specified then this is a UsageFault.
201
+ */
202
+ if (return_to_handler == (env->v7m.exception == 0)) {
203
+ /* Take an INVPC UsageFault by pushing the stack again. */
204
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
205
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
206
+ v7m_push_stack(cpu);
207
+ v7m_exception_taken(cpu, type | 0xf0000000);
208
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
209
+ "failed exception return integrity check\n");
210
+ return;
211
+ }
212
+
213
+ /* Otherwise, we have a successful exception exit. */
214
+ qemu_log_mask(CPU_LOG_INT, "...successful exception return\n");
215
}
216
217
static void arm_log_exception(int idx)
218
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
219
case EXCP_IRQ:
220
break;
221
case EXCP_EXCEPTION_EXIT:
222
- do_v7m_exception_exit(env);
223
+ do_v7m_exception_exit(cpu);
224
return;
225
default:
226
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
227
--
385
--
228
2.7.4
386
2.25.1
229
230
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The v7M exception architecture requires that if a synchronous
3
Drop el3_no_el2_cp_reginfo, el3_no_el2_v8_cp_reginfo, and the local
4
exception cannot be taken immediately (because it is disabled
4
vpidr_regs definition, and rely on the squashing to ARM_CP_CONST
5
or at too low a priority) then it should be escalated to
5
while registering for v8.
6
HardFault (and the HardFault exception is then taken).
6
7
Implement this escalation logic.
7
This is a behavior change for v7 cpus with Security Extensions and
8
8
without Virtualization Extensions, in that the virtualization cpregs
9
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
9
are now correctly not present. This would be a migration compatibility
10
[PMM: extracted from another patch]
10
break, except that we have an existing bug in which migration of 32-bit
11
cpus with Security Extensions enabled does not work.
12
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220506180242.216785-3-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
---
17
---
14
hw/intc/armv7m_nvic.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
18
target/arm/helper.c | 158 ++++----------------------------------------
15
target/arm/helper.c | 2 --
19
1 file changed, 13 insertions(+), 145 deletions(-)
16
2 files changed, 53 insertions(+), 2 deletions(-)
20
17
18
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/armv7m_nvic.c
21
+++ b/hw/intc/armv7m_nvic.c
22
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
23
24
vec = &s->vectors[irq];
25
trace_nvic_set_pending(irq, vec->enabled, vec->prio);
26
+
27
+
28
+ if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
29
+ /* If a synchronous exception is pending then it may be
30
+ * escalated to HardFault if:
31
+ * * it is equal or lower priority to current execution
32
+ * * it is disabled
33
+ * (ie we need to take it immediately but we can't do so).
34
+ * Asynchronous exceptions (and interrupts) simply remain pending.
35
+ *
36
+ * For QEMU, we don't have any imprecise (asynchronous) faults,
37
+ * so we can assume that PREFETCH_ABORT and DATA_ABORT are always
38
+ * synchronous.
39
+ * Debug exceptions are awkward because only Debug exceptions
40
+ * resulting from the BKPT instruction should be escalated,
41
+ * but we don't currently implement any Debug exceptions other
42
+ * than those that result from BKPT, so we treat all debug exceptions
43
+ * as needing escalation.
44
+ *
45
+ * This all means we can identify whether to escalate based only on
46
+ * the exception number and don't (yet) need the caller to explicitly
47
+ * tell us whether this exception is synchronous or not.
48
+ */
49
+ int running = nvic_exec_prio(s);
50
+ bool escalate = false;
51
+
52
+ if (vec->prio >= running) {
53
+ trace_nvic_escalate_prio(irq, vec->prio, running);
54
+ escalate = true;
55
+ } else if (!vec->enabled) {
56
+ trace_nvic_escalate_disabled(irq);
57
+ escalate = true;
58
+ }
59
+
60
+ if (escalate) {
61
+ if (running < 0) {
62
+ /* We want to escalate to HardFault but we can't take a
63
+ * synchronous HardFault at this point either. This is a
64
+ * Lockup condition due to a guest bug. We don't model
65
+ * Lockup, so report via cpu_abort() instead.
66
+ */
67
+ cpu_abort(&s->cpu->parent_obj,
68
+ "Lockup: can't escalate %d to HardFault "
69
+ "(current priority %d)\n", irq, running);
70
+ }
71
+
72
+ /* We can do the escalation, so we take HardFault instead */
73
+ irq = ARMV7M_EXCP_HARD;
74
+ vec = &s->vectors[irq];
75
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
76
+ }
77
+ }
78
+
79
if (!vec->pending) {
80
vec->pending = 1;
81
nvic_irq_update(s);
82
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
83
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/helper.c
23
--- a/target/arm/helper.c
85
+++ b/target/arm/helper.c
24
+++ b/target/arm/helper.c
86
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
25
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
87
26
.fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
88
/* For exceptions we just mark as pending on the NVIC, and let that
27
};
89
handle it. */
28
90
- /* TODO: Need to escalate if the current priority is higher than the
29
-/* Used to describe the behaviour of EL2 regs when EL2 does not exist. */
91
- one we're raising. */
30
-static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
92
switch (cs->exception_index) {
31
- { .name = "VBAR_EL2", .state = ARM_CP_STATE_BOTH,
93
case EXCP_UDEF:
32
- .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
94
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
33
- .access = PL2_RW,
34
- .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
35
- { .name = "HCR_EL2", .state = ARM_CP_STATE_BOTH,
36
- .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
37
- .access = PL2_RW,
38
- .type = ARM_CP_CONST, .resetvalue = 0 },
39
- { .name = "HACR_EL2", .state = ARM_CP_STATE_BOTH,
40
- .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 7,
41
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
42
- { .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
43
- .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
44
- .access = PL2_RW,
45
- .type = ARM_CP_CONST, .resetvalue = 0 },
46
- { .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH,
47
- .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2,
48
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
49
- { .name = "MAIR_EL2", .state = ARM_CP_STATE_BOTH,
50
- .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 0,
51
- .access = PL2_RW, .type = ARM_CP_CONST,
52
- .resetvalue = 0 },
53
- { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
54
- .cp = 15, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
55
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
56
- { .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH,
57
- .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0,
58
- .access = PL2_RW, .type = ARM_CP_CONST,
59
- .resetvalue = 0 },
60
- { .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
61
- .cp = 15, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
62
- .access = PL2_RW, .type = ARM_CP_CONST,
63
- .resetvalue = 0 },
64
- { .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH,
65
- .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 0,
66
- .access = PL2_RW, .type = ARM_CP_CONST,
67
- .resetvalue = 0 },
68
- { .name = "AFSR1_EL2", .state = ARM_CP_STATE_BOTH,
69
- .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 1,
70
- .access = PL2_RW, .type = ARM_CP_CONST,
71
- .resetvalue = 0 },
72
- { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
73
- .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
74
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
75
- { .name = "VTCR_EL2", .state = ARM_CP_STATE_BOTH,
76
- .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
77
- .access = PL2_RW, .accessfn = access_el3_aa32ns,
78
- .type = ARM_CP_CONST, .resetvalue = 0 },
79
- { .name = "VTTBR", .state = ARM_CP_STATE_AA32,
80
- .cp = 15, .opc1 = 6, .crm = 2,
81
- .access = PL2_RW, .accessfn = access_el3_aa32ns,
82
- .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
83
- { .name = "VTTBR_EL2", .state = ARM_CP_STATE_AA64,
84
- .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 0,
85
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
86
- { .name = "SCTLR_EL2", .state = ARM_CP_STATE_BOTH,
87
- .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 0,
88
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
89
- { .name = "TPIDR_EL2", .state = ARM_CP_STATE_BOTH,
90
- .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 2,
91
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
92
- { .name = "TTBR0_EL2", .state = ARM_CP_STATE_AA64,
93
- .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
94
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
95
- { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
96
- .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_CONST,
97
- .resetvalue = 0 },
98
- { .name = "CNTHCTL_EL2", .state = ARM_CP_STATE_BOTH,
99
- .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 1, .opc2 = 0,
100
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
101
- { .name = "CNTVOFF_EL2", .state = ARM_CP_STATE_AA64,
102
- .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 3,
103
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
104
- { .name = "CNTVOFF", .cp = 15, .opc1 = 4, .crm = 14,
105
- .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_CONST,
106
- .resetvalue = 0 },
107
- { .name = "CNTHP_CVAL_EL2", .state = ARM_CP_STATE_AA64,
108
- .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 2,
109
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
110
- { .name = "CNTHP_CVAL", .cp = 15, .opc1 = 6, .crm = 14,
111
- .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_CONST,
112
- .resetvalue = 0 },
113
- { .name = "CNTHP_TVAL_EL2", .state = ARM_CP_STATE_BOTH,
114
- .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 0,
115
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
116
- { .name = "CNTHP_CTL_EL2", .state = ARM_CP_STATE_BOTH,
117
- .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 1,
118
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
119
- { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH,
120
- .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1,
121
- .access = PL2_RW, .accessfn = access_tda,
122
- .type = ARM_CP_CONST, .resetvalue = 0 },
123
- { .name = "HPFAR_EL2", .state = ARM_CP_STATE_BOTH,
124
- .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4,
125
- .access = PL2_RW, .accessfn = access_el3_aa32ns,
126
- .type = ARM_CP_CONST, .resetvalue = 0 },
127
- { .name = "HSTR_EL2", .state = ARM_CP_STATE_BOTH,
128
- .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
129
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
130
- { .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
131
- .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0,
132
- .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
133
- { .name = "HIFAR", .state = ARM_CP_STATE_AA32,
134
- .type = ARM_CP_CONST,
135
- .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
136
- .access = PL2_RW, .resetvalue = 0 },
137
-};
138
-
139
-/* Ditto, but for registers which exist in ARMv8 but not v7 */
140
-static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
141
- { .name = "HCR2", .state = ARM_CP_STATE_AA32,
142
- .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
143
- .access = PL2_RW,
144
- .type = ARM_CP_CONST, .resetvalue = 0 },
145
-};
146
-
147
static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
148
{
149
ARMCPU *cpu = env_archcpu(env);
150
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
151
define_arm_cp_regs(cpu, v8_idregs);
152
define_arm_cp_regs(cpu, v8_cp_reginfo);
153
}
154
- if (arm_feature(env, ARM_FEATURE_EL2)) {
155
+
156
+ /*
157
+ * Register the base EL2 cpregs.
158
+ * Pre v8, these registers are implemented only as part of the
159
+ * Virtualization Extensions (EL2 present). Beginning with v8,
160
+ * if EL2 is missing but EL3 is enabled, mostly these become
161
+ * RES0 from EL3, with some specific exceptions.
162
+ */
163
+ if (arm_feature(env, ARM_FEATURE_EL2)
164
+ || (arm_feature(env, ARM_FEATURE_EL3)
165
+ && arm_feature(env, ARM_FEATURE_V8))) {
166
uint64_t vmpidr_def = mpidr_read_val(env);
167
ARMCPRegInfo vpidr_regs[] = {
168
{ .name = "VPIDR", .state = ARM_CP_STATE_AA32,
169
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
170
};
171
define_one_arm_cp_reg(cpu, &rvbar);
172
}
173
- } else {
174
- /* If EL2 is missing but higher ELs are enabled, we need to
175
- * register the no_el2 reginfos.
176
- */
177
- if (arm_feature(env, ARM_FEATURE_EL3)) {
178
- /* When EL3 exists but not EL2, VPIDR and VMPIDR take the value
179
- * of MIDR_EL1 and MPIDR_EL1.
180
- */
181
- ARMCPRegInfo vpidr_regs[] = {
182
- { .name = "VPIDR_EL2", .state = ARM_CP_STATE_BOTH,
183
- .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0,
184
- .access = PL2_RW, .accessfn = access_el3_aa32ns,
185
- .type = ARM_CP_CONST, .resetvalue = cpu->midr,
186
- .fieldoffset = offsetof(CPUARMState, cp15.vpidr_el2) },
187
- { .name = "VMPIDR_EL2", .state = ARM_CP_STATE_BOTH,
188
- .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5,
189
- .access = PL2_RW, .accessfn = access_el3_aa32ns,
190
- .type = ARM_CP_NO_RAW,
191
- .writefn = arm_cp_write_ignore, .readfn = mpidr_read },
192
- };
193
- define_arm_cp_regs(cpu, vpidr_regs);
194
- define_arm_cp_regs(cpu, el3_no_el2_cp_reginfo);
195
- if (arm_feature(env, ARM_FEATURE_V8)) {
196
- define_arm_cp_regs(cpu, el3_no_el2_v8_cp_reginfo);
197
- }
198
- }
199
}
200
+
201
+ /* Register the base EL3 cpregs. */
202
if (arm_feature(env, ARM_FEATURE_EL3)) {
203
define_arm_cp_regs(cpu, el3_cp_reginfo);
204
ARMCPRegInfo el3_regs[] = {
95
--
205
--
96
2.7.4
206
2.25.1
97
98
diff view generated by jsdifflib
1
Extract the code from the tail end of arm_v7m_do_interrupt() which
1
From: Richard Henderson <richard.henderson@linaro.org>
2
enters the exception handler into a pair of utility functions
3
v7m_exception_taken() and v7m_push_stack(), which correspond roughly
4
to the pseudocode PushStack() and ExceptionTaken().
5
2
6
This also requires us to move the arm_v7m_load_vector() utility
3
Drop zcr_no_el2_reginfo and merge the 3 registers into one array,
7
routine up so we can call it.
4
now that ZCR_EL2 can be squashed to RES0 and ZCR_EL3 dropped
5
while registering.
8
6
9
Handling illegal exception returns has some cases where we want to
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
take a UsageFault either on an existing stack frame or with a new
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
stack frame but with a specific LR value, so we want to be able to
9
Message-id: 20220506180242.216785-4-richard.henderson@linaro.org
12
call these without having to go via arm_v7m_cpu_do_interrupt().
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
16
---
11
---
17
target/arm/helper.c | 118 ++++++++++++++++++++++++++++++----------------------
12
target/arm/helper.c | 55 ++++++++++++++-------------------------------
18
1 file changed, 68 insertions(+), 50 deletions(-)
13
1 file changed, 17 insertions(+), 38 deletions(-)
19
14
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
23
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
19
@@ -XXX,XX +XXX,XX @@ static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
25
}
20
}
26
}
21
}
27
22
28
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
23
-static const ARMCPRegInfo zcr_el1_reginfo = {
29
+{
24
- .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
30
+ CPUState *cs = CPU(cpu);
25
- .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
31
+ CPUARMState *env = &cpu->env;
26
- .access = PL1_RW, .type = ARM_CP_SVE,
32
+ MemTxResult result;
27
- .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
33
+ hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
28
- .writefn = zcr_write, .raw_writefn = raw_write
34
+ uint32_t addr;
29
-};
35
+
30
-
36
+ addr = address_space_ldl(cs->as, vec,
31
-static const ARMCPRegInfo zcr_el2_reginfo = {
37
+ MEMTXATTRS_UNSPECIFIED, &result);
32
- .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
38
+ if (result != MEMTX_OK) {
33
- .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
39
+ /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
34
- .access = PL2_RW, .type = ARM_CP_SVE,
40
+ * which would then be immediately followed by our failing to load
35
- .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
41
+ * the entry vector for that HardFault, which is a Lockup case.
36
- .writefn = zcr_write, .raw_writefn = raw_write
42
+ * Since we don't model Lockup, we just report this guest error
37
-};
43
+ * via cpu_abort().
38
-
44
+ */
39
-static const ARMCPRegInfo zcr_no_el2_reginfo = {
45
+ cpu_abort(cs, "Failed to read from exception vector table "
40
- .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
46
+ "entry %08x\n", (unsigned)vec);
41
- .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
47
+ }
42
- .access = PL2_RW, .type = ARM_CP_SVE,
48
+ return addr;
43
- .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore
49
+}
44
-};
50
+
45
-
51
+static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
46
-static const ARMCPRegInfo zcr_el3_reginfo = {
52
+{
47
- .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
53
+ /* Do the "take the exception" parts of exception entry,
48
- .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
54
+ * but not the pushing of state to the stack. This is
49
- .access = PL3_RW, .type = ARM_CP_SVE,
55
+ * similar to the pseudocode ExceptionTaken() function.
50
- .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
56
+ */
51
- .writefn = zcr_write, .raw_writefn = raw_write
57
+ CPUARMState *env = &cpu->env;
52
+static const ARMCPRegInfo zcr_reginfo[] = {
58
+ uint32_t addr;
53
+ { .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
59
+
54
+ .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
60
+ armv7m_nvic_acknowledge_irq(env->nvic);
55
+ .access = PL1_RW, .type = ARM_CP_SVE,
61
+ switch_v7m_sp(env, 0);
56
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
62
+ /* Clear IT bits */
57
+ .writefn = zcr_write, .raw_writefn = raw_write },
63
+ env->condexec_bits = 0;
58
+ { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
64
+ env->regs[14] = lr;
59
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
65
+ addr = arm_v7m_load_vector(cpu);
60
+ .access = PL2_RW, .type = ARM_CP_SVE,
66
+ env->regs[15] = addr & 0xfffffffe;
61
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
67
+ env->thumb = addr & 1;
62
+ .writefn = zcr_write, .raw_writefn = raw_write },
68
+}
63
+ { .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
69
+
64
+ .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
70
+static void v7m_push_stack(ARMCPU *cpu)
65
+ .access = PL3_RW, .type = ARM_CP_SVE,
71
+{
66
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
72
+ /* Do the "set up stack frame" part of exception entry,
67
+ .writefn = zcr_write, .raw_writefn = raw_write },
73
+ * similar to pseudocode PushStack().
68
};
74
+ */
69
75
+ CPUARMState *env = &cpu->env;
70
void hw_watchpoint_update(ARMCPU *cpu, int n)
76
+ uint32_t xpsr = xpsr_read(env);
71
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
77
+
78
+ /* Align stack pointer if the guest wants that */
79
+ if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
80
+ env->regs[13] -= 4;
81
+ xpsr |= 0x200;
82
+ }
83
+ /* Switch to the handler mode. */
84
+ v7m_push(env, xpsr);
85
+ v7m_push(env, env->regs[15]);
86
+ v7m_push(env, env->regs[14]);
87
+ v7m_push(env, env->regs[12]);
88
+ v7m_push(env, env->regs[3]);
89
+ v7m_push(env, env->regs[2]);
90
+ v7m_push(env, env->regs[1]);
91
+ v7m_push(env, env->regs[0]);
92
+}
93
+
94
static void do_v7m_exception_exit(CPUARMState *env)
95
{
96
uint32_t type;
97
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
98
}
72
}
99
}
73
100
74
if (cpu_isar_feature(aa64_sve, cpu)) {
101
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
75
- define_one_arm_cp_reg(cpu, &zcr_el1_reginfo);
102
-
76
- if (arm_feature(env, ARM_FEATURE_EL2)) {
103
-{
77
- define_one_arm_cp_reg(cpu, &zcr_el2_reginfo);
104
- CPUState *cs = CPU(cpu);
78
- } else {
105
- CPUARMState *env = &cpu->env;
79
- define_one_arm_cp_reg(cpu, &zcr_no_el2_reginfo);
106
- MemTxResult result;
80
- }
107
- hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
81
- if (arm_feature(env, ARM_FEATURE_EL3)) {
108
- uint32_t addr;
82
- define_one_arm_cp_reg(cpu, &zcr_el3_reginfo);
109
-
83
- }
110
- addr = address_space_ldl(cs->as, vec,
84
+ define_arm_cp_regs(cpu, zcr_reginfo);
111
- MEMTXATTRS_UNSPECIFIED, &result);
112
- if (result != MEMTX_OK) {
113
- /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
114
- * which would then be immediately followed by our failing to load
115
- * the entry vector for that HardFault, which is a Lockup case.
116
- * Since we don't model Lockup, we just report this guest error
117
- * via cpu_abort().
118
- */
119
- cpu_abort(cs, "Failed to read from exception vector table "
120
- "entry %08x\n", (unsigned)vec);
121
- }
122
- return addr;
123
-}
124
-
125
void arm_v7m_cpu_do_interrupt(CPUState *cs)
126
{
127
ARMCPU *cpu = ARM_CPU(cs);
128
CPUARMState *env = &cpu->env;
129
- uint32_t xpsr = xpsr_read(env);
130
uint32_t lr;
131
- uint32_t addr;
132
133
arm_log_exception(cs->exception_index);
134
135
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
136
return; /* Never happens. Keep compiler happy. */
137
}
85
}
138
86
139
- armv7m_nvic_acknowledge_irq(env->nvic);
87
#ifdef TARGET_AARCH64
140
-
141
+ v7m_push_stack(cpu);
142
+ v7m_exception_taken(cpu, lr);
143
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
144
-
145
- /* Align stack pointer if the guest wants that */
146
- if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
147
- env->regs[13] -= 4;
148
- xpsr |= 0x200;
149
- }
150
- /* Switch to the handler mode. */
151
- v7m_push(env, xpsr);
152
- v7m_push(env, env->regs[15]);
153
- v7m_push(env, env->regs[14]);
154
- v7m_push(env, env->regs[12]);
155
- v7m_push(env, env->regs[3]);
156
- v7m_push(env, env->regs[2]);
157
- v7m_push(env, env->regs[1]);
158
- v7m_push(env, env->regs[0]);
159
- switch_v7m_sp(env, 0);
160
- /* Clear IT bits */
161
- env->condexec_bits = 0;
162
- env->regs[14] = lr;
163
- addr = arm_v7m_load_vector(cpu);
164
- env->regs[15] = addr & 0xfffffffe;
165
- env->thumb = addr & 1;
166
}
167
168
/* Function used to synchronize QEMU's AArch64 register set with AArch32
169
--
88
--
170
2.7.4
89
2.25.1
171
172
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Without any clock controller, the Linux kernel was hitting division by
3
This register is present for either VHE or Debugv8p2.
4
zero during boot or with clk_summary:
5
[ 0.000000] [<c031054c>] (unwind_backtrace) from [<c030ba6c>] (show_stack+0x10/0x14)
6
[ 0.000000] [<c030ba6c>] (show_stack) from [<c05b2660>] (dump_stack+0x88/0x9c)
7
[ 0.000000] [<c05b2660>] (dump_stack) from [<c05b11a4>] (Ldiv0+0x8/0x10)
8
[ 0.000000] [<c05b11a4>] (Ldiv0) from [<c06ad1e0>] (samsung_pll45xx_recalc_rate+0x58/0x74)
9
[ 0.000000] [<c06ad1e0>] (samsung_pll45xx_recalc_rate) from [<c0692ec0>] (clk_register+0x39c/0x63c)
10
[ 0.000000] [<c0692ec0>] (clk_register) from [<c125d360>] (samsung_clk_register_pll+0x2e0/0x3d4)
11
[ 0.000000] [<c125d360>] (samsung_clk_register_pll) from [<c125d7e8>] (exynos4_clk_init+0x1b0/0x5e4)
12
[ 0.000000] [<c125d7e8>] (exynos4_clk_init) from [<c12335f4>] (of_clk_init+0x17c/0x210)
13
[ 0.000000] [<c12335f4>] (of_clk_init) from [<c1204700>] (time_init+0x24/0x2c)
14
[ 0.000000] [<c1204700>] (time_init) from [<c1200b2c>] (start_kernel+0x24c/0x38c)
15
[ 0.000000] [<c1200b2c>] (start_kernel) from [<4020807c>] (0x4020807c)
16
4
17
Provide stub for clock controller returning reset values for PLLs.
18
19
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
20
Message-id: 20170226200142.31169-1-krzk@kernel.org
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220506180242.216785-5-richard.henderson@linaro.org
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
9
---
24
hw/misc/Makefile.objs | 2 +-
10
target/arm/helper.c | 15 +++++++++++----
25
hw/arm/exynos4210.c | 6 ++
11
1 file changed, 11 insertions(+), 4 deletions(-)
26
hw/misc/exynos4210_clk.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++
27
3 files changed, 171 insertions(+), 1 deletion(-)
28
create mode 100644 hw/misc/exynos4210_clk.c
29
12
30
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
31
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/Makefile.objs
15
--- a/target/arm/helper.c
33
+++ b/hw/misc/Makefile.objs
16
+++ b/target/arm/helper.c
34
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
17
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo jazelle_regs[] = {
35
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
18
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
36
obj-$(CONFIG_NSERIES) += cbus.o
19
};
37
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
20
38
-obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
21
+static const ARMCPRegInfo contextidr_el2 = {
39
+obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o
22
+ .name = "CONTEXTIDR_EL2", .state = ARM_CP_STATE_AA64,
40
obj-$(CONFIG_IMX) += imx_ccm.o
23
+ .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
41
obj-$(CONFIG_IMX) += imx31_ccm.o
24
+ .access = PL2_RW,
42
obj-$(CONFIG_IMX) += imx25_ccm.o
25
+ .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2])
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@
48
#include "qemu/osdep.h"
49
#include "qapi/error.h"
50
#include "qemu-common.h"
51
+#include "qemu/log.h"
52
#include "cpu.h"
53
#include "hw/boards.h"
54
#include "sysemu/sysemu.h"
55
@@ -XXX,XX +XXX,XX @@
56
/* PMU SFR base address */
57
#define EXYNOS4210_PMU_BASE_ADDR 0x10020000
58
59
+/* Clock controller SFR base address */
60
+#define EXYNOS4210_CLK_BASE_ADDR 0x10030000
61
+
62
/* Display controllers (FIMD) */
63
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
64
65
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
66
*/
67
sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
68
69
+ sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
70
+
71
/* PWM */
72
sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
73
s->irq_table[exynos4210_get_irq(22, 0)],
74
diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/hw/misc/exynos4210_clk.c
79
@@ -XXX,XX +XXX,XX @@
80
+/*
81
+ * Exynos4210 Clock Controller Emulation
82
+ *
83
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
84
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
86
+ * under the terms of the GNU General Public License as published by the
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
89
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ *
95
+ * You should have received a copy of the GNU General Public License along
96
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
97
+ */
98
+
99
+#include "qemu/osdep.h"
100
+#include "hw/sysbus.h"
101
+#include "qemu/log.h"
102
+
103
+#define TYPE_EXYNOS4210_CLK "exynos4210.clk"
104
+#define EXYNOS4210_CLK(obj) \
105
+ OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK)
106
+
107
+#define CLK_PLL_LOCKED BIT(29)
108
+
109
+#define EXYNOS4210_CLK_REGS_MEM_SIZE 0x15104
110
+
111
+typedef struct Exynos4210Reg {
112
+ const char *name; /* for debug only */
113
+ uint32_t offset;
114
+ uint32_t reset_value;
115
+} Exynos4210Reg;
116
+
117
+/* Clock controller register base: 0x10030000 */
118
+static const Exynos4210Reg exynos4210_clk_regs[] = {
119
+ {"EPLL_LOCK", 0xc010, 0x00000fff},
120
+ {"VPLL_LOCK", 0xc020, 0x00000fff},
121
+ {"EPLL_CON0", 0xc110, 0x00300301 | CLK_PLL_LOCKED},
122
+ {"EPLL_CON1", 0xc114, 0x00000000},
123
+ {"VPLL_CON0", 0xc120, 0x00240201 | CLK_PLL_LOCKED},
124
+ {"VPLL_CON1", 0xc124, 0x66010464},
125
+ {"APLL_LOCK", 0x14000, 0x00000fff},
126
+ {"MPLL_LOCK", 0x14004, 0x00000fff},
127
+ {"APLL_CON0", 0x14100, 0x00c80601 | CLK_PLL_LOCKED},
128
+ {"APLL_CON1", 0x14104, 0x0000001c},
129
+ {"MPLL_CON0", 0x14108, 0x00c80601 | CLK_PLL_LOCKED},
130
+ {"MPLL_CON1", 0x1410c, 0x0000001c},
131
+};
26
+};
132
+
27
+
133
+#define EXYNOS4210_REGS_NUM ARRAY_SIZE(exynos4210_clk_regs)
28
static const ARMCPRegInfo vhe_reginfo[] = {
134
+
29
- { .name = "CONTEXTIDR_EL2", .state = ARM_CP_STATE_AA64,
135
+typedef struct Exynos4210ClkState {
30
- .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
136
+ SysBusDevice parent_obj;
31
- .access = PL2_RW,
137
+
32
- .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2]) },
138
+ MemoryRegion iomem;
33
{ .name = "TTBR1_EL2", .state = ARM_CP_STATE_AA64,
139
+ uint32_t reg[EXYNOS4210_REGS_NUM];
34
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 1,
140
+} Exynos4210ClkState;
35
.access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
141
+
36
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
142
+static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset,
37
define_one_arm_cp_reg(cpu, &ssbs_reginfo);
143
+ unsigned size)
38
}
144
+{
39
145
+ const Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
40
+ if (cpu_isar_feature(aa64_vh, cpu) ||
146
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
41
+ cpu_isar_feature(aa64_debugv8p2, cpu)) {
147
+ unsigned int i;
42
+ define_one_arm_cp_reg(cpu, &contextidr_el2);
148
+
149
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
150
+ if (regs->offset == offset) {
151
+ return s->reg[i];
152
+ }
153
+ regs++;
154
+ }
43
+ }
155
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read offset 0x%04x\n",
44
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
156
+ __func__, (uint32_t)offset);
45
define_arm_cp_regs(cpu, vhe_reginfo);
157
+ return 0;
46
}
158
+}
159
+
160
+static void exynos4210_clk_write(void *opaque, hwaddr offset,
161
+ uint64_t val, unsigned size)
162
+{
163
+ Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
164
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
165
+ unsigned int i;
166
+
167
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
168
+ if (regs->offset == offset) {
169
+ s->reg[i] = val;
170
+ return;
171
+ }
172
+ regs++;
173
+ }
174
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write offset 0x%04x\n",
175
+ __func__, (uint32_t)offset);
176
+}
177
+
178
+static const MemoryRegionOps exynos4210_clk_ops = {
179
+ .read = exynos4210_clk_read,
180
+ .write = exynos4210_clk_write,
181
+ .endianness = DEVICE_NATIVE_ENDIAN,
182
+ .valid = {
183
+ .min_access_size = 4,
184
+ .max_access_size = 4,
185
+ .unaligned = false
186
+ }
187
+};
188
+
189
+static void exynos4210_clk_reset(DeviceState *dev)
190
+{
191
+ Exynos4210ClkState *s = EXYNOS4210_CLK(dev);
192
+ unsigned int i;
193
+
194
+ /* Set default values for registers */
195
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
196
+ s->reg[i] = exynos4210_clk_regs[i].reset_value;
197
+ }
198
+}
199
+
200
+static void exynos4210_clk_init(Object *obj)
201
+{
202
+ Exynos4210ClkState *s = EXYNOS4210_CLK(obj);
203
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
204
+
205
+ /* memory mapping */
206
+ memory_region_init_io(&s->iomem, obj, &exynos4210_clk_ops, s,
207
+ TYPE_EXYNOS4210_CLK, EXYNOS4210_CLK_REGS_MEM_SIZE);
208
+ sysbus_init_mmio(dev, &s->iomem);
209
+}
210
+
211
+static const VMStateDescription exynos4210_clk_vmstate = {
212
+ .name = TYPE_EXYNOS4210_CLK,
213
+ .version_id = 1,
214
+ .minimum_version_id = 1,
215
+ .fields = (VMStateField[]) {
216
+ VMSTATE_UINT32_ARRAY(reg, Exynos4210ClkState, EXYNOS4210_REGS_NUM),
217
+ VMSTATE_END_OF_LIST()
218
+ }
219
+};
220
+
221
+static void exynos4210_clk_class_init(ObjectClass *klass, void *data)
222
+{
223
+ DeviceClass *dc = DEVICE_CLASS(klass);
224
+
225
+ dc->reset = exynos4210_clk_reset;
226
+ dc->vmsd = &exynos4210_clk_vmstate;
227
+}
228
+
229
+static const TypeInfo exynos4210_clk_info = {
230
+ .name = TYPE_EXYNOS4210_CLK,
231
+ .parent = TYPE_SYS_BUS_DEVICE,
232
+ .instance_size = sizeof(Exynos4210ClkState),
233
+ .instance_init = exynos4210_clk_init,
234
+ .class_init = exynos4210_clk_class_init,
235
+};
236
+
237
+static void exynos4210_clk_register(void)
238
+{
239
+ qemu_log_mask(LOG_GUEST_ERROR, "Clock init\n");
240
+ type_register_static(&exynos4210_clk_info);
241
+}
242
+
243
+type_init(exynos4210_clk_register)
244
--
47
--
245
2.7.4
48
2.25.1
246
247
diff view generated by jsdifflib
1
Rename the nvic_state struct to NVICState, to match
1
From: Richard Henderson <richard.henderson@linaro.org>
2
our naming conventions.
2
3
3
Previously we were defining some of these in user-only mode,
4
but none of them are accessible from user-only, therefore
5
define them only in system mode.
6
7
This will shortly be used from cpu_tcg.c also.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220506180242.216785-6-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
---
13
---
8
hw/intc/armv7m_nvic.c | 44 ++++++++++++++++++++++----------------------
14
target/arm/internals.h | 6 ++++
9
1 file changed, 22 insertions(+), 22 deletions(-)
15
target/arm/cpu64.c | 64 +++---------------------------------------
10
16
target/arm/cpu_tcg.c | 59 ++++++++++++++++++++++++++++++++++++++
11
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
17
3 files changed, 69 insertions(+), 60 deletions(-)
18
19
diff --git a/target/arm/internals.h b/target/arm/internals.h
12
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/armv7m_nvic.c
21
--- a/target/arm/internals.h
14
+++ b/hw/intc/armv7m_nvic.c
22
+++ b/target/arm/internals.h
23
@@ -XXX,XX +XXX,XX @@ int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
24
int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
25
#endif
26
27
+#ifdef CONFIG_USER_ONLY
28
+static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
29
+#else
30
+void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
31
+#endif
32
+
33
#endif
34
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/cpu64.c
37
+++ b/target/arm/cpu64.c
15
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
16
#include "gic_internal.h"
39
#include "hvf_arm.h"
17
#include "qemu/log.h"
40
#include "qapi/visitor.h"
18
41
#include "hw/qdev-properties.h"
19
-typedef struct {
42
-#include "cpregs.h"
20
+typedef struct NVICState {
43
+#include "internals.h"
21
GICState gic;
44
22
ARMCPU *cpu;
45
23
struct {
46
-#ifndef CONFIG_USER_ONLY
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
47
-static uint64_t a57_a53_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
25
MemoryRegion container;
48
-{
26
uint32_t num_irq;
49
- ARMCPU *cpu = env_archcpu(env);
27
qemu_irq sysresetreq;
50
-
28
-} nvic_state;
51
- /* Number of cores is in [25:24]; otherwise we RAZ */
29
+} NVICState;
52
- return (cpu->core_count - 1) << 24;
30
53
-}
31
#define TYPE_NVIC "armv7m_nvic"
54
-#endif
32
/**
55
-
33
@@ -XXX,XX +XXX,XX @@ typedef struct NVICClass {
56
-static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
34
#define NVIC_GET_CLASS(obj) \
57
-#ifndef CONFIG_USER_ONLY
35
OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
58
- { .name = "L2CTLR_EL1", .state = ARM_CP_STATE_AA64,
36
#define NVIC(obj) \
59
- .opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 2,
37
- OBJECT_CHECK(nvic_state, (obj), TYPE_NVIC)
60
- .access = PL1_RW, .readfn = a57_a53_l2ctlr_read,
38
+ OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
61
- .writefn = arm_cp_write_ignore },
39
62
- { .name = "L2CTLR",
40
static const uint8_t nvic_id[] = {
63
- .cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 2,
41
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
64
- .access = PL1_RW, .readfn = a57_a53_l2ctlr_read,
42
@@ -XXX,XX +XXX,XX @@ static const uint8_t nvic_id[] = {
65
- .writefn = arm_cp_write_ignore },
43
int system_clock_scale;
66
-#endif
44
67
- { .name = "L2ECTLR_EL1", .state = ARM_CP_STATE_AA64,
45
/* Conversion factor from qemu timer to SysTick frequencies. */
68
- .opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 3,
46
-static inline int64_t systick_scale(nvic_state *s)
69
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
47
+static inline int64_t systick_scale(NVICState *s)
70
- { .name = "L2ECTLR",
71
- .cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 3,
72
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
73
- { .name = "L2ACTLR", .state = ARM_CP_STATE_BOTH,
74
- .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 0, .opc2 = 0,
75
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
76
- { .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
77
- .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 0,
78
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
79
- { .name = "CPUACTLR",
80
- .cp = 15, .opc1 = 0, .crm = 15,
81
- .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
82
- { .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
83
- .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 1,
84
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
85
- { .name = "CPUECTLR",
86
- .cp = 15, .opc1 = 1, .crm = 15,
87
- .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
88
- { .name = "CPUMERRSR_EL1", .state = ARM_CP_STATE_AA64,
89
- .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 2,
90
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
91
- { .name = "CPUMERRSR",
92
- .cp = 15, .opc1 = 2, .crm = 15,
93
- .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
94
- { .name = "L2MERRSR_EL1", .state = ARM_CP_STATE_AA64,
95
- .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 3,
96
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
97
- { .name = "L2MERRSR",
98
- .cp = 15, .opc1 = 3, .crm = 15,
99
- .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
100
-};
101
-
102
static void aarch64_a57_initfn(Object *obj)
48
{
103
{
49
if (s->systick.control & SYSTICK_CLKSOURCE)
104
ARMCPU *cpu = ARM_CPU(obj);
50
return system_clock_scale;
105
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
51
@@ -XXX,XX +XXX,XX @@ static inline int64_t systick_scale(nvic_state *s)
106
cpu->gic_num_lrs = 4;
52
return 1000;
107
cpu->gic_vpribits = 5;
108
cpu->gic_vprebits = 5;
109
- define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
110
+ define_cortex_a72_a57_a53_cp_reginfo(cpu);
53
}
111
}
54
112
55
-static void systick_reload(nvic_state *s, int reset)
113
static void aarch64_a53_initfn(Object *obj)
56
+static void systick_reload(NVICState *s, int reset)
114
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
57
{
115
cpu->gic_num_lrs = 4;
58
/* The Cortex-M3 Devices Generic User Guide says that "When the
116
cpu->gic_vpribits = 5;
59
* ENABLE bit is set to 1, the counter loads the RELOAD value from the
117
cpu->gic_vprebits = 5;
60
@@ -XXX,XX +XXX,XX @@ static void systick_reload(nvic_state *s, int reset)
118
- define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
61
119
+ define_cortex_a72_a57_a53_cp_reginfo(cpu);
62
static void systick_timer_tick(void * opaque)
63
{
64
- nvic_state *s = (nvic_state *)opaque;
65
+ NVICState *s = (NVICState *)opaque;
66
s->systick.control |= SYSTICK_COUNTFLAG;
67
if (s->systick.control & SYSTICK_TICKINT) {
68
/* Trigger the interrupt. */
69
@@ -XXX,XX +XXX,XX @@ static void systick_timer_tick(void * opaque)
70
}
71
}
120
}
72
121
73
-static void systick_reset(nvic_state *s)
122
static void aarch64_a72_initfn(Object *obj)
74
+static void systick_reset(NVICState *s)
123
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
75
{
124
cpu->gic_num_lrs = 4;
76
s->systick.control = 0;
125
cpu->gic_vpribits = 5;
77
s->systick.reload = 0;
126
cpu->gic_vprebits = 5;
78
@@ -XXX,XX +XXX,XX @@ static void systick_reset(nvic_state *s)
127
- define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
79
IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
128
+ define_cortex_a72_a57_a53_cp_reginfo(cpu);
80
void armv7m_nvic_set_pending(void *opaque, int irq)
81
{
82
- nvic_state *s = (nvic_state *)opaque;
83
+ NVICState *s = (NVICState *)opaque;
84
if (irq >= 16)
85
irq += 16;
86
gic_set_pending_private(&s->gic, 0, irq);
87
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
88
/* Make pending IRQ active. */
89
int armv7m_nvic_acknowledge_irq(void *opaque)
90
{
91
- nvic_state *s = (nvic_state *)opaque;
92
+ NVICState *s = (NVICState *)opaque;
93
uint32_t irq;
94
95
irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
96
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
97
98
void armv7m_nvic_complete_irq(void *opaque, int irq)
99
{
100
- nvic_state *s = (nvic_state *)opaque;
101
+ NVICState *s = (NVICState *)opaque;
102
if (irq >= 16)
103
irq += 16;
104
gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
105
}
129
}
106
130
107
-static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
131
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
108
+static uint32_t nvic_readl(NVICState *s, uint32_t offset)
132
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
109
{
133
index XXXXXXX..XXXXXXX 100644
110
ARMCPU *cpu = s->cpu;
134
--- a/target/arm/cpu_tcg.c
111
uint32_t val;
135
+++ b/target/arm/cpu_tcg.c
112
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
136
@@ -XXX,XX +XXX,XX @@
113
}
137
#endif
114
}
138
#include "cpregs.h"
115
139
116
-static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
140
+#ifndef CONFIG_USER_ONLY
117
+static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
141
+static uint64_t l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
118
{
142
+{
119
ARMCPU *cpu = s->cpu;
143
+ ARMCPU *cpu = env_archcpu(env);
120
uint32_t oldval;
144
+
121
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
145
+ /* Number of cores is in [25:24]; otherwise we RAZ */
122
static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
146
+ return (cpu->core_count - 1) << 24;
123
unsigned size)
147
+}
124
{
148
+
125
- nvic_state *s = (nvic_state *)opaque;
149
+static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
126
+ NVICState *s = (NVICState *)opaque;
150
+ { .name = "L2CTLR_EL1", .state = ARM_CP_STATE_AA64,
127
uint32_t offset = addr;
151
+ .opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 2,
128
int i;
152
+ .access = PL1_RW, .readfn = l2ctlr_read,
129
uint32_t val;
153
+ .writefn = arm_cp_write_ignore },
130
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
154
+ { .name = "L2CTLR",
131
static void nvic_sysreg_write(void *opaque, hwaddr addr,
155
+ .cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 2,
132
uint64_t value, unsigned size)
156
+ .access = PL1_RW, .readfn = l2ctlr_read,
133
{
157
+ .writefn = arm_cp_write_ignore },
134
- nvic_state *s = (nvic_state *)opaque;
158
+ { .name = "L2ECTLR_EL1", .state = ARM_CP_STATE_AA64,
135
+ NVICState *s = (NVICState *)opaque;
159
+ .opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 3,
136
uint32_t offset = addr;
160
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
137
int i;
161
+ { .name = "L2ECTLR",
138
162
+ .cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 3,
139
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
163
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
140
.version_id = 1,
164
+ { .name = "L2ACTLR", .state = ARM_CP_STATE_BOTH,
141
.minimum_version_id = 1,
165
+ .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 0, .opc2 = 0,
142
.fields = (VMStateField[]) {
166
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
143
- VMSTATE_UINT32(systick.control, nvic_state),
167
+ { .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
144
- VMSTATE_UINT32(systick.reload, nvic_state),
168
+ .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 0,
145
- VMSTATE_INT64(systick.tick, nvic_state),
169
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
146
- VMSTATE_TIMER_PTR(systick.timer, nvic_state),
170
+ { .name = "CPUACTLR",
147
+ VMSTATE_UINT32(systick.control, NVICState),
171
+ .cp = 15, .opc1 = 0, .crm = 15,
148
+ VMSTATE_UINT32(systick.reload, NVICState),
172
+ .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
149
+ VMSTATE_INT64(systick.tick, NVICState),
173
+ { .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
150
+ VMSTATE_TIMER_PTR(systick.timer, NVICState),
174
+ .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 1,
151
VMSTATE_END_OF_LIST()
175
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
152
}
176
+ { .name = "CPUECTLR",
153
};
177
+ .cp = 15, .opc1 = 1, .crm = 15,
154
178
+ .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
155
static void armv7m_nvic_reset(DeviceState *dev)
179
+ { .name = "CPUMERRSR_EL1", .state = ARM_CP_STATE_AA64,
156
{
180
+ .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 2,
157
- nvic_state *s = NVIC(dev);
181
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
158
+ NVICState *s = NVIC(dev);
182
+ { .name = "CPUMERRSR",
159
NVICClass *nc = NVIC_GET_CLASS(s);
183
+ .cp = 15, .opc1 = 2, .crm = 15,
160
nc->parent_reset(dev);
184
+ .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
161
/* Common GIC reset resets to disabled; the NVIC doesn't have
185
+ { .name = "L2MERRSR_EL1", .state = ARM_CP_STATE_AA64,
162
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
186
+ .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 3,
163
187
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
164
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
188
+ { .name = "L2MERRSR",
165
{
189
+ .cp = 15, .opc1 = 3, .crm = 15,
166
- nvic_state *s = NVIC(dev);
190
+ .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
167
+ NVICState *s = NVIC(dev);
191
+};
168
NVICClass *nc = NVIC_GET_CLASS(s);
192
+
169
Error *local_err = NULL;
193
+void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu)
170
194
+{
171
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
195
+ define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
172
*/
196
+}
173
GICState *s = ARM_GIC_COMMON(obj);
197
+#endif /* !CONFIG_USER_ONLY */
174
DeviceState *dev = DEVICE(obj);
198
+
175
- nvic_state *nvic = NVIC(obj);
199
/* CPU models. These are not needed for the AArch64 linux-user build. */
176
+ NVICState *nvic = NVIC(obj);
200
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
177
/* The ARM v7m may have anything from 0 to 496 external interrupt
201
178
* IRQ lines. We default to 64. Other boards may differ and should
179
* set the num-irq property appropriately.
180
@@ -XXX,XX +XXX,XX @@ static const TypeInfo armv7m_nvic_info = {
181
.name = TYPE_NVIC,
182
.parent = TYPE_ARM_GIC_COMMON,
183
.instance_init = armv7m_nvic_instance_init,
184
- .instance_size = sizeof(nvic_state),
185
+ .instance_size = sizeof(NVICState),
186
.class_init = armv7m_nvic_class_init,
187
.class_size = sizeof(NVICClass),
188
};
189
--
202
--
190
2.7.4
203
2.25.1
191
192
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Instead of starting with cortex-a15 and adding v8 features to
4
a v7 cpu, begin with a v8 cpu stripped of its aarch64 features.
5
This fixes the long-standing to-do where we only enabled v8
6
features for user-only.
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220506180242.216785-7-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/cpu_tcg.c | 151 ++++++++++++++++++++++++++-----------------
14
1 file changed, 92 insertions(+), 59 deletions(-)
15
16
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu_tcg.c
19
+++ b/target/arm/cpu_tcg.c
20
@@ -XXX,XX +XXX,XX @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
21
static void arm_max_initfn(Object *obj)
22
{
23
ARMCPU *cpu = ARM_CPU(obj);
24
+ uint32_t t;
25
26
- cortex_a15_initfn(obj);
27
+ /* aarch64_a57_initfn, advertising none of the aarch64 features */
28
+ cpu->dtb_compatible = "arm,cortex-a57";
29
+ set_feature(&cpu->env, ARM_FEATURE_V8);
30
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
31
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
32
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
33
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
34
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
35
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
36
+ cpu->midr = 0x411fd070;
37
+ cpu->revidr = 0x00000000;
38
+ cpu->reset_fpsid = 0x41034070;
39
+ cpu->isar.mvfr0 = 0x10110222;
40
+ cpu->isar.mvfr1 = 0x12111111;
41
+ cpu->isar.mvfr2 = 0x00000043;
42
+ cpu->ctr = 0x8444c004;
43
+ cpu->reset_sctlr = 0x00c50838;
44
+ cpu->isar.id_pfr0 = 0x00000131;
45
+ cpu->isar.id_pfr1 = 0x00011011;
46
+ cpu->isar.id_dfr0 = 0x03010066;
47
+ cpu->id_afr0 = 0x00000000;
48
+ cpu->isar.id_mmfr0 = 0x10101105;
49
+ cpu->isar.id_mmfr1 = 0x40000000;
50
+ cpu->isar.id_mmfr2 = 0x01260000;
51
+ cpu->isar.id_mmfr3 = 0x02102211;
52
+ cpu->isar.id_isar0 = 0x02101110;
53
+ cpu->isar.id_isar1 = 0x13112111;
54
+ cpu->isar.id_isar2 = 0x21232042;
55
+ cpu->isar.id_isar3 = 0x01112131;
56
+ cpu->isar.id_isar4 = 0x00011142;
57
+ cpu->isar.id_isar5 = 0x00011121;
58
+ cpu->isar.id_isar6 = 0;
59
+ cpu->isar.dbgdidr = 0x3516d000;
60
+ cpu->clidr = 0x0a200023;
61
+ cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
62
+ cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
63
+ cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
64
+ define_cortex_a72_a57_a53_cp_reginfo(cpu);
65
66
- /* old-style VFP short-vector support */
67
- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
68
+ /* Add additional features supported by QEMU */
69
+ t = cpu->isar.id_isar5;
70
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
71
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
72
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
73
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
74
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
75
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
76
+ cpu->isar.id_isar5 = t;
77
+
78
+ t = cpu->isar.id_isar6;
79
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
80
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
81
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
82
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
83
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
84
+ t = FIELD_DP32(t, ID_ISAR6, BF16, 1);
85
+ t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);
86
+ cpu->isar.id_isar6 = t;
87
+
88
+ t = cpu->isar.mvfr1;
89
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
90
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
91
+ cpu->isar.mvfr1 = t;
92
+
93
+ t = cpu->isar.mvfr2;
94
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
95
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
96
+ cpu->isar.mvfr2 = t;
97
+
98
+ t = cpu->isar.id_mmfr3;
99
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
100
+ cpu->isar.id_mmfr3 = t;
101
+
102
+ t = cpu->isar.id_mmfr4;
103
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
104
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
105
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
106
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
107
+ cpu->isar.id_mmfr4 = t;
108
+
109
+ t = cpu->isar.id_pfr0;
110
+ t = FIELD_DP32(t, ID_PFR0, DIT, 1);
111
+ cpu->isar.id_pfr0 = t;
112
+
113
+ t = cpu->isar.id_pfr2;
114
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
115
+ cpu->isar.id_pfr2 = t;
116
117
#ifdef CONFIG_USER_ONLY
118
/*
119
- * We don't set these in system emulation mode for the moment,
120
- * since we don't correctly set (all of) the ID registers to
121
- * advertise them.
122
+ * Break with true ARMv8 and add back old-style VFP short-vector support.
123
+ * Only do this for user-mode, where -cpu max is the default, so that
124
+ * older v6 and v7 programs are more likely to work without adjustment.
125
*/
126
- set_feature(&cpu->env, ARM_FEATURE_V8);
127
- {
128
- uint32_t t;
129
-
130
- t = cpu->isar.id_isar5;
131
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
132
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
133
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
134
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
135
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
136
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
137
- cpu->isar.id_isar5 = t;
138
-
139
- t = cpu->isar.id_isar6;
140
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
141
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
142
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
143
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
144
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
145
- t = FIELD_DP32(t, ID_ISAR6, BF16, 1);
146
- t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);
147
- cpu->isar.id_isar6 = t;
148
-
149
- t = cpu->isar.mvfr1;
150
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
151
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
152
- cpu->isar.mvfr1 = t;
153
-
154
- t = cpu->isar.mvfr2;
155
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
156
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
157
- cpu->isar.mvfr2 = t;
158
-
159
- t = cpu->isar.id_mmfr3;
160
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
161
- cpu->isar.id_mmfr3 = t;
162
-
163
- t = cpu->isar.id_mmfr4;
164
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
165
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
166
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
167
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
168
- cpu->isar.id_mmfr4 = t;
169
-
170
- t = cpu->isar.id_pfr0;
171
- t = FIELD_DP32(t, ID_PFR0, DIT, 1);
172
- cpu->isar.id_pfr0 = t;
173
-
174
- t = cpu->isar.id_pfr2;
175
- t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
176
- cpu->isar.id_pfr2 = t;
177
- }
178
-#endif /* CONFIG_USER_ONLY */
179
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
180
+#endif
181
}
182
#endif /* !TARGET_AARCH64 */
183
184
--
185
2.25.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
We set this for qemu-system-aarch64, but failed to do so
4
for the strictly 32-bit emulation.
5
6
Fixes: 3bec78447a9 ("target/arm: Provide ARMv8.4-PMU in '-cpu max'")
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220506180242.216785-8-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpu_tcg.c | 4 ++++
13
1 file changed, 4 insertions(+)
14
15
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu_tcg.c
18
+++ b/target/arm/cpu_tcg.c
19
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
20
t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
21
cpu->isar.id_pfr2 = t;
22
23
+ t = cpu->isar.id_dfr0;
24
+ t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
25
+ cpu->isar.id_dfr0 = t;
26
+
27
#ifdef CONFIG_USER_ONLY
28
/*
29
* Break with true ARMv8 and add back old-style VFP short-vector support.
30
--
31
2.25.1
diff view generated by jsdifflib
1
Switch to using qcrypto_random_bytes() rather than rand() as
1
From: Richard Henderson <richard.henderson@linaro.org>
2
our source of randomness for the BCM2835 RNG.
3
2
4
If qcrypto_random_bytes() fails, we don't want to return the guest a
3
Share the code to set AArch32 max features so that we no
5
non-random value in case they're really using it for cryptographic
4
longer have code drift between qemu{-system,}-{arm,aarch64}.
6
purposes, so the best we can do is a fatal error. This shouldn't
7
happen unless something's broken, though.
8
5
9
In theory we could implement this device's full FIFO and interrupt
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
semantics and then just stop filling the FIFO. That's a lot of work,
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
though, and doesn't really give a very nice diagnostic to the user
8
Message-id: 20220506180242.216785-9-richard.henderson@linaro.org
12
since the guest will just seem to hang.
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/internals.h | 2 +
12
target/arm/cpu64.c | 50 +-----------------
13
target/arm/cpu_tcg.c | 114 ++++++++++++++++++++++-------------------
14
3 files changed, 65 insertions(+), 101 deletions(-)
13
15
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
diff --git a/target/arm/internals.h b/target/arm/internals.h
15
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
16
---
17
hw/misc/bcm2835_rng.c | 27 ++++++++++++++++++++++++++-
18
1 file changed, 26 insertions(+), 1 deletion(-)
19
20
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/bcm2835_rng.c
18
--- a/target/arm/internals.h
23
+++ b/hw/misc/bcm2835_rng.c
19
+++ b/target/arm/internals.h
20
@@ -XXX,XX +XXX,XX @@ static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
21
void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
22
#endif
23
24
+void aa32_max_features(ARMCPU *cpu);
25
+
26
#endif
27
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu64.c
30
+++ b/target/arm/cpu64.c
31
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
32
{
33
ARMCPU *cpu = ARM_CPU(obj);
34
uint64_t t;
35
- uint32_t u;
36
37
if (kvm_enabled() || hvf_enabled()) {
38
/* With KVM or HVF, '-cpu max' is identical to '-cpu host' */
39
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
40
t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1);
41
cpu->isar.id_aa64zfr0 = t;
42
43
- /* Replicate the same data to the 32-bit id registers. */
44
- u = cpu->isar.id_isar5;
45
- u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */
46
- u = FIELD_DP32(u, ID_ISAR5, SHA1, 1);
47
- u = FIELD_DP32(u, ID_ISAR5, SHA2, 1);
48
- u = FIELD_DP32(u, ID_ISAR5, CRC32, 1);
49
- u = FIELD_DP32(u, ID_ISAR5, RDM, 1);
50
- u = FIELD_DP32(u, ID_ISAR5, VCMA, 1);
51
- cpu->isar.id_isar5 = u;
52
-
53
- u = cpu->isar.id_isar6;
54
- u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
55
- u = FIELD_DP32(u, ID_ISAR6, DP, 1);
56
- u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
57
- u = FIELD_DP32(u, ID_ISAR6, SB, 1);
58
- u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
59
- u = FIELD_DP32(u, ID_ISAR6, BF16, 1);
60
- u = FIELD_DP32(u, ID_ISAR6, I8MM, 1);
61
- cpu->isar.id_isar6 = u;
62
-
63
- u = cpu->isar.id_pfr0;
64
- u = FIELD_DP32(u, ID_PFR0, DIT, 1);
65
- cpu->isar.id_pfr0 = u;
66
-
67
- u = cpu->isar.id_pfr2;
68
- u = FIELD_DP32(u, ID_PFR2, SSBS, 1);
69
- cpu->isar.id_pfr2 = u;
70
-
71
- u = cpu->isar.id_mmfr3;
72
- u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
73
- cpu->isar.id_mmfr3 = u;
74
-
75
- u = cpu->isar.id_mmfr4;
76
- u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */
77
- u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
78
- u = FIELD_DP32(u, ID_MMFR4, CNP, 1); /* TTCNP */
79
- u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */
80
- cpu->isar.id_mmfr4 = u;
81
-
82
t = cpu->isar.id_aa64dfr0;
83
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
84
cpu->isar.id_aa64dfr0 = t;
85
86
- u = cpu->isar.id_dfr0;
87
- u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
88
- cpu->isar.id_dfr0 = u;
89
-
90
- u = cpu->isar.mvfr1;
91
- u = FIELD_DP32(u, MVFR1, FPHP, 3); /* v8.2-FP16 */
92
- u = FIELD_DP32(u, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
93
- cpu->isar.mvfr1 = u;
94
+ /* Replicate the same data to the 32-bit id registers. */
95
+ aa32_max_features(cpu);
96
97
#ifdef CONFIG_USER_ONLY
98
/*
99
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/cpu_tcg.c
102
+++ b/target/arm/cpu_tcg.c
24
@@ -XXX,XX +XXX,XX @@
103
@@ -XXX,XX +XXX,XX @@
25
104
#endif
26
#include "qemu/osdep.h"
105
#include "cpregs.h"
27
#include "qemu/log.h"
106
28
+#include "qapi/error.h"
107
+
29
+#include "crypto/random.h"
108
+/* Share AArch32 -cpu max features with AArch64. */
30
#include "hw/misc/bcm2835_rng.h"
109
+void aa32_max_features(ARMCPU *cpu)
31
32
+static uint32_t get_random_bytes(void)
33
+{
110
+{
34
+ uint32_t res;
111
+ uint32_t t;
35
+ Error *err = NULL;
112
+
36
+
113
+ /* Add additional features supported by QEMU */
37
+ if (qcrypto_random_bytes((uint8_t *)&res, sizeof(res), &err) < 0) {
114
+ t = cpu->isar.id_isar5;
38
+ /* On failure we don't want to return the guest a non-random
115
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
39
+ * value in case they're really using it for cryptographic
116
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
40
+ * purposes, so the best we can do is die here.
117
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
41
+ * This shouldn't happen unless something's broken.
118
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
42
+ * In theory we could implement this device's full FIFO
119
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
43
+ * and interrupt semantics and then just stop filling the
120
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
44
+ * FIFO. That's a lot of work, though, so we assume any
121
+ cpu->isar.id_isar5 = t;
45
+ * errors are systematic problems and trust that if we didn't
122
+
46
+ * fail as the guest inited then we won't fail later on
123
+ t = cpu->isar.id_isar6;
47
+ * mid-run.
124
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
48
+ */
125
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
49
+ error_report_err(err);
126
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
50
+ exit(1);
127
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
51
+ }
128
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
52
+ return res;
129
+ t = FIELD_DP32(t, ID_ISAR6, BF16, 1);
130
+ t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);
131
+ cpu->isar.id_isar6 = t;
132
+
133
+ t = cpu->isar.mvfr1;
134
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
135
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
136
+ cpu->isar.mvfr1 = t;
137
+
138
+ t = cpu->isar.mvfr2;
139
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
140
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
141
+ cpu->isar.mvfr2 = t;
142
+
143
+ t = cpu->isar.id_mmfr3;
144
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
145
+ cpu->isar.id_mmfr3 = t;
146
+
147
+ t = cpu->isar.id_mmfr4;
148
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
149
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
150
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
151
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
152
+ cpu->isar.id_mmfr4 = t;
153
+
154
+ t = cpu->isar.id_pfr0;
155
+ t = FIELD_DP32(t, ID_PFR0, DIT, 1);
156
+ cpu->isar.id_pfr0 = t;
157
+
158
+ t = cpu->isar.id_pfr2;
159
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
160
+ cpu->isar.id_pfr2 = t;
161
+
162
+ t = cpu->isar.id_dfr0;
163
+ t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
164
+ cpu->isar.id_dfr0 = t;
53
+}
165
+}
54
+
166
+
55
static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
167
#ifndef CONFIG_USER_ONLY
56
unsigned size)
168
static uint64_t l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
57
{
169
{
58
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
170
@@ -XXX,XX +XXX,XX @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
59
res = s->rng_status | (1 << 24);
171
static void arm_max_initfn(Object *obj)
60
break;
172
{
61
case 0x8: /* rng_data */
173
ARMCPU *cpu = ARM_CPU(obj);
62
- res = rand();
174
- uint32_t t;
63
+ res = get_random_bytes();
175
64
break;
176
/* aarch64_a57_initfn, advertising none of the aarch64 features */
65
177
cpu->dtb_compatible = "arm,cortex-a57";
66
default:
178
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
179
cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
180
define_cortex_a72_a57_a53_cp_reginfo(cpu);
181
182
- /* Add additional features supported by QEMU */
183
- t = cpu->isar.id_isar5;
184
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
185
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
186
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
187
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
188
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
189
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
190
- cpu->isar.id_isar5 = t;
191
-
192
- t = cpu->isar.id_isar6;
193
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
194
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
195
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
196
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
197
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
198
- t = FIELD_DP32(t, ID_ISAR6, BF16, 1);
199
- t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);
200
- cpu->isar.id_isar6 = t;
201
-
202
- t = cpu->isar.mvfr1;
203
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
204
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
205
- cpu->isar.mvfr1 = t;
206
-
207
- t = cpu->isar.mvfr2;
208
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
209
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
210
- cpu->isar.mvfr2 = t;
211
-
212
- t = cpu->isar.id_mmfr3;
213
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
214
- cpu->isar.id_mmfr3 = t;
215
-
216
- t = cpu->isar.id_mmfr4;
217
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
218
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
219
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
220
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
221
- cpu->isar.id_mmfr4 = t;
222
-
223
- t = cpu->isar.id_pfr0;
224
- t = FIELD_DP32(t, ID_PFR0, DIT, 1);
225
- cpu->isar.id_pfr0 = t;
226
-
227
- t = cpu->isar.id_pfr2;
228
- t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
229
- cpu->isar.id_pfr2 = t;
230
-
231
- t = cpu->isar.id_dfr0;
232
- t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
233
- cpu->isar.id_dfr0 = t;
234
+ aa32_max_features(cpu);
235
236
#ifdef CONFIG_USER_ONLY
237
/*
67
--
238
--
68
2.7.4
239
2.25.1
69
70
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Exynos4210 has cluster ID 0x9 in its MPIDR register (raw value
3
Update the legacy feature names to the current names.
4
0x8000090x). If this cluster ID is not provided, then Linux kernel
4
Provide feature names for id changes that were not marked.
5
cannot map DeviceTree nodes to MPIDR values resulting in kernel
5
Sort the field updates into increasing bitfield order.
6
warning and lack of any secondary CPUs:
7
6
8
DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map
9
...
10
smp: Bringing up secondary CPUs ...
11
smp: Brought up 1 node, 1 CPU
12
SMP: Total of 1 processors activated (24.00 BogoMIPS).
13
14
Provide a cluster ID so Linux will see proper MPIDR and will try to
15
bring the secondary CPU online.
16
17
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
18
Message-id: 20170226200142.31169-2-krzk@kernel.org
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220506180242.216785-10-richard.henderson@linaro.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
11
---
22
hw/arm/exynos4210.c | 12 ++++++++++++
12
target/arm/cpu64.c | 100 +++++++++++++++++++++----------------------
23
1 file changed, 12 insertions(+)
13
target/arm/cpu_tcg.c | 48 ++++++++++-----------
14
2 files changed, 74 insertions(+), 74 deletions(-)
24
15
25
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
16
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
26
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/exynos4210.c
18
--- a/target/arm/cpu64.c
28
+++ b/hw/arm/exynos4210.c
19
+++ b/target/arm/cpu64.c
29
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
20
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
30
info->smp_loader_start);
21
cpu->midr = t;
22
23
t = cpu->isar.id_aa64isar0;
24
- t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* AES + PMULL */
25
- t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1);
26
- t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* SHA512 */
27
+ t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* FEAT_PMULL */
28
+ t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); /* FEAT_SHA1 */
29
+ t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* FEAT_SHA512 */
30
t = FIELD_DP64(t, ID_AA64ISAR0, CRC32, 1);
31
- t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 2);
32
- t = FIELD_DP64(t, ID_AA64ISAR0, RDM, 1);
33
- t = FIELD_DP64(t, ID_AA64ISAR0, SHA3, 1);
34
- t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1);
35
- t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
36
- t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
37
- t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
38
- t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
39
- t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */
40
- t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1);
41
+ t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 2); /* FEAT_LSE */
42
+ t = FIELD_DP64(t, ID_AA64ISAR0, RDM, 1); /* FEAT_RDM */
43
+ t = FIELD_DP64(t, ID_AA64ISAR0, SHA3, 1); /* FEAT_SHA3 */
44
+ t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1); /* FEAT_SM3 */
45
+ t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1); /* FEAT_SM4 */
46
+ t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1); /* FEAT_DotProd */
47
+ t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1); /* FEAT_FHM */
48
+ t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* FEAT_FlagM2 */
49
+ t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */
50
+ t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); /* FEAT_RNG */
51
cpu->isar.id_aa64isar0 = t;
52
53
t = cpu->isar.id_aa64isar1;
54
- t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);
55
- t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
56
- t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
57
- t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
58
- t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
59
- t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1);
60
- t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
61
- t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */
62
- t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1);
63
+ t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */
64
+ t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); /* FEAT_JSCVT */
65
+ t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); /* FEAT_FCMA */
66
+ t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* FEAT_LRCPC2 */
67
+ t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1); /* FEAT_FRINTTS */
68
+ t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1); /* FEAT_SB */
69
+ t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1); /* FEAT_SPECRES */
70
+ t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1); /* FEAT_BF16 */
71
+ t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); /* FEAT_I8MM */
72
cpu->isar.id_aa64isar1 = t;
73
74
t = cpu->isar.id_aa64pfr0;
75
+ t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */
76
+ t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */
77
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
78
- t = FIELD_DP64(t, ID_AA64PFR0, FP, 1);
79
- t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);
80
- t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1);
81
- t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1);
82
+ t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
83
+ t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
84
cpu->isar.id_aa64pfr0 = t;
85
86
t = cpu->isar.id_aa64pfr1;
87
- t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
88
- t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2);
89
+ t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); /* FEAT_BTI */
90
+ t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); /* FEAT_SSBS2 */
91
/*
92
* Begin with full support for MTE. This will be downgraded to MTE=0
93
* during realize if the board provides no tag memory, much like
94
* we do for EL2 with the virtualization=on property.
95
*/
96
- t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3);
97
+ t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
98
cpu->isar.id_aa64pfr1 = t;
99
100
t = cpu->isar.id_aa64mmfr0;
101
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
102
cpu->isar.id_aa64mmfr0 = t;
103
104
t = cpu->isar.id_aa64mmfr1;
105
- t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
106
- t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
107
- t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
108
- t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
109
- t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */
110
- t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */
111
+ t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */
112
+ t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
113
+ t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
114
+ t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */
115
+ t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* FEAT_PAN2 */
116
+ t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
117
cpu->isar.id_aa64mmfr1 = t;
118
119
t = cpu->isar.id_aa64mmfr2;
120
- t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
121
- t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
122
- t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
123
- t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */
124
- t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
125
- t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */
126
+ t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* FEAT_TTCNP */
127
+ t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); /* FEAT_UAO */
128
+ t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */
129
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* FEAT_TTST */
130
+ t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
131
+ t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */
132
cpu->isar.id_aa64mmfr2 = t;
133
134
t = cpu->isar.id_aa64zfr0;
135
t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1);
136
- t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* PMULL */
137
- t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1);
138
- t = FIELD_DP64(t, ID_AA64ZFR0, BFLOAT16, 1);
139
- t = FIELD_DP64(t, ID_AA64ZFR0, SHA3, 1);
140
- t = FIELD_DP64(t, ID_AA64ZFR0, SM4, 1);
141
- t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1);
142
- t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1);
143
- t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1);
144
+ t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* FEAT_SVE_PMULL128 */
145
+ t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); /* FEAT_SVE_BitPerm */
146
+ t = FIELD_DP64(t, ID_AA64ZFR0, BFLOAT16, 1); /* FEAT_BF16 */
147
+ t = FIELD_DP64(t, ID_AA64ZFR0, SHA3, 1); /* FEAT_SVE_SHA3 */
148
+ t = FIELD_DP64(t, ID_AA64ZFR0, SM4, 1); /* FEAT_SVE_SM4 */
149
+ t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); /* FEAT_I8MM */
150
+ t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); /* FEAT_F32MM */
151
+ t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); /* FEAT_F64MM */
152
cpu->isar.id_aa64zfr0 = t;
153
154
t = cpu->isar.id_aa64dfr0;
155
- t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
156
+ t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* FEAT_PMUv3p4 */
157
cpu->isar.id_aa64dfr0 = t;
158
159
/* Replicate the same data to the 32-bit id registers. */
160
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/target/arm/cpu_tcg.c
163
+++ b/target/arm/cpu_tcg.c
164
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
165
166
/* Add additional features supported by QEMU */
167
t = cpu->isar.id_isar5;
168
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
169
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
170
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
171
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2); /* FEAT_PMULL */
172
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); /* FEAT_SHA1 */
173
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); /* FEAT_SHA256 */
174
t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
175
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
176
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
177
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1); /* FEAT_RDM */
178
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); /* FEAT_FCMA */
179
cpu->isar.id_isar5 = t;
180
181
t = cpu->isar.id_isar6;
182
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
183
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
184
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
185
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
186
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
187
- t = FIELD_DP32(t, ID_ISAR6, BF16, 1);
188
- t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);
189
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); /* FEAT_JSCVT */
190
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1); /* Feat_DotProd */
191
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1); /* FEAT_FHM */
192
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1); /* FEAT_SB */
193
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); /* FEAT_SPECRES */
194
+ t = FIELD_DP32(t, ID_ISAR6, BF16, 1); /* FEAT_AA32BF16 */
195
+ t = FIELD_DP32(t, ID_ISAR6, I8MM, 1); /* FEAT_AA32I8MM */
196
cpu->isar.id_isar6 = t;
197
198
t = cpu->isar.mvfr1;
199
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
200
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
201
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* FEAT_FP16 */
202
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* FEAT_FP16 */
203
cpu->isar.mvfr1 = t;
204
205
t = cpu->isar.mvfr2;
206
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
207
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
208
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
209
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
210
cpu->isar.mvfr2 = t;
211
212
t = cpu->isar.id_mmfr3;
213
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
214
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* FEAT_PAN2 */
215
cpu->isar.id_mmfr3 = t;
216
217
t = cpu->isar.id_mmfr4;
218
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
219
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
220
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
221
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
222
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* FEAT_AA32HPD */
223
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
224
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* FEAT_TTCNP */
225
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX*/
226
cpu->isar.id_mmfr4 = t;
227
228
t = cpu->isar.id_pfr0;
229
- t = FIELD_DP32(t, ID_PFR0, DIT, 1);
230
+ t = FIELD_DP32(t, ID_PFR0, DIT, 1); /* FEAT_DIT */
231
cpu->isar.id_pfr0 = t;
232
233
t = cpu->isar.id_pfr2;
234
- t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
235
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1); /* FEAT_SSBS */
236
cpu->isar.id_pfr2 = t;
237
238
t = cpu->isar.id_dfr0;
239
- t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
240
+ t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* FEAT_PMUv3p4 */
241
cpu->isar.id_dfr0 = t;
31
}
242
}
32
243
33
+static uint64_t exynos4210_calc_affinity(int cpu)
34
+{
35
+ uint64_t mp_affinity;
36
+
37
+ /* Exynos4210 has 0x9 as cluster ID */
38
+ mp_affinity = (0x9 << ARM_AFF1_SHIFT) | cpu;
39
+
40
+ return mp_affinity;
41
+}
42
+
43
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
44
unsigned long ram_size)
45
{
46
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
47
}
48
49
s->cpu[n] = ARM_CPU(cpuobj);
50
+ object_property_set_int(cpuobj, exynos4210_calc_affinity(n),
51
+ "mp-affinity", &error_abort);
52
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
53
"reset-cbar", &error_abort);
54
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
55
--
244
--
56
2.7.4
245
2.25.1
57
58
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform.
3
Use FIELD_DP{32,64} to manipulate id_pfr1 and id_aa64pfr0
4
during arm_cpu_realizefn.
4
5
5
For supporting the SD controller selection (alternate function of GPIOs
6
48-53), the bcm2835_gpio now exposes an sdbus.
7
It also has a link to both the sdbus of sdhci and sdhost controllers,
8
and the card is reparented from one bus to another when the alternate
9
function of GPIOs 48-53 is modified.
10
11
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
12
Message-id: 20170224164021.9066-5-clement.deschamps@antfield.fr
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220506180242.216785-11-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
include/hw/arm/bcm2835_peripherals.h | 4 ++++
11
target/arm/cpu.c | 22 +++++++++++++---------
17
hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++++--
12
1 file changed, 13 insertions(+), 9 deletions(-)
18
2 files changed, 45 insertions(+), 2 deletions(-)
19
13
20
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2835_peripherals.h
16
--- a/target/arm/cpu.c
23
+++ b/include/hw/arm/bcm2835_peripherals.h
17
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
25
#include "hw/misc/bcm2835_rng.h"
19
*/
26
#include "hw/misc/bcm2835_mbox.h"
20
unset_feature(env, ARM_FEATURE_EL3);
27
#include "hw/sd/sdhci.h"
21
28
+#include "hw/sd/bcm2835_sdhost.h"
22
- /* Disable the security extension feature bits in the processor feature
29
+#include "hw/gpio/bcm2835_gpio.h"
23
- * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12].
30
24
+ /*
31
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
25
+ * Disable the security extension feature bits in the processor
32
#define BCM2835_PERIPHERALS(obj) \
26
+ * feature registers as well.
33
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
27
*/
34
BCM2835RngState rng;
28
- cpu->isar.id_pfr1 &= ~0xf0;
35
BCM2835MboxState mboxes;
29
- cpu->isar.id_aa64pfr0 &= ~0xf000;
36
SDHCIState sdhci;
30
+ cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, ID_PFR1, SECURITY, 0);
37
+ BCM2835SDHostState sdhost;
31
+ cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
38
+ BCM2835GpioState gpio;
32
+ ID_AA64PFR0, EL3, 0);
39
} BCM2835PeripheralState;
40
41
#endif /* BCM2835_PERIPHERALS_H */
42
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/bcm2835_peripherals.c
45
+++ b/hw/arm/bcm2835_peripherals.c
46
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
47
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
48
qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
49
50
+ /* SDHOST */
51
+ object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST);
52
+ object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL);
53
+ qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default());
54
+
55
/* DMA Channels */
56
object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA);
57
object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL);
58
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
59
60
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
61
OBJECT(&s->gpu_bus_mr), &error_abort);
62
+
63
+ /* GPIO */
64
+ object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO);
65
+ object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL);
66
+ qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default());
67
+
68
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
69
+ OBJECT(&s->sdhci.sdbus), &error_abort);
70
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
71
+ OBJECT(&s->sdhost.sdbus), &error_abort);
72
}
73
74
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
75
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
76
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
77
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
78
INTERRUPT_ARASANSDIO));
79
- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-bus",
80
- &err);
81
+
82
+ /* SDHOST */
83
+ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err);
84
if (err) {
85
error_propagate(errp, err);
86
return;
87
}
33
}
88
34
89
+ memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET,
35
if (!cpu->has_el2) {
90
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0));
36
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
91
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0,
92
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
93
+ INTERRUPT_SDIO));
94
+
95
/* DMA Channels */
96
object_property_set_bool(OBJECT(&s->dma), true, "realized", &err);
97
if (err) {
98
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
99
BCM2835_IC_GPU_IRQ,
100
INTERRUPT_DMA0 + n));
101
}
37
}
102
+
38
103
+ /* GPIO */
39
if (!arm_feature(env, ARM_FEATURE_EL2)) {
104
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
40
- /* Disable the hypervisor feature bits in the processor feature
105
+ if (err) {
41
- * registers if we don't have EL2. These are id_pfr1[15:12] and
106
+ error_propagate(errp, err);
42
- * id_aa64pfr0_el1[11:8].
107
+ return;
43
+ /*
108
+ }
44
+ * Disable the hypervisor feature bits in the processor feature
109
+
45
+ * registers if we don't have EL2.
110
+ memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
46
*/
111
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
47
- cpu->isar.id_aa64pfr0 &= ~0xf00;
112
+
48
- cpu->isar.id_pfr1 &= ~0xf000;
113
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus",
49
+ cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
114
+ &err);
50
+ ID_AA64PFR0, EL2, 0);
115
+ if (err) {
51
+ cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1,
116
+ error_propagate(errp, err);
52
+ ID_PFR1, VIRTUALIZATION, 0);
117
+ return;
53
}
118
+ }
54
119
}
55
#ifndef CONFIG_USER_ONLY
120
121
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
122
--
56
--
123
2.7.4
57
2.25.1
124
125
diff view generated by jsdifflib
1
Implement the NVIC SHCSR write behaviour which allows pending and
1
From: Richard Henderson <richard.henderson@linaro.org>
2
active status of some exceptions to be changed.
3
2
3
The only portion of FEAT_Debugv8p2 that is relevant to QEMU
4
is CONTEXTIDR_EL2, which is also conditionally implemented
5
with FEAT_VHE. The rest of the debug extension concerns the
6
External debug interface, which is outside the scope of QEMU.
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220506180242.216785-12-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
---
12
---
7
hw/intc/armv7m_nvic.c | 13 +++++++++++--
13
docs/system/arm/emulation.rst | 1 +
8
1 file changed, 11 insertions(+), 2 deletions(-)
14
target/arm/cpu.c | 1 +
15
target/arm/cpu64.c | 1 +
16
target/arm/cpu_tcg.c | 2 ++
17
4 files changed, 5 insertions(+)
9
18
10
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
11
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/intc/armv7m_nvic.c
21
--- a/docs/system/arm/emulation.rst
13
+++ b/hw/intc/armv7m_nvic.c
22
+++ b/docs/system/arm/emulation.rst
14
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
23
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
15
cpu->env.v7m.ccr = value;
24
- FEAT_BTI (Branch Target Identification)
16
break;
25
- FEAT_DIT (Data Independent Timing instructions)
17
case 0xd24: /* System Handler Control. */
26
- FEAT_DPB (DC CVAP instruction)
18
- /* TODO: Real hardware allows you to set/clear the active bits
27
+- FEAT_Debugv8p2 (Debug changes for v8.2)
19
- under some circumstances. We don't implement this. */
28
- FEAT_DotProd (Advanced SIMD dot product instructions)
20
+ s->vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
29
- FEAT_FCMA (Floating-point complex number instructions)
21
+ s->vectors[ARMV7M_EXCP_BUS].active = (value & (1 << 1)) != 0;
30
- FEAT_FHM (Floating-point half-precision multiplication instructions)
22
+ s->vectors[ARMV7M_EXCP_USAGE].active = (value & (1 << 3)) != 0;
31
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
23
+ s->vectors[ARMV7M_EXCP_SVC].active = (value & (1 << 7)) != 0;
32
index XXXXXXX..XXXXXXX 100644
24
+ s->vectors[ARMV7M_EXCP_DEBUG].active = (value & (1 << 8)) != 0;
33
--- a/target/arm/cpu.c
25
+ s->vectors[ARMV7M_EXCP_PENDSV].active = (value & (1 << 10)) != 0;
34
+++ b/target/arm/cpu.c
26
+ s->vectors[ARMV7M_EXCP_SYSTICK].active = (value & (1 << 11)) != 0;
35
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
27
+ s->vectors[ARMV7M_EXCP_USAGE].pending = (value & (1 << 12)) != 0;
36
* feature registers as well.
28
+ s->vectors[ARMV7M_EXCP_MEM].pending = (value & (1 << 13)) != 0;
37
*/
29
+ s->vectors[ARMV7M_EXCP_BUS].pending = (value & (1 << 14)) != 0;
38
cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, ID_PFR1, SECURITY, 0);
30
+ s->vectors[ARMV7M_EXCP_SVC].pending = (value & (1 << 15)) != 0;
39
+ cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0);
31
s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
40
cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
32
s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
41
ID_AA64PFR0, EL3, 0);
33
s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
42
}
43
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/cpu64.c
46
+++ b/target/arm/cpu64.c
47
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
48
cpu->isar.id_aa64zfr0 = t;
49
50
t = cpu->isar.id_aa64dfr0;
51
+ t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 8); /* FEAT_Debugv8p2 */
52
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* FEAT_PMUv3p4 */
53
cpu->isar.id_aa64dfr0 = t;
54
55
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/cpu_tcg.c
58
+++ b/target/arm/cpu_tcg.c
59
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
60
cpu->isar.id_pfr2 = t;
61
62
t = cpu->isar.id_dfr0;
63
+ t = FIELD_DP32(t, ID_DFR0, COPDBG, 8); /* FEAT_Debugv8p2 */
64
+ t = FIELD_DP32(t, ID_DFR0, COPSDBG, 8); /* FEAT_Debugv8p2 */
65
t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* FEAT_PMUv3p4 */
66
cpu->isar.id_dfr0 = t;
67
}
34
--
68
--
35
2.7.4
69
2.25.1
36
37
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In SDHCI protocol, the 'Block count enable' bit of the Transfer
3
This extension concerns changes to the External Debug interface,
4
Mode register is relevant only in multi block transfers. We need
4
with Secure and Non-secure access to the debug registers, and all
5
not check it in single block transfers.
5
of it is outside the scope of QEMU. Indicating support for this
6
is mandatory with FEAT_SEL2, which we do implement.
6
7
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20170214185225.7994-5-ppandit@redhat.com
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
10
Message-id: 20220506180242.216785-13-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/sd/sdhci.c | 6 +-----
13
docs/system/arm/emulation.rst | 1 +
13
1 file changed, 1 insertion(+), 5 deletions(-)
14
target/arm/cpu64.c | 2 +-
15
target/arm/cpu_tcg.c | 4 ++--
16
3 files changed, 4 insertions(+), 3 deletions(-)
14
17
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
18
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
20
--- a/docs/system/arm/emulation.rst
18
+++ b/hw/sd/sdhci.c
21
+++ b/docs/system/arm/emulation.rst
19
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
22
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
20
}
23
- FEAT_DIT (Data Independent Timing instructions)
21
24
- FEAT_DPB (DC CVAP instruction)
22
/* single block SDMA transfer */
25
- FEAT_Debugv8p2 (Debug changes for v8.2)
23
-
26
+- FEAT_Debugv8p4 (Debug changes for v8.4)
24
static void sdhci_sdma_transfer_single_block(SDHCIState *s)
27
- FEAT_DotProd (Advanced SIMD dot product instructions)
25
{
28
- FEAT_FCMA (Floating-point complex number instructions)
26
int n;
29
- FEAT_FHM (Floating-point half-precision multiplication instructions)
27
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
30
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
28
sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
31
index XXXXXXX..XXXXXXX 100644
29
}
32
--- a/target/arm/cpu64.c
30
}
33
+++ b/target/arm/cpu64.c
31
-
34
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
32
- if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
35
cpu->isar.id_aa64zfr0 = t;
33
- s->blkcnt--;
36
34
- }
37
t = cpu->isar.id_aa64dfr0;
35
+ s->blkcnt--;
38
- t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 8); /* FEAT_Debugv8p2 */
36
39
+ t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 9); /* FEAT_Debugv8p4 */
37
sdhci_end_transfer(s);
40
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* FEAT_PMUv3p4 */
41
cpu->isar.id_aa64dfr0 = t;
42
43
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/cpu_tcg.c
46
+++ b/target/arm/cpu_tcg.c
47
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
48
cpu->isar.id_pfr2 = t;
49
50
t = cpu->isar.id_dfr0;
51
- t = FIELD_DP32(t, ID_DFR0, COPDBG, 8); /* FEAT_Debugv8p2 */
52
- t = FIELD_DP32(t, ID_DFR0, COPSDBG, 8); /* FEAT_Debugv8p2 */
53
+ t = FIELD_DP32(t, ID_DFR0, COPDBG, 9); /* FEAT_Debugv8p4 */
54
+ t = FIELD_DP32(t, ID_DFR0, COPSDBG, 9); /* FEAT_Debugv8p4 */
55
t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* FEAT_PMUv3p4 */
56
cpu->isar.id_dfr0 = t;
38
}
57
}
39
--
58
--
40
2.7.4
59
2.25.1
41
42
diff view generated by jsdifflib
1
Having armv7m_nvic_acknowledge_irq() return the new value of
1
From: Richard Henderson <richard.henderson@linaro.org>
2
env->v7m.exception and its one caller assign the return value
3
back to env->v7m.exception is pointless. Just make the return
4
type void instead.
5
2
3
Add only the system registers required to implement zero error
4
records. This means that all values for ERRSELR are out of range,
5
which means that it and all of the indexed error record registers
6
need not be implemented.
7
8
Add the EL2 registers required for injecting virtual SError.
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20220506180242.216785-14-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
---
14
---
9
target/arm/cpu.h | 2 +-
15
target/arm/cpu.h | 5 +++
10
hw/intc/armv7m_nvic.c | 4 +---
16
target/arm/helper.c | 84 +++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/helper.c | 2 +-
17
2 files changed, 89 insertions(+)
12
3 files changed, 3 insertions(+), 5 deletions(-)
13
18
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
21
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
23
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
19
}
24
uint64_t tfsr_el[4]; /* tfsre0_el1 is index 0. */
20
#endif
25
uint64_t gcr_el1;
21
void armv7m_nvic_set_pending(void *opaque, int irq);
26
uint64_t rgsr_el1;
22
-int armv7m_nvic_acknowledge_irq(void *opaque);
27
+
23
+void armv7m_nvic_acknowledge_irq(void *opaque);
28
+ /* Minimal RAS registers */
24
void armv7m_nvic_complete_irq(void *opaque, int irq);
29
+ uint64_t disr_el1;
25
30
+ uint64_t vdisr_el2;
26
/* Interface for defining coprocessor registers.
31
+ uint64_t vsesr_el2;
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
32
} cp15;
28
index XXXXXXX..XXXXXXX 100644
33
29
--- a/hw/intc/armv7m_nvic.c
34
struct {
30
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
32
}
33
34
/* Make pending IRQ active. */
35
-int armv7m_nvic_acknowledge_irq(void *opaque)
36
+void armv7m_nvic_acknowledge_irq(void *opaque)
37
{
38
NVICState *s = (NVICState *)opaque;
39
CPUARMState *env = &s->cpu->env;
40
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
41
env->v7m.exception = s->vectpending;
42
43
nvic_irq_update(s);
44
-
45
- return env->v7m.exception;
46
}
47
48
void armv7m_nvic_complete_irq(void *opaque, int irq)
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
35
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/helper.c
37
--- a/target/arm/helper.c
52
+++ b/target/arm/helper.c
38
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
39
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
40
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
55
return;
41
};
56
case EXCP_IRQ:
42
57
- env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
43
+/*
58
+ armv7m_nvic_acknowledge_irq(env->nvic);
44
+ * Check for traps to RAS registers, which are controlled
59
break;
45
+ * by HCR_EL2.TERR and SCR_EL3.TERR.
60
case EXCP_EXCEPTION_EXIT:
46
+ */
61
do_v7m_exception_exit(env);
47
+static CPAccessResult access_terr(CPUARMState *env, const ARMCPRegInfo *ri,
48
+ bool isread)
49
+{
50
+ int el = arm_current_el(env);
51
+
52
+ if (el < 2 && (arm_hcr_el2_eff(env) & HCR_TERR)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ if (el < 3 && (env->cp15.scr_el3 & SCR_TERR)) {
56
+ return CP_ACCESS_TRAP_EL3;
57
+ }
58
+ return CP_ACCESS_OK;
59
+}
60
+
61
+static uint64_t disr_read(CPUARMState *env, const ARMCPRegInfo *ri)
62
+{
63
+ int el = arm_current_el(env);
64
+
65
+ if (el < 2 && (arm_hcr_el2_eff(env) & HCR_AMO)) {
66
+ return env->cp15.vdisr_el2;
67
+ }
68
+ if (el < 3 && (env->cp15.scr_el3 & SCR_EA)) {
69
+ return 0; /* RAZ/WI */
70
+ }
71
+ return env->cp15.disr_el1;
72
+}
73
+
74
+static void disr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val)
75
+{
76
+ int el = arm_current_el(env);
77
+
78
+ if (el < 2 && (arm_hcr_el2_eff(env) & HCR_AMO)) {
79
+ env->cp15.vdisr_el2 = val;
80
+ return;
81
+ }
82
+ if (el < 3 && (env->cp15.scr_el3 & SCR_EA)) {
83
+ return; /* RAZ/WI */
84
+ }
85
+ env->cp15.disr_el1 = val;
86
+}
87
+
88
+/*
89
+ * Minimal RAS implementation with no Error Records.
90
+ * Which means that all of the Error Record registers:
91
+ * ERXADDR_EL1
92
+ * ERXCTLR_EL1
93
+ * ERXFR_EL1
94
+ * ERXMISC0_EL1
95
+ * ERXMISC1_EL1
96
+ * ERXMISC2_EL1
97
+ * ERXMISC3_EL1
98
+ * ERXPFGCDN_EL1 (RASv1p1)
99
+ * ERXPFGCTL_EL1 (RASv1p1)
100
+ * ERXPFGF_EL1 (RASv1p1)
101
+ * ERXSTATUS_EL1
102
+ * and
103
+ * ERRSELR_EL1
104
+ * may generate UNDEFINED, which is the effect we get by not
105
+ * listing them at all.
106
+ */
107
+static const ARMCPRegInfo minimal_ras_reginfo[] = {
108
+ { .name = "DISR_EL1", .state = ARM_CP_STATE_BOTH,
109
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 1,
110
+ .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.disr_el1),
111
+ .readfn = disr_read, .writefn = disr_write, .raw_writefn = raw_write },
112
+ { .name = "ERRIDR_EL1", .state = ARM_CP_STATE_BOTH,
113
+ .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 3, .opc2 = 0,
114
+ .access = PL1_R, .accessfn = access_terr,
115
+ .type = ARM_CP_CONST, .resetvalue = 0 },
116
+ { .name = "VDISR_EL2", .state = ARM_CP_STATE_BOTH,
117
+ .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 1, .opc2 = 1,
118
+ .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.vdisr_el2) },
119
+ { .name = "VSESR_EL2", .state = ARM_CP_STATE_BOTH,
120
+ .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 3,
121
+ .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.vsesr_el2) },
122
+};
123
+
124
/* Return the exception level to which exceptions should be taken
125
* via SVEAccessTrap. If an exception should be routed through
126
* AArch64.AdvSIMDFPAccessTrap, return 0; fp_exception_el should
127
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
128
if (cpu_isar_feature(aa64_ssbs, cpu)) {
129
define_one_arm_cp_reg(cpu, &ssbs_reginfo);
130
}
131
+ if (cpu_isar_feature(any_ras, cpu)) {
132
+ define_arm_cp_regs(cpu, minimal_ras_reginfo);
133
+ }
134
135
if (cpu_isar_feature(aa64_vh, cpu) ||
136
cpu_isar_feature(aa64_debugv8p2, cpu)) {
62
--
137
--
63
2.7.4
138
2.25.1
64
65
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
All the places in armv7m_cpu_do_interrupt() which pend an
3
Enable writes to the TERR and TEA bits when RAS is enabled.
4
exception in the NVIC are doing so for synchronous
4
These bits are otherwise RES0.
5
exceptions. We know that we will always take some
6
exception in this case, so we can just acknowledge it
7
immediately, rather than returning and then immediately
8
being called again because the NVIC has raised its outbound
9
IRQ line.
10
5
11
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
[PMM: tweaked commit message; added DEBUG to the set of
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
exceptions we handle immediately, since it is synchronous
8
Message-id: 20220506180242.216785-15-richard.henderson@linaro.org
14
when it results from the BKPT instruction]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
---
10
---
18
target/arm/helper.c | 15 +++++++++------
11
target/arm/helper.c | 9 +++++++++
19
1 file changed, 9 insertions(+), 6 deletions(-)
12
1 file changed, 9 insertions(+)
20
13
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
16
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
17
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
18
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
26
case EXCP_UDEF:
27
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
28
env->v7m.cfsr |= R_V7M_CFSR_UNDEFINSTR_MASK;
29
- return;
30
+ break;
31
case EXCP_NOCP:
32
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
33
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
34
- return;
35
+ break;
36
case EXCP_SWI:
37
/* The PC already points to the next instruction. */
38
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
39
- return;
40
+ break;
41
case EXCP_PREFETCH_ABORT:
42
case EXCP_DATA_ABORT:
43
/* TODO: if we implemented the MPU registers, this is where we
44
* should set the MMFAR, etc from exception.fsr and exception.vaddress.
45
*/
46
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
47
- return;
48
+ break;
49
case EXCP_BKPT:
50
if (semihosting_enabled()) {
51
int nr;
52
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
53
}
54
}
19
}
55
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
20
valid_mask &= ~SCR_NET;
56
- return;
21
57
+ break;
22
+ if (cpu_isar_feature(aa64_ras, cpu)) {
58
case EXCP_IRQ:
23
+ valid_mask |= SCR_TERR;
59
- armv7m_nvic_acknowledge_irq(env->nvic);
24
+ }
60
break;
25
if (cpu_isar_feature(aa64_lor, cpu)) {
61
case EXCP_EXCEPTION_EXIT:
26
valid_mask |= SCR_TLOR;
62
do_v7m_exception_exit(env);
27
}
63
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
28
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
64
return; /* Never happens. Keep compiler happy. */
29
}
30
} else {
31
valid_mask &= ~(SCR_RW | SCR_ST);
32
+ if (cpu_isar_feature(aa32_ras, cpu)) {
33
+ valid_mask |= SCR_TERR;
34
+ }
65
}
35
}
66
36
67
+ armv7m_nvic_acknowledge_irq(env->nvic);
37
if (!arm_feature(env, ARM_FEATURE_EL2)) {
68
+
38
@@ -XXX,XX +XXX,XX @@ static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
69
+ qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
39
if (cpu_isar_feature(aa64_vh, cpu)) {
70
+
40
valid_mask |= HCR_E2H;
71
/* Align stack pointer if the guest wants that */
41
}
72
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
42
+ if (cpu_isar_feature(aa64_ras, cpu)) {
73
env->regs[13] -= 4;
43
+ valid_mask |= HCR_TERR | HCR_TEA;
44
+ }
45
if (cpu_isar_feature(aa64_lor, cpu)) {
46
valid_mask |= HCR_TLOR;
47
}
74
--
48
--
75
2.7.4
49
2.25.1
76
77
diff view generated by jsdifflib
1
M profile doesn't implement ARM, and the architecturally required
1
From: Richard Henderson <richard.henderson@linaro.org>
2
behaviour for attempts to execute with the Thumb bit clear is to
3
generate a UsageFault with the CFSR INVSTATE bit set. We were
4
incorrectly implementing this as generating an UNDEFINSTR UsageFault;
5
fix this.
6
2
3
Virtual SError exceptions are raised by setting HCR_EL2.VSE,
4
and are routed to EL1 just like other virtual exceptions.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220506180242.216785-16-richard.henderson@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: Alex Bennée <alex.bennee@linaro.org>
9
---
10
---
10
target/arm/cpu.h | 1 +
11
target/arm/cpu.h | 2 ++
11
linux-user/main.c | 1 +
12
target/arm/internals.h | 8 ++++++++
12
target/arm/helper.c | 4 ++++
13
target/arm/syndrome.h | 5 +++++
13
target/arm/translate.c | 8 ++++++--
14
target/arm/cpu.c | 38 +++++++++++++++++++++++++++++++++++++-
14
4 files changed, 12 insertions(+), 2 deletions(-)
15
target/arm/helper.c | 40 +++++++++++++++++++++++++++++++++++++++-
16
5 files changed, 91 insertions(+), 2 deletions(-)
15
17
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
20
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
21
#define EXCP_VFIQ 15
23
#define EXCP_LSERR 21 /* v8M LSERR SecureFault */
22
#define EXCP_SEMIHOST 16 /* semihosting call */
24
#define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
23
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
25
#define EXCP_DIVBYZERO 23 /* v7M DIVBYZERO UsageFault */
24
+#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
26
+#define EXCP_VSERR 24
27
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
25
28
26
#define ARMV7M_EXCP_RESET 1
29
#define ARMV7M_EXCP_RESET 1
27
#define ARMV7M_EXCP_NMI 2
30
@@ -XXX,XX +XXX,XX @@ enum {
28
diff --git a/linux-user/main.c b/linux-user/main.c
31
#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
29
index XXXXXXX..XXXXXXX 100644
32
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_EXT_2
30
--- a/linux-user/main.c
33
#define CPU_INTERRUPT_VFIQ CPU_INTERRUPT_TGT_EXT_3
31
+++ b/linux-user/main.c
34
+#define CPU_INTERRUPT_VSERR CPU_INTERRUPT_TGT_INT_0
32
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
35
33
switch(trapnr) {
36
/* The usual mapping for an AArch64 system register to its AArch32
34
case EXCP_UDEF:
37
* counterpart is for the 32 bit world to have access to the lower
35
case EXCP_NOCP:
38
diff --git a/target/arm/internals.h b/target/arm/internals.h
36
+ case EXCP_INVSTATE:
39
index XXXXXXX..XXXXXXX 100644
37
{
40
--- a/target/arm/internals.h
38
TaskState *ts = cs->opaque;
41
+++ b/target/arm/internals.h
39
uint32_t opcode;
42
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_virq(ARMCPU *cpu);
43
*/
44
void arm_cpu_update_vfiq(ARMCPU *cpu);
45
46
+/**
47
+ * arm_cpu_update_vserr: Update CPU_INTERRUPT_VSERR bit
48
+ *
49
+ * Update the CPU_INTERRUPT_VSERR bit in cs->interrupt_request,
50
+ * following a change to the HCR_EL2.VSE bit.
51
+ */
52
+void arm_cpu_update_vserr(ARMCPU *cpu);
53
+
54
/**
55
* arm_mmu_idx_el:
56
* @env: The cpu environment
57
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/syndrome.h
60
+++ b/target/arm/syndrome.h
61
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_pcalignment(void)
62
return (EC_PCALIGNMENT << ARM_EL_EC_SHIFT) | ARM_EL_IL;
63
}
64
65
+static inline uint32_t syn_serror(uint32_t extra)
66
+{
67
+ return (EC_SERROR << ARM_EL_EC_SHIFT) | ARM_EL_IL | extra;
68
+}
69
+
70
#endif /* TARGET_ARM_SYNDROME_H */
71
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/cpu.c
74
+++ b/target/arm/cpu.c
75
@@ -XXX,XX +XXX,XX @@ static bool arm_cpu_has_work(CPUState *cs)
76
return (cpu->power_state != PSCI_OFF)
77
&& cs->interrupt_request &
78
(CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD
79
- | CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ
80
+ | CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ | CPU_INTERRUPT_VSERR
81
| CPU_INTERRUPT_EXITTB);
82
}
83
84
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
85
return false;
86
}
87
return !(env->daif & PSTATE_I);
88
+ case EXCP_VSERR:
89
+ if (!(hcr_el2 & HCR_AMO) || (hcr_el2 & HCR_TGE)) {
90
+ /* VIRQs are only taken when hypervized. */
91
+ return false;
92
+ }
93
+ return !(env->daif & PSTATE_A);
94
default:
95
g_assert_not_reached();
96
}
97
@@ -XXX,XX +XXX,XX @@ static bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
98
goto found;
99
}
100
}
101
+ if (interrupt_request & CPU_INTERRUPT_VSERR) {
102
+ excp_idx = EXCP_VSERR;
103
+ target_el = 1;
104
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
105
+ cur_el, secure, hcr_el2)) {
106
+ /* Taking a virtual abort clears HCR_EL2.VSE */
107
+ env->cp15.hcr_el2 &= ~HCR_VSE;
108
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_VSERR);
109
+ goto found;
110
+ }
111
+ }
112
return false;
113
114
found:
115
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_vfiq(ARMCPU *cpu)
116
}
117
}
118
119
+void arm_cpu_update_vserr(ARMCPU *cpu)
120
+{
121
+ /*
122
+ * Update the interrupt level for VSERR, which is the HCR_EL2.VSE bit.
123
+ */
124
+ CPUARMState *env = &cpu->env;
125
+ CPUState *cs = CPU(cpu);
126
+
127
+ bool new_state = env->cp15.hcr_el2 & HCR_VSE;
128
+
129
+ if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VSERR) != 0)) {
130
+ if (new_state) {
131
+ cpu_interrupt(cs, CPU_INTERRUPT_VSERR);
132
+ } else {
133
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_VSERR);
134
+ }
135
+ }
136
+}
137
+
138
#ifndef CONFIG_USER_ONLY
139
static void arm_cpu_set_irq(void *opaque, int irq, int level)
140
{
40
diff --git a/target/arm/helper.c b/target/arm/helper.c
141
diff --git a/target/arm/helper.c b/target/arm/helper.c
41
index XXXXXXX..XXXXXXX 100644
142
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/helper.c
143
--- a/target/arm/helper.c
43
+++ b/target/arm/helper.c
144
+++ b/target/arm/helper.c
44
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
145
@@ -XXX,XX +XXX,XX @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
45
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
146
}
46
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
147
}
148
149
- /* External aborts are not possible in QEMU so A bit is always clear */
150
+ if (hcr_el2 & HCR_AMO) {
151
+ if (cs->interrupt_request & CPU_INTERRUPT_VSERR) {
152
+ ret |= CPSR_A;
153
+ }
154
+ }
155
+
156
return ret;
157
}
158
159
@@ -XXX,XX +XXX,XX @@ static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
160
g_assert(qemu_mutex_iothread_locked());
161
arm_cpu_update_virq(cpu);
162
arm_cpu_update_vfiq(cpu);
163
+ arm_cpu_update_vserr(cpu);
164
}
165
166
static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
167
@@ -XXX,XX +XXX,XX @@ void arm_log_exception(CPUState *cs)
168
[EXCP_LSERR] = "v8M LSERR UsageFault",
169
[EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
170
[EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
171
+ [EXCP_VSERR] = "Virtual SERR",
172
};
173
174
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
175
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
176
mask = CPSR_A | CPSR_I | CPSR_F;
177
offset = 4;
47
break;
178
break;
48
+ case EXCP_INVSTATE:
179
+ case EXCP_VSERR:
49
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
180
+ {
50
+ env->v7m.cfsr |= R_V7M_CFSR_INVSTATE_MASK;
181
+ /*
182
+ * Note that this is reported as a data abort, but the DFAR
183
+ * has an UNKNOWN value. Construct the SError syndrome from
184
+ * AET and ExT fields.
185
+ */
186
+ ARMMMUFaultInfo fi = { .type = ARMFault_AsyncExternal, };
187
+
188
+ if (extended_addresses_enabled(env)) {
189
+ env->exception.fsr = arm_fi_to_lfsc(&fi);
190
+ } else {
191
+ env->exception.fsr = arm_fi_to_sfsc(&fi);
192
+ }
193
+ env->exception.fsr |= env->cp15.vsesr_el2 & 0xd000;
194
+ A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr);
195
+ qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x\n",
196
+ env->exception.fsr);
197
+
198
+ new_mode = ARM_CPU_MODE_ABT;
199
+ addr = 0x10;
200
+ mask = CPSR_A | CPSR_I;
201
+ offset = 8;
202
+ }
51
+ break;
203
+ break;
52
case EXCP_SWI:
204
case EXCP_SMC:
53
/* The PC already points to the next instruction. */
205
new_mode = ARM_CPU_MODE_MON;
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
206
addr = 0x08;
55
diff --git a/target/arm/translate.c b/target/arm/translate.c
207
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
56
index XXXXXXX..XXXXXXX 100644
208
case EXCP_VFIQ:
57
--- a/target/arm/translate.c
209
addr += 0x100;
58
+++ b/target/arm/translate.c
210
break;
59
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
211
+ case EXCP_VSERR:
60
TCGv_i32 addr;
212
+ addr += 0x180;
61
TCGv_i64 tmp64;
213
+ /* Construct the SError syndrome from IDS and ISS fields. */
62
214
+ env->exception.syndrome = syn_serror(env->cp15.vsesr_el2 & 0x1ffffff);
63
- /* M variants do not implement ARM mode. */
215
+ env->cp15.esr_el[new_el] = env->exception.syndrome;
64
+ /* M variants do not implement ARM mode; this must raise the INVSTATE
216
+ break;
65
+ * UsageFault exception.
217
default:
66
+ */
218
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
67
if (arm_dc_feature(s, ARM_FEATURE_M)) {
219
}
68
- goto illegal_op;
69
+ gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
70
+ default_exception_el(s));
71
+ return;
72
}
73
cond = insn >> 28;
74
if (cond == 0xf){
75
--
220
--
76
2.7.4
221
2.25.1
77
78
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Despite some superficial similarities of register layout, the
3
Check for and defer any pending virtual SError.
4
M-profile NVIC is really very different from the A-profile GIC.
5
Our current attempt to reuse the GIC code means that we have
6
significant bugs in our NVIC.
7
4
8
Implement the NVIC as an entirely separate device, to give
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
us somewhere we can get the behaviour correct.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220506180242.216785-17-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/helper.h | 1 +
11
target/arm/a32.decode | 16 ++++++++------
12
target/arm/t32.decode | 18 ++++++++--------
13
target/arm/op_helper.c | 43 ++++++++++++++++++++++++++++++++++++++
14
target/arm/translate-a64.c | 17 +++++++++++++++
15
target/arm/translate.c | 23 ++++++++++++++++++++
16
6 files changed, 103 insertions(+), 15 deletions(-)
10
17
11
This initial commit does not attempt to implement exception
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
12
priority escalation, since the GIC-based code didn't either.
19
index XXXXXXX..XXXXXXX 100644
13
It does fix a few bugs in passing:
20
--- a/target/arm/helper.h
14
* ICSR.RETTOBASE polarity was wrong and didn't account for
21
+++ b/target/arm/helper.h
15
internal exceptions
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(wfe, void, env)
16
* ICSR.VECTPENDING was 16 too high if the pending exception
23
DEF_HELPER_1(yield, void, env)
17
was for an external interrupt
24
DEF_HELPER_1(pre_hvc, void, env)
18
* UsageFault, BusFault and MemFault were not disabled on reset
25
DEF_HELPER_2(pre_smc, void, env, i32)
19
as they are supposed to be
26
+DEF_HELPER_1(vesb, void, env)
20
27
21
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
28
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
22
[PMM: reworked, various bugs and stylistic cleanups]
29
DEF_HELPER_2(cpsr_write_eret, void, env, i32)
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
diff --git a/target/arm/a32.decode b/target/arm/a32.decode
24
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
31
index XXXXXXX..XXXXXXX 100644
25
---
32
--- a/target/arm/a32.decode
26
hw/intc/armv7m_nvic.c | 738 ++++++++++++++++++++++++++++++++++++++++----------
33
+++ b/target/arm/a32.decode
27
hw/intc/trace-events | 15 +
34
@@ -XXX,XX +XXX,XX @@ SMULTT .... 0001 0110 .... 0000 .... 1110 .... @rd0mn
28
2 files changed, 609 insertions(+), 144 deletions(-)
35
29
36
{
30
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
37
{
31
index XXXXXXX..XXXXXXX 100644
38
- YIELD ---- 0011 0010 0000 1111 ---- 0000 0001
32
--- a/hw/intc/armv7m_nvic.c
39
- WFE ---- 0011 0010 0000 1111 ---- 0000 0010
33
+++ b/hw/intc/armv7m_nvic.c
40
- WFI ---- 0011 0010 0000 1111 ---- 0000 0011
34
@@ -XXX,XX +XXX,XX @@
41
+ [
35
#include "hw/sysbus.h"
42
+ YIELD ---- 0011 0010 0000 1111 ---- 0000 0001
36
#include "qemu/timer.h"
43
+ WFE ---- 0011 0010 0000 1111 ---- 0000 0010
37
#include "hw/arm/arm.h"
44
+ WFI ---- 0011 0010 0000 1111 ---- 0000 0011
38
+#include "target/arm/cpu.h"
45
39
#include "exec/address-spaces.h"
46
- # TODO: Implement SEV, SEVL; may help SMP performance.
40
-#include "gic_internal.h"
47
- # SEV ---- 0011 0010 0000 1111 ---- 0000 0100
41
#include "qemu/log.h"
48
- # SEVL ---- 0011 0010 0000 1111 ---- 0000 0101
42
+#include "trace.h"
49
+ # TODO: Implement SEV, SEVL; may help SMP performance.
43
+
50
+ # SEV ---- 0011 0010 0000 1111 ---- 0000 0100
44
+/* IRQ number counting:
51
+ # SEVL ---- 0011 0010 0000 1111 ---- 0000 0101
45
+ *
52
+
46
+ * the num-irq property counts the number of external IRQ lines
53
+ ESB ---- 0011 0010 0000 1111 ---- 0001 0000
47
+ *
54
+ ]
48
+ * NVICState::num_irq counts the total number of exceptions
55
49
+ * (external IRQs, the 15 internal exceptions including reset,
56
# The canonical nop ends in 00000000, but the whole of the
50
+ * and one for the unused exception number 0).
57
# rest of the space executes as nop if otherwise unsupported.
51
+ *
58
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
52
+ * NVIC_MAX_IRQ is the highest permitted number of external IRQ lines.
59
index XXXXXXX..XXXXXXX 100644
53
+ *
60
--- a/target/arm/t32.decode
54
+ * NVIC_MAX_VECTORS is the highest permitted number of exceptions.
61
+++ b/target/arm/t32.decode
55
+ *
62
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
56
+ * Iterating through all exceptions should typically be done with
63
[
57
+ * for (i = 1; i < s->num_irq; i++) to avoid the unused slot 0.
64
# Hints, and CPS
58
+ *
65
{
59
+ * The external qemu_irq lines are the NVIC's external IRQ lines,
66
- YIELD 1111 0011 1010 1111 1000 0000 0000 0001
60
+ * so line 0 is exception 16.
67
- WFE 1111 0011 1010 1111 1000 0000 0000 0010
61
+ *
68
- WFI 1111 0011 1010 1111 1000 0000 0000 0011
62
+ * In the terminology of the architecture manual, "interrupts" are
69
+ [
63
+ * a subcategory of exception referring to the external interrupts
70
+ YIELD 1111 0011 1010 1111 1000 0000 0000 0001
64
+ * (which are exception numbers NVIC_FIRST_IRQ and upward).
71
+ WFE 1111 0011 1010 1111 1000 0000 0000 0010
65
+ * For historical reasons QEMU tends to use "interrupt" and
72
+ WFI 1111 0011 1010 1111 1000 0000 0000 0011
66
+ * "exception" more or less interchangeably.
73
74
- # TODO: Implement SEV, SEVL; may help SMP performance.
75
- # SEV 1111 0011 1010 1111 1000 0000 0000 0100
76
- # SEVL 1111 0011 1010 1111 1000 0000 0000 0101
77
+ # TODO: Implement SEV, SEVL; may help SMP performance.
78
+ # SEV 1111 0011 1010 1111 1000 0000 0000 0100
79
+ # SEVL 1111 0011 1010 1111 1000 0000 0000 0101
80
81
- # For M-profile minimal-RAS ESB can be a NOP, which is the
82
- # default behaviour since it is in the hint space.
83
- # ESB 1111 0011 1010 1111 1000 0000 0001 0000
84
+ ESB 1111 0011 1010 1111 1000 0000 0001 0000
85
+ ]
86
87
# The canonical nop ends in 0000 0000, but the whole rest
88
# of the space is "reserved hint, behaves as nop".
89
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/op_helper.c
92
+++ b/target/arm/op_helper.c
93
@@ -XXX,XX +XXX,XX @@ void HELPER(probe_access)(CPUARMState *env, target_ulong ptr,
94
access_type, mmu_idx, ra);
95
}
96
}
97
+
98
+/*
99
+ * This function corresponds to AArch64.vESBOperation().
100
+ * Note that the AArch32 version is not functionally different.
67
+ */
101
+ */
68
+#define NVIC_FIRST_IRQ 16
102
+void HELPER(vesb)(CPUARMState *env)
69
+#define NVIC_MAX_VECTORS 512
103
+{
70
+#define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ)
104
+ /*
71
+
105
+ * The EL2Enabled() check is done inside arm_hcr_el2_eff,
72
+/* Effective running priority of the CPU when no exception is active
106
+ * and will return HCR_EL2.VSE == 0, so nothing happens.
73
+ * (higher than the highest possible priority value)
74
+ */
75
+#define NVIC_NOEXC_PRIO 0x100
76
+
77
+typedef struct VecInfo {
78
+ /* Exception priorities can range from -3 to 255; only the unmodifiable
79
+ * priority values for RESET, NMI and HardFault can be negative.
80
+ */
107
+ */
81
+ int16_t prio;
108
+ uint64_t hcr = arm_hcr_el2_eff(env);
82
+ uint8_t enabled;
109
+ bool enabled = !(hcr & HCR_TGE) && (hcr & HCR_AMO);
83
+ uint8_t pending;
110
+ bool pending = enabled && (hcr & HCR_VSE);
84
+ uint8_t active;
111
+ bool masked = (env->daif & PSTATE_A);
85
+ uint8_t level; /* exceptions <=15 never set level */
112
+
86
+} VecInfo;
113
+ /* If VSE pending and masked, defer the exception. */
87
114
+ if (pending && masked) {
88
typedef struct NVICState {
115
+ uint32_t syndrome;
89
- GICState gic;
116
+
90
+ /*< private >*/
117
+ if (arm_el_is_aa64(env, 1)) {
91
+ SysBusDevice parent_obj;
118
+ /* Copy across IDS and ISS from VSESR. */
92
+ /*< public >*/
119
+ syndrome = env->cp15.vsesr_el2 & 0x1ffffff;
93
+
120
+ } else {
94
ARMCPU *cpu;
121
+ ARMMMUFaultInfo fi = { .type = ARMFault_AsyncExternal };
95
122
+
96
+ VecInfo vectors[NVIC_MAX_VECTORS];
123
+ if (extended_addresses_enabled(env)) {
97
uint32_t prigroup;
124
+ syndrome = arm_fi_to_lfsc(&fi);
98
125
+ } else {
99
+ /* vectpending and exception_prio are both cached state that can
126
+ syndrome = arm_fi_to_sfsc(&fi);
100
+ * be recalculated from the vectors[] array and the prigroup field.
101
+ */
102
+ unsigned int vectpending; /* highest prio pending enabled exception */
103
+ int exception_prio; /* group prio of the highest prio active exception */
104
+
105
struct {
106
uint32_t control;
107
uint32_t reload;
108
int64_t tick;
109
QEMUTimer *timer;
110
} systick;
111
+
112
MemoryRegion sysregmem;
113
- MemoryRegion gic_iomem_alias;
114
MemoryRegion container;
115
+
116
uint32_t num_irq;
117
+ qemu_irq excpout;
118
qemu_irq sysresetreq;
119
} NVICState;
120
121
#define TYPE_NVIC "armv7m_nvic"
122
-/**
123
- * NVICClass:
124
- * @parent_reset: the parent class' reset handler.
125
- *
126
- * A model of the v7M NVIC and System Controller
127
- */
128
-typedef struct NVICClass {
129
- /*< private >*/
130
- ARMGICClass parent_class;
131
- /*< public >*/
132
- DeviceRealize parent_realize;
133
- void (*parent_reset)(DeviceState *dev);
134
-} NVICClass;
135
-
136
-#define NVIC_CLASS(klass) \
137
- OBJECT_CLASS_CHECK(NVICClass, (klass), TYPE_NVIC)
138
-#define NVIC_GET_CLASS(obj) \
139
- OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
140
+
141
#define NVIC(obj) \
142
OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
143
144
@@ -XXX,XX +XXX,XX @@ static void systick_reset(NVICState *s)
145
timer_del(s->systick.timer);
146
}
147
148
-/* The external routines use the hardware vector numbering, ie. the first
149
- IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
150
+static int nvic_pending_prio(NVICState *s)
151
+{
152
+ /* return the priority of the current pending interrupt,
153
+ * or NVIC_NOEXC_PRIO if no interrupt is pending
154
+ */
155
+ return s->vectpending ? s->vectors[s->vectpending].prio : NVIC_NOEXC_PRIO;
156
+}
157
+
158
+/* Return the value of the ISCR RETTOBASE bit:
159
+ * 1 if there is exactly one active exception
160
+ * 0 if there is more than one active exception
161
+ * UNKNOWN if there are no active exceptions (we choose 1,
162
+ * which matches the choice Cortex-M3 is documented as making).
163
+ *
164
+ * NB: some versions of the documentation talk about this
165
+ * counting "active exceptions other than the one shown by IPSR";
166
+ * this is only different in the obscure corner case where guest
167
+ * code has manually deactivated an exception and is about
168
+ * to fail an exception-return integrity check. The definition
169
+ * above is the one from the v8M ARM ARM and is also in line
170
+ * with the behaviour documented for the Cortex-M3.
171
+ */
172
+static bool nvic_rettobase(NVICState *s)
173
+{
174
+ int irq, nhand = 0;
175
+
176
+ for (irq = ARMV7M_EXCP_RESET; irq < s->num_irq; irq++) {
177
+ if (s->vectors[irq].active) {
178
+ nhand++;
179
+ if (nhand == 2) {
180
+ return 0;
181
+ }
127
+ }
128
+ /* Copy across AET and ExT from VSESR. */
129
+ syndrome |= env->cp15.vsesr_el2 & 0xd000;
182
+ }
130
+ }
183
+ }
131
+
184
+
132
+ /* Set VDISR_EL2.A along with the syndrome. */
185
+ return 1;
133
+ env->cp15.vdisr_el2 = syndrome | (1u << 31);
186
+}
134
+
187
+
135
+ /* Clear pending virtual SError */
188
+/* Return the value of the ISCR ISRPENDING bit:
136
+ env->cp15.hcr_el2 &= ~HCR_VSE;
189
+ * 1 if an external interrupt is pending
137
+ cpu_reset_interrupt(env_cpu(env), CPU_INTERRUPT_VSERR);
190
+ * 0 if no external interrupt is pending
191
+ */
192
+static bool nvic_isrpending(NVICState *s)
193
+{
194
+ int irq;
195
+
196
+ /* We can shortcut if the highest priority pending interrupt
197
+ * happens to be external or if there is nothing pending.
198
+ */
199
+ if (s->vectpending > NVIC_FIRST_IRQ) {
200
+ return true;
201
+ }
202
+ if (s->vectpending == 0) {
203
+ return false;
204
+ }
205
+
206
+ for (irq = NVIC_FIRST_IRQ; irq < s->num_irq; irq++) {
207
+ if (s->vectors[irq].pending) {
208
+ return true;
209
+ }
210
+ }
211
+ return false;
212
+}
213
+
214
+/* Return a mask word which clears the subpriority bits from
215
+ * a priority value for an M-profile exception, leaving only
216
+ * the group priority.
217
+ */
218
+static inline uint32_t nvic_gprio_mask(NVICState *s)
219
+{
220
+ return ~0U << (s->prigroup + 1);
221
+}
222
+
223
+/* Recompute vectpending and exception_prio */
224
+static void nvic_recompute_state(NVICState *s)
225
+{
226
+ int i;
227
+ int pend_prio = NVIC_NOEXC_PRIO;
228
+ int active_prio = NVIC_NOEXC_PRIO;
229
+ int pend_irq = 0;
230
+
231
+ for (i = 1; i < s->num_irq; i++) {
232
+ VecInfo *vec = &s->vectors[i];
233
+
234
+ if (vec->enabled && vec->pending && vec->prio < pend_prio) {
235
+ pend_prio = vec->prio;
236
+ pend_irq = i;
237
+ }
238
+ if (vec->active && vec->prio < active_prio) {
239
+ active_prio = vec->prio;
240
+ }
241
+ }
242
+
243
+ s->vectpending = pend_irq;
244
+ s->exception_prio = active_prio & nvic_gprio_mask(s);
245
+
246
+ trace_nvic_recompute_state(s->vectpending, s->exception_prio);
247
+}
248
+
249
+/* Return the current execution priority of the CPU
250
+ * (equivalent to the pseudocode ExecutionPriority function).
251
+ * This is a value between -2 (NMI priority) and NVIC_NOEXC_PRIO.
252
+ */
253
+static inline int nvic_exec_prio(NVICState *s)
254
+{
255
+ CPUARMState *env = &s->cpu->env;
256
+ int running;
257
+
258
+ if (env->daif & PSTATE_F) { /* FAULTMASK */
259
+ running = -1;
260
+ } else if (env->daif & PSTATE_I) { /* PRIMASK */
261
+ running = 0;
262
+ } else if (env->v7m.basepri > 0) {
263
+ running = env->v7m.basepri & nvic_gprio_mask(s);
264
+ } else {
265
+ running = NVIC_NOEXC_PRIO; /* lower than any possible priority */
266
+ }
267
+ /* consider priority of active handler */
268
+ return MIN(running, s->exception_prio);
269
+}
270
+
271
+/* caller must call nvic_irq_update() after this */
272
+static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
273
+{
274
+ assert(irq > ARMV7M_EXCP_NMI); /* only use for configurable prios */
275
+ assert(irq < s->num_irq);
276
+
277
+ s->vectors[irq].prio = prio;
278
+
279
+ trace_nvic_set_prio(irq, prio);
280
+}
281
+
282
+/* Recompute state and assert irq line accordingly.
283
+ * Must be called after changes to:
284
+ * vec->active, vec->enabled, vec->pending or vec->prio for any vector
285
+ * prigroup
286
+ */
287
+static void nvic_irq_update(NVICState *s)
288
+{
289
+ int lvl;
290
+ int pend_prio;
291
+
292
+ nvic_recompute_state(s);
293
+ pend_prio = nvic_pending_prio(s);
294
+
295
+ /* Raise NVIC output if this IRQ would be taken, except that we
296
+ * ignore the effects of the BASEPRI, FAULTMASK and PRIMASK (which
297
+ * will be checked for in arm_v7m_cpu_exec_interrupt()); changes
298
+ * to those CPU registers don't cause us to recalculate the NVIC
299
+ * pending info.
300
+ */
301
+ lvl = (pend_prio < s->exception_prio);
302
+ trace_nvic_irq_update(s->vectpending, pend_prio, s->exception_prio, lvl);
303
+ qemu_set_irq(s->excpout, lvl);
304
+}
305
+
306
+static void armv7m_nvic_clear_pending(void *opaque, int irq)
307
+{
308
+ NVICState *s = (NVICState *)opaque;
309
+ VecInfo *vec;
310
+
311
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
312
+
313
+ vec = &s->vectors[irq];
314
+ trace_nvic_clear_pending(irq, vec->enabled, vec->prio);
315
+ if (vec->pending) {
316
+ vec->pending = 0;
317
+ nvic_irq_update(s);
318
+ }
138
+ }
319
+}
139
+}
320
+
140
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
321
void armv7m_nvic_set_pending(void *opaque, int irq)
141
index XXXXXXX..XXXXXXX 100644
322
{
142
--- a/target/arm/translate-a64.c
323
NVICState *s = (NVICState *)opaque;
143
+++ b/target/arm/translate-a64.c
324
- if (irq >= 16)
144
@@ -XXX,XX +XXX,XX @@ static void handle_hint(DisasContext *s, uint32_t insn,
325
- irq += 16;
145
gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
326
- gic_set_pending_private(&s->gic, 0, irq);
327
+ VecInfo *vec;
328
+
329
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
330
+
331
+ vec = &s->vectors[irq];
332
+ trace_nvic_set_pending(irq, vec->enabled, vec->prio);
333
+ if (!vec->pending) {
334
+ vec->pending = 1;
335
+ nvic_irq_update(s);
336
+ }
337
}
338
339
/* Make pending IRQ active. */
340
int armv7m_nvic_acknowledge_irq(void *opaque)
341
{
342
NVICState *s = (NVICState *)opaque;
343
- uint32_t irq;
344
-
345
- irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
346
- if (irq == 1023)
347
- hw_error("Interrupt but no vector\n");
348
- if (irq >= 32)
349
- irq -= 16;
350
- return irq;
351
+ CPUARMState *env = &s->cpu->env;
352
+ const int pending = s->vectpending;
353
+ const int running = nvic_exec_prio(s);
354
+ int pendgroupprio;
355
+ VecInfo *vec;
356
+
357
+ assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
358
+
359
+ vec = &s->vectors[pending];
360
+
361
+ assert(vec->enabled);
362
+ assert(vec->pending);
363
+
364
+ pendgroupprio = vec->prio & nvic_gprio_mask(s);
365
+ assert(pendgroupprio < running);
366
+
367
+ trace_nvic_acknowledge_irq(pending, vec->prio);
368
+
369
+ vec->active = 1;
370
+ vec->pending = 0;
371
+
372
+ env->v7m.exception = s->vectpending;
373
+
374
+ nvic_irq_update(s);
375
+
376
+ return env->v7m.exception;
377
}
378
379
void armv7m_nvic_complete_irq(void *opaque, int irq)
380
{
381
NVICState *s = (NVICState *)opaque;
382
- if (irq >= 16)
383
- irq += 16;
384
- gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
385
+ VecInfo *vec;
386
+
387
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
388
+
389
+ vec = &s->vectors[irq];
390
+
391
+ trace_nvic_complete_irq(irq);
392
+
393
+ vec->active = 0;
394
+ if (vec->level) {
395
+ /* Re-pend the exception if it's still held high; only
396
+ * happens for extenal IRQs
397
+ */
398
+ assert(irq >= NVIC_FIRST_IRQ);
399
+ vec->pending = 1;
400
+ }
401
+
402
+ nvic_irq_update(s);
403
+}
404
+
405
+/* callback when external interrupt line is changed */
406
+static void set_irq_level(void *opaque, int n, int level)
407
+{
408
+ NVICState *s = opaque;
409
+ VecInfo *vec;
410
+
411
+ n += NVIC_FIRST_IRQ;
412
+
413
+ assert(n >= NVIC_FIRST_IRQ && n < s->num_irq);
414
+
415
+ trace_nvic_set_irq_level(n, level);
416
+
417
+ /* The pending status of an external interrupt is
418
+ * latched on rising edge and exception handler return.
419
+ *
420
+ * Pulsing the IRQ will always run the handler
421
+ * once, and the handler will re-run until the
422
+ * level is low when the handler completes.
423
+ */
424
+ vec = &s->vectors[n];
425
+ if (level != vec->level) {
426
+ vec->level = level;
427
+ if (level) {
428
+ armv7m_nvic_set_pending(s, n);
429
+ }
430
+ }
431
}
432
433
static uint32_t nvic_readl(NVICState *s, uint32_t offset)
434
{
435
ARMCPU *cpu = s->cpu;
436
uint32_t val;
437
- int irq;
438
439
switch (offset) {
440
case 4: /* Interrupt Control Type. */
441
- return (s->num_irq / 32) - 1;
442
+ return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
443
case 0x10: /* SysTick Control and Status. */
444
val = s->systick.control;
445
s->systick.control &= ~SYSTICK_COUNTFLAG;
446
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
447
case 0xd04: /* Interrupt Control State. */
448
/* VECTACTIVE */
449
val = cpu->env.v7m.exception;
450
- if (val == 1023) {
451
- val = 0;
452
- } else if (val >= 32) {
453
- val -= 16;
454
- }
455
/* VECTPENDING */
456
- if (s->gic.current_pending[0] != 1023)
457
- val |= (s->gic.current_pending[0] << 12);
458
- /* ISRPENDING and RETTOBASE */
459
- for (irq = 32; irq < s->num_irq; irq++) {
460
- if (s->gic.irq_state[irq].pending) {
461
- val |= (1 << 22);
462
- break;
463
- }
464
- if (irq != cpu->env.v7m.exception && s->gic.irq_state[irq].active) {
465
- val |= (1 << 11);
466
- }
467
+ val |= (s->vectpending & 0xff) << 12;
468
+ /* ISRPENDING - set if any external IRQ is pending */
469
+ if (nvic_isrpending(s)) {
470
+ val |= (1 << 22);
471
+ }
472
+ /* RETTOBASE - set if only one handler is active */
473
+ if (nvic_rettobase(s)) {
474
+ val |= (1 << 11);
475
}
476
/* PENDSTSET */
477
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
478
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].pending) {
479
val |= (1 << 26);
480
+ }
481
/* PENDSVSET */
482
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
483
+ if (s->vectors[ARMV7M_EXCP_PENDSV].pending) {
484
val |= (1 << 28);
485
+ }
486
/* NMIPENDSET */
487
- if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
488
+ if (s->vectors[ARMV7M_EXCP_NMI].pending) {
489
val |= (1 << 31);
490
+ }
491
+ /* ISRPREEMPT not implemented */
492
return val;
493
case 0xd08: /* Vector Table Offset. */
494
return cpu->env.v7m.vecbase;
495
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
496
return cpu->env.v7m.ccr;
497
case 0xd24: /* System Handler Status. */
498
val = 0;
499
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
500
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1);
501
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3);
502
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7);
503
- if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8);
504
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10);
505
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11);
506
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12);
507
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13);
508
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14);
509
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15);
510
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16);
511
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17);
512
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
513
+ if (s->vectors[ARMV7M_EXCP_MEM].active) {
514
+ val |= (1 << 0);
515
+ }
516
+ if (s->vectors[ARMV7M_EXCP_BUS].active) {
517
+ val |= (1 << 1);
518
+ }
519
+ if (s->vectors[ARMV7M_EXCP_USAGE].active) {
520
+ val |= (1 << 3);
521
+ }
522
+ if (s->vectors[ARMV7M_EXCP_SVC].active) {
523
+ val |= (1 << 7);
524
+ }
525
+ if (s->vectors[ARMV7M_EXCP_DEBUG].active) {
526
+ val |= (1 << 8);
527
+ }
528
+ if (s->vectors[ARMV7M_EXCP_PENDSV].active) {
529
+ val |= (1 << 10);
530
+ }
531
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].active) {
532
+ val |= (1 << 11);
533
+ }
534
+ if (s->vectors[ARMV7M_EXCP_USAGE].pending) {
535
+ val |= (1 << 12);
536
+ }
537
+ if (s->vectors[ARMV7M_EXCP_MEM].pending) {
538
+ val |= (1 << 13);
539
+ }
540
+ if (s->vectors[ARMV7M_EXCP_BUS].pending) {
541
+ val |= (1 << 14);
542
+ }
543
+ if (s->vectors[ARMV7M_EXCP_SVC].pending) {
544
+ val |= (1 << 15);
545
+ }
546
+ if (s->vectors[ARMV7M_EXCP_MEM].enabled) {
547
+ val |= (1 << 16);
548
+ }
549
+ if (s->vectors[ARMV7M_EXCP_BUS].enabled) {
550
+ val |= (1 << 17);
551
+ }
552
+ if (s->vectors[ARMV7M_EXCP_USAGE].enabled) {
553
+ val |= (1 << 18);
554
+ }
555
return val;
556
case 0xd28: /* Configurable Fault Status. */
557
return cpu->env.v7m.cfsr;
558
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
559
if (value & (1 << 28)) {
560
armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
561
} else if (value & (1 << 27)) {
562
- s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending = 0;
563
- gic_update(&s->gic);
564
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_PENDSV);
565
}
566
if (value & (1 << 26)) {
567
armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
568
} else if (value & (1 << 25)) {
569
- s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending = 0;
570
- gic_update(&s->gic);
571
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_SYSTICK);
572
}
146
}
573
break;
147
break;
574
case 0xd08: /* Vector Table Offset. */
148
+ case 0b10000: /* ESB */
575
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
149
+ /* Without RAS, we must implement this as NOP. */
576
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
150
+ if (dc_isar_feature(aa64_ras, s)) {
577
}
151
+ /*
578
s->prigroup = extract32(value, 8, 3);
152
+ * QEMU does not have a source of physical SErrors,
579
+ nvic_irq_update(s);
153
+ * so we are only concerned with virtual SErrors.
580
}
154
+ * The pseudocode in the ARM for this case is
581
break;
155
+ * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
582
case 0xd10: /* System Control. */
156
+ * AArch64.vESBOperation();
583
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
157
+ * Most of the condition can be evaluated at translation time.
584
case 0xd24: /* System Handler Control. */
158
+ * Test for EL2 present, and defer test for SEL2 to runtime.
585
/* TODO: Real hardware allows you to set/clear the active bits
159
+ */
586
under some circumstances. We don't implement this. */
160
+ if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
587
- s->gic.irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
161
+ gen_helper_vesb(cpu_env);
588
- s->gic.irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
589
- s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
590
+ s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
591
+ s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
592
+ s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
593
+ nvic_irq_update(s);
594
break;
595
case 0xd28: /* Configurable Fault Status. */
596
cpu->env.v7m.cfsr &= ~value; /* W1C */
597
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
598
"NVIC: Aux fault status registers unimplemented\n");
599
break;
600
case 0xf00: /* Software Triggered Interrupt Register */
601
+ {
602
/* user mode can only write to STIR if CCR.USERSETMPEND permits it */
603
- if ((value & 0x1ff) < s->num_irq &&
604
+ int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
605
+ if (excnum < s->num_irq &&
606
(arm_current_el(&cpu->env) ||
607
(cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) {
608
- gic_set_pending_private(&s->gic, 0, value & 0x1ff);
609
+ armv7m_nvic_set_pending(s, excnum);
610
}
611
break;
612
+ }
613
default:
614
qemu_log_mask(LOG_GUEST_ERROR,
615
"NVIC: Bad write offset 0x%x\n", offset);
616
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
617
{
618
NVICState *s = (NVICState *)opaque;
619
uint32_t offset = addr;
620
- int i;
621
+ unsigned i, startvec, end;
622
uint32_t val;
623
624
switch (offset) {
625
+ /* reads of set and clear both return the status */
626
+ case 0x100 ... 0x13f: /* NVIC Set enable */
627
+ offset += 0x80;
628
+ /* fall through */
629
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
630
+ val = 0;
631
+ startvec = offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */
632
+
633
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
634
+ if (s->vectors[startvec + i].enabled) {
635
+ val |= (1 << i);
636
+ }
162
+ }
637
+ }
163
+ }
638
+ break;
164
+ break;
639
+ case 0x200 ... 0x23f: /* NVIC Set pend */
165
case 0b11000: /* PACIAZ */
640
+ offset += 0x80;
166
if (s->pauth_active) {
641
+ /* fall through */
167
gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
642
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
168
diff --git a/target/arm/translate.c b/target/arm/translate.c
643
+ val = 0;
169
index XXXXXXX..XXXXXXX 100644
644
+ startvec = offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */
170
--- a/target/arm/translate.c
645
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
171
+++ b/target/arm/translate.c
646
+ if (s->vectors[startvec + i].pending) {
172
@@ -XXX,XX +XXX,XX @@ static bool trans_WFI(DisasContext *s, arg_WFI *a)
647
+ val |= (1 << i);
173
return true;
648
+ }
649
+ }
650
+ break;
651
+ case 0x300 ... 0x33f: /* NVIC Active */
652
+ val = 0;
653
+ startvec = offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */
654
+
655
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
656
+ if (s->vectors[startvec + i].active) {
657
+ val |= (1 << i);
658
+ }
659
+ }
660
+ break;
661
+ case 0x400 ... 0x5ef: /* NVIC Priority */
662
+ val = 0;
663
+ startvec = offset - 0x400 + NVIC_FIRST_IRQ; /* vector # */
664
+
665
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
666
+ val |= s->vectors[startvec + i].prio << (8 * i);
667
+ }
668
+ break;
669
case 0xd18 ... 0xd23: /* System Handler Priority. */
670
val = 0;
671
for (i = 0; i < size; i++) {
672
- val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
673
+ val |= s->vectors[(offset - 0xd14) + i].prio << (i * 8);
674
}
675
- return val;
676
+ break;
677
case 0xfe0 ... 0xfff: /* ID. */
678
if (offset & 3) {
679
- return 0;
680
+ val = 0;
681
+ } else {
682
+ val = nvic_id[(offset - 0xfe0) >> 2];
683
+ }
684
+ break;
685
+ default:
686
+ if (size == 4) {
687
+ val = nvic_readl(s, offset);
688
+ } else {
689
+ qemu_log_mask(LOG_GUEST_ERROR,
690
+ "NVIC: Bad read of size %d at offset 0x%x\n",
691
+ size, offset);
692
+ val = 0;
693
}
694
- return nvic_id[(offset - 0xfe0) >> 2];
695
- }
696
- if (size == 4) {
697
- return nvic_readl(s, offset);
698
}
699
- qemu_log_mask(LOG_GUEST_ERROR,
700
- "NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
701
- return 0;
702
+
703
+ trace_nvic_sysreg_read(addr, val, size);
704
+ return val;
705
}
174
}
706
175
707
static void nvic_sysreg_write(void *opaque, hwaddr addr,
176
+static bool trans_ESB(DisasContext *s, arg_ESB *a)
708
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
177
+{
709
{
178
+ /*
710
NVICState *s = (NVICState *)opaque;
179
+ * For M-profile, minimal-RAS ESB can be a NOP.
711
uint32_t offset = addr;
180
+ * Without RAS, we must implement this as NOP.
712
- int i;
181
+ */
713
+ unsigned i, startvec, end;
182
+ if (!arm_dc_feature(s, ARM_FEATURE_M) && dc_isar_feature(aa32_ras, s)) {
714
+ unsigned setval = 0;
183
+ /*
715
+
184
+ * QEMU does not have a source of physical SErrors,
716
+ trace_nvic_sysreg_write(addr, value, size);
185
+ * so we are only concerned with virtual SErrors.
717
186
+ * The pseudocode in the ARM for this case is
718
switch (offset) {
187
+ * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
719
+ case 0x100 ... 0x13f: /* NVIC Set enable */
188
+ * AArch32.vESBOperation();
720
+ offset += 0x80;
189
+ * Most of the condition can be evaluated at translation time.
721
+ setval = 1;
190
+ * Test for EL2 present, and defer test for SEL2 to runtime.
722
+ /* fall through */
723
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
724
+ startvec = 8 * (offset - 0x180) + NVIC_FIRST_IRQ;
725
+
726
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
727
+ if (value & (1 << i)) {
728
+ s->vectors[startvec + i].enabled = setval;
729
+ }
730
+ }
731
+ nvic_irq_update(s);
732
+ return;
733
+ case 0x200 ... 0x23f: /* NVIC Set pend */
734
+ /* the special logic in armv7m_nvic_set_pending()
735
+ * is not needed since IRQs are never escalated
736
+ */
191
+ */
737
+ offset += 0x80;
192
+ if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
738
+ setval = 1;
193
+ gen_helper_vesb(cpu_env);
739
+ /* fall through */
740
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
741
+ startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
742
+
743
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
744
+ if (value & (1 << i)) {
745
+ s->vectors[startvec + i].pending = setval;
746
+ }
747
+ }
748
+ nvic_irq_update(s);
749
+ return;
750
+ case 0x300 ... 0x33f: /* NVIC Active */
751
+ return; /* R/O */
752
+ case 0x400 ... 0x5ef: /* NVIC Priority */
753
+ startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
754
+
755
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
756
+ set_prio(s, startvec + i, (value >> (i * 8)) & 0xff);
757
+ }
758
+ nvic_irq_update(s);
759
+ return;
760
case 0xd18 ... 0xd23: /* System Handler Priority. */
761
for (i = 0; i < size; i++) {
762
- s->gic.priority1[(offset - 0xd14) + i][0] =
763
- (value >> (i * 8)) & 0xff;
764
+ unsigned hdlidx = (offset - 0xd14) + i;
765
+ set_prio(s, hdlidx, (value >> (i * 8)) & 0xff);
766
}
767
- gic_update(&s->gic);
768
+ nvic_irq_update(s);
769
return;
770
}
771
if (size == 4) {
772
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
773
.endianness = DEVICE_NATIVE_ENDIAN,
774
};
775
776
+static int nvic_post_load(void *opaque, int version_id)
777
+{
778
+ NVICState *s = opaque;
779
+ unsigned i;
780
+
781
+ /* Check for out of range priority settings */
782
+ if (s->vectors[ARMV7M_EXCP_RESET].prio != -3 ||
783
+ s->vectors[ARMV7M_EXCP_NMI].prio != -2 ||
784
+ s->vectors[ARMV7M_EXCP_HARD].prio != -1) {
785
+ return 1;
786
+ }
787
+ for (i = ARMV7M_EXCP_MEM; i < s->num_irq; i++) {
788
+ if (s->vectors[i].prio & ~0xff) {
789
+ return 1;
790
+ }
194
+ }
791
+ }
195
+ }
792
+
196
+ return true;
793
+ nvic_recompute_state(s);
794
+
795
+ return 0;
796
+}
197
+}
797
+
198
+
798
+static const VMStateDescription vmstate_VecInfo = {
199
static bool trans_NOP(DisasContext *s, arg_NOP *a)
799
+ .name = "armv7m_nvic_info",
800
+ .version_id = 1,
801
+ .minimum_version_id = 1,
802
+ .fields = (VMStateField[]) {
803
+ VMSTATE_INT16(prio, VecInfo),
804
+ VMSTATE_UINT8(enabled, VecInfo),
805
+ VMSTATE_UINT8(pending, VecInfo),
806
+ VMSTATE_UINT8(active, VecInfo),
807
+ VMSTATE_UINT8(level, VecInfo),
808
+ VMSTATE_END_OF_LIST()
809
+ }
810
+};
811
+
812
static const VMStateDescription vmstate_nvic = {
813
.name = "armv7m_nvic",
814
- .version_id = 2,
815
- .minimum_version_id = 2,
816
+ .version_id = 3,
817
+ .minimum_version_id = 3,
818
+ .post_load = &nvic_post_load,
819
.fields = (VMStateField[]) {
820
+ VMSTATE_STRUCT_ARRAY(vectors, NVICState, NVIC_MAX_VECTORS, 1,
821
+ vmstate_VecInfo, VecInfo),
822
VMSTATE_UINT32(systick.control, NVICState),
823
VMSTATE_UINT32(systick.reload, NVICState),
824
VMSTATE_INT64(systick.tick, NVICState),
825
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
826
}
827
};
828
829
+static Property props_nvic[] = {
830
+ /* Number of external IRQ lines (so excluding the 16 internal exceptions) */
831
+ DEFINE_PROP_UINT32("num-irq", NVICState, num_irq, 64),
832
+ DEFINE_PROP_END_OF_LIST()
833
+};
834
+
835
static void armv7m_nvic_reset(DeviceState *dev)
836
{
200
{
837
NVICState *s = NVIC(dev);
201
return true;
838
- NVICClass *nc = NVIC_GET_CLASS(s);
839
- nc->parent_reset(dev);
840
- /* Common GIC reset resets to disabled; the NVIC doesn't have
841
- * per-CPU interfaces so mark our non-existent CPU interface
842
- * as enabled by default, and with a priority mask which allows
843
- * all interrupts through.
844
+
845
+ s->vectors[ARMV7M_EXCP_NMI].enabled = 1;
846
+ s->vectors[ARMV7M_EXCP_HARD].enabled = 1;
847
+ /* MEM, BUS, and USAGE are enabled through
848
+ * the System Handler Control register
849
*/
850
- s->gic.cpu_ctlr[0] = GICC_CTLR_EN_GRP0;
851
- s->gic.priority_mask[0] = 0x100;
852
- /* The NVIC as a whole is always enabled. */
853
- s->gic.ctlr = 1;
854
+ s->vectors[ARMV7M_EXCP_SVC].enabled = 1;
855
+ s->vectors[ARMV7M_EXCP_DEBUG].enabled = 1;
856
+ s->vectors[ARMV7M_EXCP_PENDSV].enabled = 1;
857
+ s->vectors[ARMV7M_EXCP_SYSTICK].enabled = 1;
858
+
859
+ s->vectors[ARMV7M_EXCP_RESET].prio = -3;
860
+ s->vectors[ARMV7M_EXCP_NMI].prio = -2;
861
+ s->vectors[ARMV7M_EXCP_HARD].prio = -1;
862
+
863
+ /* Strictly speaking the reset handler should be enabled.
864
+ * However, we don't simulate soft resets through the NVIC,
865
+ * and the reset vector should never be pended.
866
+ * So we leave it disabled to catch logic errors.
867
+ */
868
+
869
+ s->exception_prio = NVIC_NOEXC_PRIO;
870
+ s->vectpending = 0;
871
+
872
systick_reset(s);
873
}
874
875
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
876
{
877
NVICState *s = NVIC(dev);
878
- NVICClass *nc = NVIC_GET_CLASS(s);
879
- Error *local_err = NULL;
880
881
s->cpu = ARM_CPU(qemu_get_cpu(0));
882
assert(s->cpu);
883
- /* The NVIC always has only one CPU */
884
- s->gic.num_cpu = 1;
885
- /* Tell the common code we're an NVIC */
886
- s->gic.revision = 0xffffffff;
887
- s->num_irq = s->gic.num_irq;
888
- nc->parent_realize(dev, &local_err);
889
- if (local_err) {
890
- error_propagate(errp, local_err);
891
+
892
+ if (s->num_irq > NVIC_MAX_IRQ) {
893
+ error_setg(errp, "num-irq %d exceeds NVIC maximum", s->num_irq);
894
return;
895
}
896
- gic_init_irqs_and_distributor(&s->gic);
897
- /* The NVIC and system controller register area looks like this:
898
- * 0..0xff : system control registers, including systick
899
- * 0x100..0xcff : GIC-like registers
900
- * 0xd00..0xfff : system control registers
901
- * We use overlaying to put the GIC like registers
902
- * over the top of the system control register region.
903
+
904
+ qdev_init_gpio_in(dev, set_irq_level, s->num_irq);
905
+
906
+ /* include space for internal exception vectors */
907
+ s->num_irq += NVIC_FIRST_IRQ;
908
+
909
+ /* The NVIC and System Control Space (SCS) starts at 0xe000e000
910
+ * and looks like this:
911
+ * 0x004 - ICTR
912
+ * 0x010 - 0x1c - systick
913
+ * 0x100..0x7ec - NVIC
914
+ * 0x7f0..0xcff - Reserved
915
+ * 0xd00..0xd3c - SCS registers
916
+ * 0xd40..0xeff - Reserved or Not implemented
917
+ * 0xf00 - STIR
918
+ *
919
+ * At the moment there is only one thing in the container region,
920
+ * but we leave it in place to allow us to pull systick out into
921
+ * its own device object later.
922
*/
923
memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
924
/* The system register region goes at the bottom of the priority
925
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
926
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
927
"nvic_sysregs", 0x1000);
928
memory_region_add_subregion(&s->container, 0, &s->sysregmem);
929
- /* Alias the GIC region so we can get only the section of it
930
- * we need, and layer it on top of the system register region.
931
- */
932
- memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s),
933
- "nvic-gic", &s->gic.iomem,
934
- 0x100, 0xc00);
935
- memory_region_add_subregion_overlap(&s->container, 0x100,
936
- &s->gic_iomem_alias, 1);
937
+
938
/* Map the whole thing into system memory at the location required
939
* by the v7M architecture.
940
*/
941
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
942
* any user-specified property setting, so just modify the
943
* value in the GICState struct.
944
*/
945
- GICState *s = ARM_GIC_COMMON(obj);
946
DeviceState *dev = DEVICE(obj);
947
NVICState *nvic = NVIC(obj);
948
- /* The ARM v7m may have anything from 0 to 496 external interrupt
949
- * IRQ lines. We default to 64. Other boards may differ and should
950
- * set the num-irq property appropriately.
951
- */
952
- s->num_irq = 64;
953
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
954
+
955
+ sysbus_init_irq(sbd, &nvic->excpout);
956
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
957
}
958
959
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
960
{
961
- NVICClass *nc = NVIC_CLASS(klass);
962
DeviceClass *dc = DEVICE_CLASS(klass);
963
964
- nc->parent_reset = dc->reset;
965
- nc->parent_realize = dc->realize;
966
dc->vmsd = &vmstate_nvic;
967
+ dc->props = props_nvic;
968
dc->reset = armv7m_nvic_reset;
969
dc->realize = armv7m_nvic_realize;
970
}
971
972
static const TypeInfo armv7m_nvic_info = {
973
.name = TYPE_NVIC,
974
- .parent = TYPE_ARM_GIC_COMMON,
975
+ .parent = TYPE_SYS_BUS_DEVICE,
976
.instance_init = armv7m_nvic_instance_init,
977
.instance_size = sizeof(NVICState),
978
.class_init = armv7m_nvic_class_init,
979
- .class_size = sizeof(NVICClass),
980
+ .class_size = sizeof(SysBusDeviceClass),
981
};
982
983
static void armv7m_nvic_register_types(void)
984
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
985
index XXXXXXX..XXXXXXX 100644
986
--- a/hw/intc/trace-events
987
+++ b/hw/intc/trace-events
988
@@ -XXX,XX +XXX,XX @@ gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size,
989
gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
990
gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor %x interrupt %d level changed to %d"
991
gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor %x pending SGI %d"
992
+
993
+# hw/intc/armv7m_nvic.c
994
+nvic_recompute_state(int vectpending, int exception_prio) "NVIC state recomputed: vectpending %d exception_prio %d"
995
+nvic_set_prio(int irq, uint8_t prio) "NVIC set irq %d priority %d"
996
+nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d"
997
+nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
998
+nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
999
+nvic_set_pending(int irq, int en, int prio) "NVIC set pending irq %d (enabled: %d priority %d)"
1000
+nvic_clear_pending(int irq, int en, int prio) "NVIC clear pending irq %d (enabled: %d priority %d)"
1001
+nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
1002
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
1003
+nvic_complete_irq(int irq) "NVIC complete IRQ %d"
1004
+nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
1005
+nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1006
+nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1007
--
202
--
1008
2.7.4
203
2.25.1
1009
1010
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The VECTCLRACTIVE and VECTRESET bits in the AIRCR are both
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
documented as UNPREDICTABLE if you write a 1 to them when
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
the processor is not halted in Debug state (ie stopped
5
Message-id: 20220506180242.216785-18-richard.henderson@linaro.org
6
and under the control of an external JTAG debugger).
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Since we don't implement Debug state or emulated JTAG
7
---
8
these bits are always UNPREDICTABLE for us. Instead of
8
docs/system/arm/emulation.rst | 1 +
9
logging them as unimplemented we can simply log writes
9
target/arm/cpu64.c | 1 +
10
as guest errors and ignore them.
10
target/arm/cpu_tcg.c | 1 +
11
3 files changed, 3 insertions(+)
11
12
12
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
13
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
13
[PMM: change extracted from another patch; commit message
14
constructed from scratch]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
---
19
hw/intc/armv7m_nvic.c | 8 ++++++--
20
1 file changed, 6 insertions(+), 2 deletions(-)
21
22
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/armv7m_nvic.c
15
--- a/docs/system/arm/emulation.rst
25
+++ b/hw/intc/armv7m_nvic.c
16
+++ b/docs/system/arm/emulation.rst
26
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
17
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
27
qemu_irq_pulse(s->sysresetreq);
18
- FEAT_PMULL (PMULL, PMULL2 instructions)
28
}
19
- FEAT_PMUv3p1 (PMU Extensions v3.1)
29
if (value & 2) {
20
- FEAT_PMUv3p4 (PMU Extensions v3.4)
30
- qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
21
+- FEAT_RAS (Reliability, availability, and serviceability)
31
+ qemu_log_mask(LOG_GUEST_ERROR,
22
- FEAT_RDM (Advanced SIMD rounding double multiply accumulate instructions)
32
+ "Setting VECTCLRACTIVE when not in DEBUG mode "
23
- FEAT_RNG (Random number generator)
33
+ "is UNPREDICTABLE\n");
24
- FEAT_SB (Speculation Barrier)
34
}
25
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
35
if (value & 1) {
26
index XXXXXXX..XXXXXXX 100644
36
- qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
27
--- a/target/arm/cpu64.c
37
+ qemu_log_mask(LOG_GUEST_ERROR,
28
+++ b/target/arm/cpu64.c
38
+ "Setting VECTRESET when not in DEBUG mode "
29
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
39
+ "is UNPREDICTABLE\n");
30
t = cpu->isar.id_aa64pfr0;
40
}
31
t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */
41
s->prigroup = extract32(value, 8, 3);
32
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */
42
nvic_irq_update(s);
33
+ t = FIELD_DP64(t, ID_AA64PFR0, RAS, 1); /* FEAT_RAS */
34
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
35
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
36
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
37
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/cpu_tcg.c
40
+++ b/target/arm/cpu_tcg.c
41
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
42
43
t = cpu->isar.id_pfr0;
44
t = FIELD_DP32(t, ID_PFR0, DIT, 1); /* FEAT_DIT */
45
+ t = FIELD_DP32(t, ID_PFR0, RAS, 1); /* FEAT_RAS */
46
cpu->isar.id_pfr0 = t;
47
48
t = cpu->isar.id_pfr2;
43
--
49
--
44
2.7.4
50
2.25.1
45
46
diff view generated by jsdifflib
1
Add a state field for the v7M PRIGROUP register and implent
1
From: Richard Henderson <richard.henderson@linaro.org>
2
reading and writing it. The current NVIC doesn't honour
3
the values written, but the new version will.
4
2
3
This feature is AArch64 only, and applies to physical SErrors,
4
which QEMU does not implement, thus the feature is a nop.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220506180242.216785-19-richard.henderson@linaro.org
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: Alex Bennée <alex.bennee@linaro.org>
8
---
10
---
9
hw/intc/armv7m_nvic.c | 14 ++++++++------
11
docs/system/arm/emulation.rst | 1 +
10
1 file changed, 8 insertions(+), 6 deletions(-)
12
target/arm/cpu64.c | 1 +
13
2 files changed, 2 insertions(+)
11
14
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
15
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
17
--- a/docs/system/arm/emulation.rst
15
+++ b/hw/intc/armv7m_nvic.c
18
+++ b/docs/system/arm/emulation.rst
16
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
17
typedef struct NVICState {
20
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
18
GICState gic;
21
- FEAT_HPDS (Hierarchical permission disables)
19
ARMCPU *cpu;
22
- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
20
+
23
+- FEAT_IESB (Implicit error synchronization event)
21
+ uint32_t prigroup;
24
- FEAT_JSCVT (JavaScript conversion instructions)
22
+
25
- FEAT_LOR (Limited ordering regions)
23
struct {
26
- FEAT_LPA (Large Physical Address space)
24
uint32_t control;
27
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
25
uint32_t reload;
28
index XXXXXXX..XXXXXXX 100644
26
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
29
--- a/target/arm/cpu64.c
27
case 0xd08: /* Vector Table Offset. */
30
+++ b/target/arm/cpu64.c
28
return cpu->env.v7m.vecbase;
31
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
29
case 0xd0c: /* Application Interrupt/Reset Control. */
32
t = cpu->isar.id_aa64mmfr2;
30
- return 0xfa050000;
33
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* FEAT_TTCNP */
31
+ return 0xfa050000 | (s->prigroup << 8);
34
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); /* FEAT_UAO */
32
case 0xd10: /* System Control. */
35
+ t = FIELD_DP64(t, ID_AA64MMFR2, IESB, 1); /* FEAT_IESB */
33
/* TODO: Implement SLEEPONEXIT. */
36
t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */
34
return 0;
37
t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* FEAT_TTST */
35
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
38
t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
36
if (value & 1) {
37
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
38
}
39
- if (value & 0x700) {
40
- qemu_log_mask(LOG_UNIMP, "PRIGROUP unimplemented\n");
41
- }
42
+ s->prigroup = extract32(value, 8, 3);
43
}
44
break;
45
case 0xd10: /* System Control. */
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
47
48
static const VMStateDescription vmstate_nvic = {
49
.name = "armv7m_nvic",
50
- .version_id = 1,
51
- .minimum_version_id = 1,
52
+ .version_id = 2,
53
+ .minimum_version_id = 2,
54
.fields = (VMStateField[]) {
55
VMSTATE_UINT32(systick.control, NVICState),
56
VMSTATE_UINT32(systick.reload, NVICState),
57
VMSTATE_INT64(systick.tick, NVICState),
58
VMSTATE_TIMER_PTR(systick.timer, NVICState),
59
+ VMSTATE_UINT32(prigroup, NVICState),
60
VMSTATE_END_OF_LIST()
61
}
62
};
63
--
39
--
64
2.7.4
40
2.25.1
65
66
diff view generated by jsdifflib
1
In get_page_addr_code(), if the guest PC doesn't correspond to RAM
1
From: Richard Henderson <richard.henderson@linaro.org>
2
then we currently run the CPU's do_unassigned_access() hook if it has
3
one, and otherwise we give up and exit QEMU with a more-or-less
4
useful message. This code assumes that the do_unassigned_access hook
5
will never return, because if it does then we'll plough on attempting
6
to use a non-RAM TLB entry to get a RAM address and will abort() in
7
qemu_ram_addr_from_host_nofail(). Unfortunately some CPU
8
implementations of this hook do return: Microblaze, SPARC and the ARM
9
v7M.
10
2
11
Change the code to call report_bad_exec() if the hook returns, as
3
This extension concerns branch speculation, which TCG does
12
well as if it didn't have one. This means we can tidy it up to use
4
not implement. Thus we can trivially enable this feature.
13
the cpu_unassigned_access() function which wraps the "get the CPU
14
class and call the hook if it has one" work, since we aren't trying
15
to distinguish "no hook" from "hook existed and returned" any more.
16
5
17
This brings the handling of this hook into line with the handling
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
used for data accesses, where "hook returned" is treated the
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
19
same as "no hook existed" and gets you the default behaviour.
8
Message-id: 20220506180242.216785-20-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
docs/system/arm/emulation.rst | 1 +
12
target/arm/cpu64.c | 1 +
13
target/arm/cpu_tcg.c | 1 +
14
3 files changed, 3 insertions(+)
20
15
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
22
Reviewed-by: Richard Henderson <rth@twiddle.net>
23
---
24
cputlb.c | 15 +++++++--------
25
1 file changed, 7 insertions(+), 8 deletions(-)
26
27
diff --git a/cputlb.c b/cputlb.c
28
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
29
--- a/cputlb.c
18
--- a/docs/system/arm/emulation.rst
30
+++ b/cputlb.c
19
+++ b/docs/system/arm/emulation.rst
31
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
20
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
32
pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
21
- FEAT_BBM at level 2 (Translation table break-before-make levels)
33
mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
22
- FEAT_BF16 (AArch64 BFloat16 instructions)
34
if (memory_region_is_unassigned(mr)) {
23
- FEAT_BTI (Branch Target Identification)
35
- CPUClass *cc = CPU_GET_CLASS(cpu);
24
+- FEAT_CSV2 (Cache speculation variant 2)
36
-
25
- FEAT_DIT (Data Independent Timing instructions)
37
- if (cc->do_unassigned_access) {
26
- FEAT_DPB (DC CVAP instruction)
38
- cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
27
- FEAT_Debugv8p2 (Debug changes for v8.2)
39
- } else {
28
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
40
- report_bad_exec(cpu, addr);
29
index XXXXXXX..XXXXXXX 100644
41
- exit(1);
30
--- a/target/arm/cpu64.c
42
- }
31
+++ b/target/arm/cpu64.c
43
+ cpu_unassigned_access(cpu, addr, false, true, 0, 4);
32
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
44
+ /* The CPU's unassigned access hook might have longjumped out
33
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
45
+ * with an exception. If it didn't (or there was no hook) then
34
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
46
+ * we can't proceed further.
35
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
47
+ */
36
+ t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 1); /* FEAT_CSV2 */
48
+ report_bad_exec(cpu, addr);
37
cpu->isar.id_aa64pfr0 = t;
49
+ exit(1);
38
50
}
39
t = cpu->isar.id_aa64pfr1;
51
p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
40
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
52
return qemu_ram_addr_from_host_nofail(p);
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/cpu_tcg.c
43
+++ b/target/arm/cpu_tcg.c
44
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
45
cpu->isar.id_mmfr4 = t;
46
47
t = cpu->isar.id_pfr0;
48
+ t = FIELD_DP32(t, ID_PFR0, CSV2, 2); /* FEAT_CVS2 */
49
t = FIELD_DP32(t, ID_PFR0, DIT, 1); /* FEAT_DIT */
50
t = FIELD_DP32(t, ID_PFR0, RAS, 1); /* FEAT_RAS */
51
cpu->isar.id_pfr0 = t;
53
--
52
--
54
2.7.4
53
2.25.1
55
56
diff view generated by jsdifflib
1
The M profile condition for when we can take a pending exception or
1
From: Richard Henderson <richard.henderson@linaro.org>
2
interrupt is not the same as that for A/R profile. The code
3
originally copied from the A/R profile version of the
4
cpu_exec_interrupt function only worked by chance for the
5
very simple case of exceptions being masked by PRIMASK.
6
Replace it with a call to a function in the NVIC code that
7
correctly compares the priority of the pending exception
8
against the current execution priority of the CPU.
9
2
10
[Michael Davidsaver's patchset had a patch to do something
3
There is no branch prediction in TCG, therefore there is no
11
similar but the implementation ended up being a rewrite.]
4
need to actually include the context number into the predictor.
5
Therefore all we need to do is add the state for SCXTNUM_ELx.
12
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220506180242.216785-21-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
---
11
---
16
target/arm/cpu.h | 8 ++++++++
12
docs/system/arm/emulation.rst | 3 ++
17
hw/intc/armv7m_nvic.c | 7 +++++++
13
target/arm/cpu.h | 16 +++++++++
18
target/arm/cpu.c | 16 ++++++++--------
14
target/arm/cpu.c | 5 +++
19
3 files changed, 23 insertions(+), 8 deletions(-)
15
target/arm/cpu64.c | 3 +-
16
target/arm/helper.c | 61 ++++++++++++++++++++++++++++++++++-
17
5 files changed, 86 insertions(+), 2 deletions(-)
20
18
19
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
20
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/arm/emulation.rst
22
+++ b/docs/system/arm/emulation.rst
23
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
24
- FEAT_BF16 (AArch64 BFloat16 instructions)
25
- FEAT_BTI (Branch Target Identification)
26
- FEAT_CSV2 (Cache speculation variant 2)
27
+- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
28
+- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
29
+- FEAT_CSV2_2 (Cache speculation variant 2, version 2)
30
- FEAT_DIT (Data Independent Timing instructions)
31
- FEAT_DPB (DC CVAP instruction)
32
- FEAT_Debugv8p2 (Debug changes for v8.2)
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
33
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
35
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
36
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
37
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
26
uint32_t cur_el, bool secure);
38
ARMPACKey apdb;
27
39
ARMPACKey apga;
28
/* Interface between CPU and Interrupt controller. */
40
} keys;
29
+#ifndef CONFIG_USER_ONLY
41
+
30
+bool armv7m_nvic_can_take_pending_exception(void *opaque);
42
+ uint64_t scxtnum_el[4];
31
+#else
43
#endif
32
+static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
44
45
#if defined(CONFIG_USER_ONLY)
46
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
47
#define SCTLR_WXN (1U << 19)
48
#define SCTLR_ST (1U << 20) /* up to ??, RAZ in v6 */
49
#define SCTLR_UWXN (1U << 20) /* v7 onward, AArch32 only */
50
+#define SCTLR_TSCXT (1U << 20) /* FEAT_CSV2_1p2, AArch64 only */
51
#define SCTLR_FI (1U << 21) /* up to v7, v8 RES0 */
52
#define SCTLR_IESB (1U << 21) /* v8.2-IESB, AArch64 only */
53
#define SCTLR_U (1U << 22) /* up to v6, RAO in v7 */
54
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
55
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
56
}
57
58
+static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id)
33
+{
59
+{
34
+ return true;
60
+ int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2);
61
+ if (key >= 2) {
62
+ return true; /* FEAT_CSV2_2 */
63
+ }
64
+ if (key == 1) {
65
+ key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC);
66
+ return key >= 2; /* FEAT_CSV2_1p2 */
67
+ }
68
+ return false;
35
+}
69
+}
36
+#endif
70
+
37
void armv7m_nvic_set_pending(void *opaque, int irq);
71
static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
38
int armv7m_nvic_acknowledge_irq(void *opaque);
39
void armv7m_nvic_complete_irq(void *opaque, int irq);
40
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/armv7m_nvic.c
43
+++ b/hw/intc/armv7m_nvic.c
44
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
45
return MIN(running, s->exception_prio);
46
}
47
48
+bool armv7m_nvic_can_take_pending_exception(void *opaque)
49
+{
50
+ NVICState *s = opaque;
51
+
52
+ return nvic_exec_prio(s) > nvic_pending_prio(s);
53
+}
54
+
55
/* caller must call nvic_irq_update() after this */
56
static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
57
{
72
{
73
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
58
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
74
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/cpu.c
76
--- a/target/arm/cpu.c
61
+++ b/target/arm/cpu.c
77
+++ b/target/arm/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
78
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
63
CPUARMState *env = &cpu->env;
79
*/
64
bool ret = false;
80
env->cp15.gcr_el1 = 0x1ffff;
65
81
}
66
-
82
+ /*
67
- if (interrupt_request & CPU_INTERRUPT_FIQ
83
+ * Disable access to SCXTNUM_EL0 from CSV2_1p2.
68
- && !(env->daif & PSTATE_F)) {
84
+ * This is not yet exposed from the Linux kernel in any way.
69
- cs->exception_index = EXCP_FIQ;
85
+ */
70
- cc->do_interrupt(cs);
86
+ env->cp15.sctlr_el[1] |= SCTLR_TSCXT;
71
- ret = true;
87
#else
72
- }
88
/* Reset into the highest available EL */
73
/* ARMv7-M interrupt return works by loading a magic value
89
if (arm_feature(env, ARM_FEATURE_EL3)) {
74
* into the PC. On real hardware the load causes the
90
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
75
* return to occur. The qemu implementation performs the
91
index XXXXXXX..XXXXXXX 100644
76
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
92
--- a/target/arm/cpu64.c
77
* the stack if an interrupt occurred at the wrong time.
93
+++ b/target/arm/cpu64.c
78
* We avoid this by disabling interrupts when
94
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
79
* pc contains a magic address.
95
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
80
+ *
96
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
81
+ * ARMv7-M interrupt masking works differently than -A or -R.
97
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
82
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
98
- t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 1); /* FEAT_CSV2 */
83
+ * masking FIQ and IRQ interrupts, an exception is taken only
99
+ t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */
84
+ * if it is higher priority than the current execution priority
100
cpu->isar.id_aa64pfr0 = t;
85
+ * (which depends on state like BASEPRI, FAULTMASK and the
101
86
+ * currently active exception).
102
t = cpu->isar.id_aa64pfr1;
103
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
104
* we do for EL2 with the virtualization=on property.
87
*/
105
*/
88
if (interrupt_request & CPU_INTERRUPT_HARD
106
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
89
- && !(env->daif & PSTATE_I)
107
+ t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
90
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))
108
cpu->isar.id_aa64pfr1 = t;
91
&& (env->regs[15] < 0xfffffff0)) {
109
92
cs->exception_index = EXCP_IRQ;
110
t = cpu->isar.id_aa64mmfr0;
93
cc->do_interrupt(cs);
111
diff --git a/target/arm/helper.c b/target/arm/helper.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/helper.c
114
+++ b/target/arm/helper.c
115
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
116
if (cpu_isar_feature(aa64_mte, cpu)) {
117
valid_mask |= SCR_ATA;
118
}
119
+ if (cpu_isar_feature(aa64_scxtnum, cpu)) {
120
+ valid_mask |= SCR_ENSCXT;
121
+ }
122
} else {
123
valid_mask &= ~(SCR_RW | SCR_ST);
124
if (cpu_isar_feature(aa32_ras, cpu)) {
125
@@ -XXX,XX +XXX,XX @@ static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
126
if (cpu_isar_feature(aa64_mte, cpu)) {
127
valid_mask |= HCR_ATA | HCR_DCT | HCR_TID5;
128
}
129
+ if (cpu_isar_feature(aa64_scxtnum, cpu)) {
130
+ valid_mask |= HCR_ENSCXT;
131
+ }
132
}
133
134
/* Clear RES0 bits. */
135
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
136
{ K(3, 0, 5, 6, 0), K(3, 4, 5, 6, 0), K(3, 5, 5, 6, 0),
137
"TFSR_EL1", "TFSR_EL2", "TFSR_EL12", isar_feature_aa64_mte },
138
139
+ { K(3, 0, 13, 0, 7), K(3, 4, 13, 0, 7), K(3, 5, 13, 0, 7),
140
+ "SCXTNUM_EL1", "SCXTNUM_EL2", "SCXTNUM_EL12",
141
+ isar_feature_aa64_scxtnum },
142
+
143
/* TODO: ARMv8.2-SPE -- PMSCR_EL2 */
144
/* TODO: ARMv8.4-Trace -- TRFCR_EL2 */
145
};
146
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
147
},
148
};
149
150
-#endif
151
+static CPAccessResult access_scxtnum(CPUARMState *env, const ARMCPRegInfo *ri,
152
+ bool isread)
153
+{
154
+ uint64_t hcr = arm_hcr_el2_eff(env);
155
+ int el = arm_current_el(env);
156
+
157
+ if (el == 0 && !((hcr & HCR_E2H) && (hcr & HCR_TGE))) {
158
+ if (env->cp15.sctlr_el[1] & SCTLR_TSCXT) {
159
+ if (hcr & HCR_TGE) {
160
+ return CP_ACCESS_TRAP_EL2;
161
+ }
162
+ return CP_ACCESS_TRAP;
163
+ }
164
+ } else if (el < 2 && (env->cp15.sctlr_el[2] & SCTLR_TSCXT)) {
165
+ return CP_ACCESS_TRAP_EL2;
166
+ }
167
+ if (el < 2 && arm_is_el2_enabled(env) && !(hcr & HCR_ENSCXT)) {
168
+ return CP_ACCESS_TRAP_EL2;
169
+ }
170
+ if (el < 3
171
+ && arm_feature(env, ARM_FEATURE_EL3)
172
+ && !(env->cp15.scr_el3 & SCR_ENSCXT)) {
173
+ return CP_ACCESS_TRAP_EL3;
174
+ }
175
+ return CP_ACCESS_OK;
176
+}
177
+
178
+static const ARMCPRegInfo scxtnum_reginfo[] = {
179
+ { .name = "SCXTNUM_EL0", .state = ARM_CP_STATE_AA64,
180
+ .opc0 = 3, .opc1 = 3, .crn = 13, .crm = 0, .opc2 = 7,
181
+ .access = PL0_RW, .accessfn = access_scxtnum,
182
+ .fieldoffset = offsetof(CPUARMState, scxtnum_el[0]) },
183
+ { .name = "SCXTNUM_EL1", .state = ARM_CP_STATE_AA64,
184
+ .opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 7,
185
+ .access = PL1_RW, .accessfn = access_scxtnum,
186
+ .fieldoffset = offsetof(CPUARMState, scxtnum_el[1]) },
187
+ { .name = "SCXTNUM_EL2", .state = ARM_CP_STATE_AA64,
188
+ .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 7,
189
+ .access = PL2_RW, .accessfn = access_scxtnum,
190
+ .fieldoffset = offsetof(CPUARMState, scxtnum_el[2]) },
191
+ { .name = "SCXTNUM_EL3", .state = ARM_CP_STATE_AA64,
192
+ .opc0 = 3, .opc1 = 6, .crn = 13, .crm = 0, .opc2 = 7,
193
+ .access = PL3_RW,
194
+ .fieldoffset = offsetof(CPUARMState, scxtnum_el[3]) },
195
+};
196
+#endif /* TARGET_AARCH64 */
197
198
static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
199
bool isread)
200
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
201
define_arm_cp_regs(cpu, mte_tco_ro_reginfo);
202
define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo);
203
}
204
+
205
+ if (cpu_isar_feature(aa64_scxtnum, cpu)) {
206
+ define_arm_cp_regs(cpu, scxtnum_reginfo);
207
+ }
208
#endif
209
210
if (cpu_isar_feature(any_predinv, cpu)) {
94
--
211
--
95
2.7.4
212
2.25.1
96
97
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In sdhci_write invoke multi block transfer if it is enabled
3
This extension concerns cache speculation, which TCG does
4
in the transfer mode register 's->trnmod'.
4
not implement. Thus we can trivially enable this feature.
5
5
6
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20170214185225.7994-4-ppandit@redhat.com
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
Message-id: 20220506180242.216785-22-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
hw/sd/sdhci.c | 6 +++++-
11
docs/system/arm/emulation.rst | 1 +
12
1 file changed, 5 insertions(+), 1 deletion(-)
12
target/arm/cpu64.c | 1 +
13
target/arm/cpu_tcg.c | 1 +
14
3 files changed, 3 insertions(+)
13
15
14
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/sd/sdhci.c
18
--- a/docs/system/arm/emulation.rst
17
+++ b/hw/sd/sdhci.c
19
+++ b/docs/system/arm/emulation.rst
18
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
20
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
19
/* Writing to last byte of sdmasysad might trigger transfer */
21
- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
20
if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
22
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
21
s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
23
- FEAT_CSV2_2 (Cache speculation variant 2, version 2)
22
- sdhci_sdma_transfer_multi_blocks(s);
24
+- FEAT_CSV3 (Cache speculation variant 3)
23
+ if (s->trnmod & SDHC_TRNS_MULTI) {
25
- FEAT_DIT (Data Independent Timing instructions)
24
+ sdhci_sdma_transfer_multi_blocks(s);
26
- FEAT_DPB (DC CVAP instruction)
25
+ } else {
27
- FEAT_Debugv8p2 (Debug changes for v8.2)
26
+ sdhci_sdma_transfer_single_block(s);
28
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
27
+ }
29
index XXXXXXX..XXXXXXX 100644
28
}
30
--- a/target/arm/cpu64.c
29
break;
31
+++ b/target/arm/cpu64.c
30
case SDHC_BLKSIZE:
32
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
33
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
34
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
35
t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */
36
+ t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1); /* FEAT_CSV3 */
37
cpu->isar.id_aa64pfr0 = t;
38
39
t = cpu->isar.id_aa64pfr1;
40
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/cpu_tcg.c
43
+++ b/target/arm/cpu_tcg.c
44
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
45
cpu->isar.id_pfr0 = t;
46
47
t = cpu->isar.id_pfr2;
48
+ t = FIELD_DP32(t, ID_PFR2, CSV3, 1); /* FEAT_CSV3 */
49
t = FIELD_DP32(t, ID_PFR2, SSBS, 1); /* FEAT_SSBS */
50
cpu->isar.id_pfr2 = t;
51
31
--
52
--
32
2.7.4
53
2.25.1
33
34
diff view generated by jsdifflib
1
From: Nick Reilly <nreilly@blackberry.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The aarch64 crypto instructions for AES and SHA are missing the
3
This extension concerns not merging memory access, which TCG does
4
check for if the FPU is enabled.
4
not implement. Thus we can trivially enable this feature.
5
Add a comment to handle_hint for the DGH instruction, but no code.
5
6
6
Signed-off-by: Nick Reilly <nreilly@blackberry.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220506180242.216785-23-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/translate-a64.c | 12 ++++++++++++
12
docs/system/arm/emulation.rst | 1 +
11
1 file changed, 12 insertions(+)
13
target/arm/cpu64.c | 1 +
14
target/arm/translate-a64.c | 1 +
15
3 files changed, 3 insertions(+)
12
16
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/arm/emulation.rst
20
+++ b/docs/system/arm/emulation.rst
21
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
22
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
23
- FEAT_CSV2_2 (Cache speculation variant 2, version 2)
24
- FEAT_CSV3 (Cache speculation variant 3)
25
+- FEAT_DGH (Data gathering hint)
26
- FEAT_DIT (Data Independent Timing instructions)
27
- FEAT_DPB (DC CVAP instruction)
28
- FEAT_Debugv8p2 (Debug changes for v8.2)
29
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu64.c
32
+++ b/target/arm/cpu64.c
33
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
34
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1); /* FEAT_SB */
35
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1); /* FEAT_SPECRES */
36
t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1); /* FEAT_BF16 */
37
+ t = FIELD_DP64(t, ID_AA64ISAR1, DGH, 1); /* FEAT_DGH */
38
t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); /* FEAT_I8MM */
39
cpu->isar.id_aa64isar1 = t;
40
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
41
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
43
--- a/target/arm/translate-a64.c
16
+++ b/target/arm/translate-a64.c
44
+++ b/target/arm/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
45
@@ -XXX,XX +XXX,XX @@ static void handle_hint(DisasContext *s, uint32_t insn,
18
return;
46
break;
19
}
47
case 0b00100: /* SEV */
20
48
case 0b00101: /* SEVL */
21
+ if (!fp_access_check(s)) {
49
+ case 0b00110: /* DGH */
22
+ return;
50
/* we treat all as NOP at least for now */
23
+ }
51
break;
24
+
52
case 0b00111: /* XPACLRI */
25
/* Note that we convert the Vx register indexes into the
26
* index within the vfp.regs[] array, so we can share the
27
* helper with the AArch32 instructions.
28
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
29
return;
30
}
31
32
+ if (!fp_access_check(s)) {
33
+ return;
34
+ }
35
+
36
tcg_rd_regno = tcg_const_i32(rd << 1);
37
tcg_rn_regno = tcg_const_i32(rn << 1);
38
tcg_rm_regno = tcg_const_i32(rm << 1);
39
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
40
return;
41
}
42
43
+ if (!fp_access_check(s)) {
44
+ return;
45
+ }
46
+
47
tcg_rd_regno = tcg_const_i32(rd << 1);
48
tcg_rn_regno = tcg_const_i32(rn << 1);
49
50
--
53
--
51
2.7.4
54
2.25.1
52
53
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Provide a new function sdbus_reparent_card() in sd core for reparenting
3
Enable the a76 for virt and sbsa board use.
4
a card from a SDBus to another one.
5
4
6
This function is required by the raspi platform, where the two SD
7
controllers can be dynamically switched.
8
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
10
Message-id: 20170224164021.9066-3-clement.deschamps@antfield.fr
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
[PMM: added a doc comment to the header file]
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220506180242.216785-24-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
9
---
15
include/hw/sd/sd.h | 11 +++++++++++
10
docs/system/arm/virt.rst | 1 +
16
hw/sd/core.c | 30 ++++++++++++++++++++++++++++++
11
hw/arm/sbsa-ref.c | 1 +
17
2 files changed, 41 insertions(+)
12
hw/arm/virt.c | 1 +
13
target/arm/cpu64.c | 66 ++++++++++++++++++++++++++++++++++++++++
14
4 files changed, 69 insertions(+)
18
15
19
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
16
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/sd/sd.h
18
--- a/docs/system/arm/virt.rst
22
+++ b/include/hw/sd/sd.h
19
+++ b/docs/system/arm/virt.rst
23
@@ -XXX,XX +XXX,XX @@ uint8_t sdbus_read_data(SDBus *sd);
20
@@ -XXX,XX +XXX,XX @@ Supported guest CPU types:
24
bool sdbus_data_ready(SDBus *sd);
21
- ``cortex-a53`` (64-bit)
25
bool sdbus_get_inserted(SDBus *sd);
22
- ``cortex-a57`` (64-bit)
26
bool sdbus_get_readonly(SDBus *sd);
23
- ``cortex-a72`` (64-bit)
27
+/**
24
+- ``cortex-a76`` (64-bit)
28
+ * sdbus_reparent_card: Reparent an SD card from one controller to another
25
- ``a64fx`` (64-bit)
29
+ * @from: controller bus to remove card from
26
- ``host`` (with KVM only)
30
+ * @to: controller bus to move card to
27
- ``max`` (same as ``host`` for KVM; best possible emulation with TCG)
31
+ *
28
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
32
+ * Reparent an SD card, effectively unplugging it from one controller
33
+ * and inserting it into another. This is useful for SoCs like the
34
+ * bcm2835 which have two SD controllers and connect a single SD card
35
+ * to them, selected by the guest reprogramming GPIO line routing.
36
+ */
37
+void sdbus_reparent_card(SDBus *from, SDBus *to);
38
39
/* Functions to be used by SD devices to report back to qdevified controllers */
40
void sdbus_set_inserted(SDBus *sd, bool inserted);
41
diff --git a/hw/sd/core.c b/hw/sd/core.c
42
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/sd/core.c
30
--- a/hw/arm/sbsa-ref.c
44
+++ b/hw/sd/core.c
31
+++ b/hw/arm/sbsa-ref.c
45
@@ -XXX,XX +XXX,XX @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly)
32
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
46
}
33
static const char * const valid_cpus[] = {
34
ARM_CPU_TYPE_NAME("cortex-a57"),
35
ARM_CPU_TYPE_NAME("cortex-a72"),
36
+ ARM_CPU_TYPE_NAME("cortex-a76"),
37
ARM_CPU_TYPE_NAME("max"),
38
};
39
40
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/virt.c
43
+++ b/hw/arm/virt.c
44
@@ -XXX,XX +XXX,XX @@ static const char *valid_cpus[] = {
45
ARM_CPU_TYPE_NAME("cortex-a53"),
46
ARM_CPU_TYPE_NAME("cortex-a57"),
47
ARM_CPU_TYPE_NAME("cortex-a72"),
48
+ ARM_CPU_TYPE_NAME("cortex-a76"),
49
ARM_CPU_TYPE_NAME("a64fx"),
50
ARM_CPU_TYPE_NAME("host"),
51
ARM_CPU_TYPE_NAME("max"),
52
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/cpu64.c
55
+++ b/target/arm/cpu64.c
56
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
57
define_cortex_a72_a57_a53_cp_reginfo(cpu);
47
}
58
}
48
59
49
+void sdbus_reparent_card(SDBus *from, SDBus *to)
60
+static void aarch64_a76_initfn(Object *obj)
50
+{
61
+{
51
+ BusChild *kid = QTAILQ_FIRST(&from->qbus.children);
62
+ ARMCPU *cpu = ARM_CPU(obj);
52
+ SDState *card;
53
+ SDCardClass *sc;
54
+ bool readonly;
55
+
63
+
56
+ /* We directly reparent the card object rather than implementing this
64
+ cpu->dtb_compatible = "arm,cortex-a76";
57
+ * as a hotpluggable connection because we don't want to expose SD cards
65
+ set_feature(&cpu->env, ARM_FEATURE_V8);
58
+ * to users as being hotpluggable, and we can get away with it in this
66
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
59
+ * limited use case. This could perhaps be implemented more cleanly in
67
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
60
+ * future by adding support to the hotplug infrastructure for "device
68
+ set_feature(&cpu->env, ARM_FEATURE_AARCH64);
61
+ * can be hotplugged only via code, not by user".
69
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
62
+ */
70
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
71
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
72
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
63
+
73
+
64
+ if (!kid) {
74
+ /* Ordered by B2.4 AArch64 registers by functional group */
65
+ return;
75
+ cpu->clidr = 0x82000023;
66
+ }
76
+ cpu->ctr = 0x8444C004;
77
+ cpu->dcz_blocksize = 4;
78
+ cpu->isar.id_aa64dfr0 = 0x0000000010305408ull;
79
+ cpu->isar.id_aa64isar0 = 0x0000100010211120ull;
80
+ cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
81
+ cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
82
+ cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
83
+ cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
84
+ cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */
85
+ cpu->isar.id_aa64pfr1 = 0x0000000000000010ull;
86
+ cpu->id_afr0 = 0x00000000;
87
+ cpu->isar.id_dfr0 = 0x04010088;
88
+ cpu->isar.id_isar0 = 0x02101110;
89
+ cpu->isar.id_isar1 = 0x13112111;
90
+ cpu->isar.id_isar2 = 0x21232042;
91
+ cpu->isar.id_isar3 = 0x01112131;
92
+ cpu->isar.id_isar4 = 0x00010142;
93
+ cpu->isar.id_isar5 = 0x01011121;
94
+ cpu->isar.id_isar6 = 0x00000010;
95
+ cpu->isar.id_mmfr0 = 0x10201105;
96
+ cpu->isar.id_mmfr1 = 0x40000000;
97
+ cpu->isar.id_mmfr2 = 0x01260000;
98
+ cpu->isar.id_mmfr3 = 0x02122211;
99
+ cpu->isar.id_mmfr4 = 0x00021110;
100
+ cpu->isar.id_pfr0 = 0x10010131;
101
+ cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */
102
+ cpu->isar.id_pfr2 = 0x00000011;
103
+ cpu->midr = 0x414fd0b1; /* r4p1 */
104
+ cpu->revidr = 0;
67
+
105
+
68
+ card = SD_CARD(kid->child);
106
+ /* From B2.18 CCSIDR_EL1 */
69
+ sc = SD_CARD_GET_CLASS(card);
107
+ cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */
70
+ readonly = sc->get_readonly(card);
108
+ cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */
109
+ cpu->ccsidr[2] = 0x707fe03a; /* 512KB L2 cache */
71
+
110
+
72
+ sdbus_set_inserted(from, false);
111
+ /* From B2.93 SCTLR_EL3 */
73
+ object_unparent(OBJECT(kid));
112
+ cpu->reset_sctlr = 0x30c50838;
74
+ qdev_set_parent_bus(DEVICE(card), &to->qbus);
113
+
75
+ sdbus_set_inserted(to, true);
114
+ /* From B4.23 ICH_VTR_EL2 */
76
+ sdbus_set_readonly(to, readonly);
115
+ cpu->gic_num_lrs = 4;
116
+ cpu->gic_vpribits = 5;
117
+ cpu->gic_vprebits = 5;
118
+
119
+ /* From B5.1 AdvSIMD AArch64 register summary */
120
+ cpu->isar.mvfr0 = 0x10110222;
121
+ cpu->isar.mvfr1 = 0x13211111;
122
+ cpu->isar.mvfr2 = 0x00000043;
77
+}
123
+}
78
+
124
+
79
static const TypeInfo sd_bus_info = {
125
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
80
.name = TYPE_SD_BUS,
126
{
81
.parent = TYPE_BUS,
127
/*
128
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo aarch64_cpus[] = {
129
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
130
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
131
{ .name = "cortex-a72", .initfn = aarch64_a72_initfn },
132
+ { .name = "cortex-a76", .initfn = aarch64_a76_initfn },
133
{ .name = "a64fx", .initfn = aarch64_a64fx_initfn },
134
{ .name = "max", .initfn = aarch64_max_initfn },
135
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
82
--
136
--
83
2.7.4
137
2.25.1
84
85
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In 2.9 ITS will block save/restore and migration use cases. As such,
3
Enable the n1 for virt and sbsa board use.
4
let's introduce a user option that allows to turn its instantiation
5
off, along with GICv3. With the "its" option turned false, migration
6
will be possible, obviously at the expense of MSI support (with GICv3).
7
4
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 1487681108-14452-1-git-send-email-eric.auger@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220506180242.216785-25-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
9
---
13
include/hw/arm/virt.h | 1 +
10
docs/system/arm/virt.rst | 1 +
14
hw/arm/virt.c | 31 +++++++++++++++++++++++++++++--
11
hw/arm/sbsa-ref.c | 1 +
15
2 files changed, 30 insertions(+), 2 deletions(-)
12
hw/arm/virt.c | 1 +
13
target/arm/cpu64.c | 66 ++++++++++++++++++++++++++++++++++++++++
14
4 files changed, 69 insertions(+)
16
15
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
16
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
18
--- a/docs/system/arm/virt.rst
20
+++ b/include/hw/arm/virt.h
19
+++ b/docs/system/arm/virt.rst
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
20
@@ -XXX,XX +XXX,XX @@ Supported guest CPU types:
22
FWCfgState *fw_cfg;
21
- ``cortex-a76`` (64-bit)
23
bool secure;
22
- ``a64fx`` (64-bit)
24
bool highmem;
23
- ``host`` (with KVM only)
25
+ bool its;
24
+- ``neoverse-n1`` (64-bit)
26
bool virt;
25
- ``max`` (same as ``host`` for KVM; best possible emulation with TCG)
27
int32_t gic_version;
26
28
struct arm_boot_info bootinfo;
27
Note that the default is ``cortex-a15``, so for an AArch64 guest you must
28
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/sbsa-ref.c
31
+++ b/hw/arm/sbsa-ref.c
32
@@ -XXX,XX +XXX,XX @@ static const char * const valid_cpus[] = {
33
ARM_CPU_TYPE_NAME("cortex-a57"),
34
ARM_CPU_TYPE_NAME("cortex-a72"),
35
ARM_CPU_TYPE_NAME("cortex-a76"),
36
+ ARM_CPU_TYPE_NAME("neoverse-n1"),
37
ARM_CPU_TYPE_NAME("max"),
38
};
39
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
40
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
30
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/virt.c
42
--- a/hw/arm/virt.c
32
+++ b/hw/arm/virt.c
43
+++ b/hw/arm/virt.c
33
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
44
@@ -XXX,XX +XXX,XX @@ static const char *valid_cpus[] = {
34
static void create_gic(VirtMachineState *vms, qemu_irq *pic)
45
ARM_CPU_TYPE_NAME("cortex-a72"),
35
{
46
ARM_CPU_TYPE_NAME("cortex-a76"),
36
/* We create a standalone GIC */
47
ARM_CPU_TYPE_NAME("a64fx"),
37
- VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
48
+ ARM_CPU_TYPE_NAME("neoverse-n1"),
38
DeviceState *gicdev;
49
ARM_CPU_TYPE_NAME("host"),
39
SysBusDevice *gicbusdev;
50
ARM_CPU_TYPE_NAME("max"),
40
const char *gictype;
51
};
41
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
52
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
42
53
index XXXXXXX..XXXXXXX 100644
43
fdt_add_gic_node(vms);
54
--- a/target/arm/cpu64.c
44
55
+++ b/target/arm/cpu64.c
45
- if (type == 3 && !vmc->no_its) {
56
@@ -XXX,XX +XXX,XX @@ static void aarch64_a76_initfn(Object *obj)
46
+ if (type == 3 && vms->its) {
57
cpu->isar.mvfr2 = 0x00000043;
47
create_its(vms, gicdev);
48
} else if (type == 2) {
49
create_v2m(vms, pic);
50
@@ -XXX,XX +XXX,XX @@ static void virt_set_highmem(Object *obj, bool value, Error **errp)
51
vms->highmem = value;
52
}
58
}
53
59
54
+static bool virt_get_its(Object *obj, Error **errp)
60
+static void aarch64_neoverse_n1_initfn(Object *obj)
55
+{
61
+{
56
+ VirtMachineState *vms = VIRT_MACHINE(obj);
62
+ ARMCPU *cpu = ARM_CPU(obj);
57
+
63
+
58
+ return vms->its;
64
+ cpu->dtb_compatible = "arm,neoverse-n1";
65
+ set_feature(&cpu->env, ARM_FEATURE_V8);
66
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
67
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
68
+ set_feature(&cpu->env, ARM_FEATURE_AARCH64);
69
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
70
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
71
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
72
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
73
+
74
+ /* Ordered by B2.4 AArch64 registers by functional group */
75
+ cpu->clidr = 0x82000023;
76
+ cpu->ctr = 0x8444c004;
77
+ cpu->dcz_blocksize = 4;
78
+ cpu->isar.id_aa64dfr0 = 0x0000000110305408ull;
79
+ cpu->isar.id_aa64isar0 = 0x0000100010211120ull;
80
+ cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
81
+ cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
82
+ cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
83
+ cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
84
+ cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */
85
+ cpu->isar.id_aa64pfr1 = 0x0000000000000020ull;
86
+ cpu->id_afr0 = 0x00000000;
87
+ cpu->isar.id_dfr0 = 0x04010088;
88
+ cpu->isar.id_isar0 = 0x02101110;
89
+ cpu->isar.id_isar1 = 0x13112111;
90
+ cpu->isar.id_isar2 = 0x21232042;
91
+ cpu->isar.id_isar3 = 0x01112131;
92
+ cpu->isar.id_isar4 = 0x00010142;
93
+ cpu->isar.id_isar5 = 0x01011121;
94
+ cpu->isar.id_isar6 = 0x00000010;
95
+ cpu->isar.id_mmfr0 = 0x10201105;
96
+ cpu->isar.id_mmfr1 = 0x40000000;
97
+ cpu->isar.id_mmfr2 = 0x01260000;
98
+ cpu->isar.id_mmfr3 = 0x02122211;
99
+ cpu->isar.id_mmfr4 = 0x00021110;
100
+ cpu->isar.id_pfr0 = 0x10010131;
101
+ cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */
102
+ cpu->isar.id_pfr2 = 0x00000011;
103
+ cpu->midr = 0x414fd0c1; /* r4p1 */
104
+ cpu->revidr = 0;
105
+
106
+ /* From B2.23 CCSIDR_EL1 */
107
+ cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */
108
+ cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */
109
+ cpu->ccsidr[2] = 0x70ffe03a; /* 1MB L2 cache */
110
+
111
+ /* From B2.98 SCTLR_EL3 */
112
+ cpu->reset_sctlr = 0x30c50838;
113
+
114
+ /* From B4.23 ICH_VTR_EL2 */
115
+ cpu->gic_num_lrs = 4;
116
+ cpu->gic_vpribits = 5;
117
+ cpu->gic_vprebits = 5;
118
+
119
+ /* From B5.1 AdvSIMD AArch64 register summary */
120
+ cpu->isar.mvfr0 = 0x10110222;
121
+ cpu->isar.mvfr1 = 0x13211111;
122
+ cpu->isar.mvfr2 = 0x00000043;
59
+}
123
+}
60
+
124
+
61
+static void virt_set_its(Object *obj, bool value, Error **errp)
125
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
62
+{
63
+ VirtMachineState *vms = VIRT_MACHINE(obj);
64
+
65
+ vms->its = value;
66
+}
67
+
68
static char *virt_get_gic_version(Object *obj, Error **errp)
69
{
126
{
70
VirtMachineState *vms = VIRT_MACHINE(obj);
127
/*
71
@@ -XXX,XX +XXX,XX @@ type_init(machvirt_machine_init);
128
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo aarch64_cpus[] = {
72
static void virt_2_9_instance_init(Object *obj)
129
{ .name = "cortex-a72", .initfn = aarch64_a72_initfn },
73
{
130
{ .name = "cortex-a76", .initfn = aarch64_a76_initfn },
74
VirtMachineState *vms = VIRT_MACHINE(obj);
131
{ .name = "a64fx", .initfn = aarch64_a64fx_initfn },
75
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
132
+ { .name = "neoverse-n1", .initfn = aarch64_neoverse_n1_initfn },
76
133
{ .name = "max", .initfn = aarch64_max_initfn },
77
/* EL3 is disabled by default on virt: this makes us consistent
134
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
78
* between KVM and TCG for this board, and it also allows us to
135
{ .name = "host", .initfn = aarch64_host_initfn },
79
@@ -XXX,XX +XXX,XX @@ static void virt_2_9_instance_init(Object *obj)
80
"Set GIC version. "
81
"Valid values are 2, 3 and host", NULL);
82
83
+ if (vmc->no_its) {
84
+ vms->its = false;
85
+ } else {
86
+ /* Default allows ITS instantiation */
87
+ vms->its = true;
88
+ object_property_add_bool(obj, "its", virt_get_its,
89
+ virt_set_its, NULL);
90
+ object_property_set_description(obj, "its",
91
+ "Set on/off to enable/disable "
92
+ "ITS instantiation",
93
+ NULL);
94
+ }
95
+
96
vms->memmap = a15memmap;
97
vms->irqmap = a15irqmap;
98
}
99
--
136
--
100
2.7.4
137
2.25.1
101
102
diff view generated by jsdifflib
1
From: Marcin Chojnacki <marcinch7@gmail.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Recent vanilla Raspberry Pi kernels started to make use of
3
The sbsa-ref machine is continuously evolving. Some of the changes we
4
the hardware random number generator in BCM2835 SoC. As a
4
want to make in the near future, to align with real components (e.g.
5
result, those kernels wouldn't work anymore under QEMU
5
the GIC-700), will break compatibility for existing firmware.
6
but rather just freeze during the boot process.
7
6
8
This patch implements a trivial BCM2835 compatible RNG,
7
Introduce two new properties to the DT generated on machine generation:
9
and adds it as a peripheral to BCM2835 platform, which
8
- machine-version-major
10
allows to boot a vanilla Raspberry Pi kernel under Qemu.
9
To be incremented when a platform change makes the machine
10
incompatible with existing firmware.
11
- machine-version-minor
12
To be incremented when functionality is added to the machine
13
without causing incompatibility with existing firmware.
14
to be reset to 0 when machine-version-major is incremented.
11
15
12
Changes since v1:
16
This versioning scheme is *neither*:
13
* Prevented guest from writing [31..20] bits in rng_status
17
- A QEMU versioned machine type; a given version of QEMU will emulate
14
* Removed redundant minimum_version_id_old
18
a given version of the platform.
15
* Added field entries for the state
19
- A reflection of level of SBSA (now SystemReady SR) support provided.
16
* Changed realize function to reset
17
20
18
Signed-off-by: Marcin Chojnacki <marcinch7@gmail.com>
21
The version will increment on guest-visible functional changes only,
19
Message-id: 20170210210857.47893-1-marcinch7@gmail.com
22
akin to a revision ID register found on a physical platform.
23
24
These properties are both introduced with the value 0.
25
(Hence, a machine where the DT is lacking these nodes is equivalent
26
to version 0.0.)
27
28
Signed-off-by: Leif Lindholm <quic_llindhol@quicinc.com>
29
Message-id: 20220505113947.75714-1-quic_llindhol@quicinc.com
30
Cc: Peter Maydell <peter.maydell@linaro.org>
31
Cc: Radoslaw Biernacki <rad@semihalf.com>
32
Cc: Cédric Le Goater <clg@kaod.org>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
33
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
35
---
23
hw/misc/Makefile.objs | 1 +
36
hw/arm/sbsa-ref.c | 14 ++++++++++++++
24
include/hw/arm/bcm2835_peripherals.h | 2 +
37
1 file changed, 14 insertions(+)
25
include/hw/misc/bcm2835_rng.h | 27 ++++++++
26
hw/arm/bcm2835_peripherals.c | 15 +++++
27
hw/misc/bcm2835_rng.c | 124 +++++++++++++++++++++++++++++++++++
28
5 files changed, 169 insertions(+)
29
create mode 100644 include/hw/misc/bcm2835_rng.h
30
create mode 100644 hw/misc/bcm2835_rng.c
31
38
32
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
39
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
33
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/misc/Makefile.objs
41
--- a/hw/arm/sbsa-ref.c
35
+++ b/hw/misc/Makefile.objs
42
+++ b/hw/arm/sbsa-ref.c
36
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_sdrc.o
43
@@ -XXX,XX +XXX,XX @@ static void create_fdt(SBSAMachineState *sms)
37
obj-$(CONFIG_OMAP) += omap_tap.o
44
qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
38
obj-$(CONFIG_RASPI) += bcm2835_mbox.o
45
qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
39
obj-$(CONFIG_RASPI) += bcm2835_property.o
46
40
+obj-$(CONFIG_RASPI) += bcm2835_rng.o
47
+ /*
41
obj-$(CONFIG_SLAVIO) += slavio_misc.o
48
+ * This versioning scheme is for informing platform fw only. It is neither:
42
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
49
+ * - A QEMU versioned machine type; a given version of QEMU will emulate
43
obj-$(CONFIG_ZYNQ) += zynq-xadc.o
50
+ * a given version of the platform.
44
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
51
+ * - A reflection of level of SBSA (now SystemReady SR) support provided.
45
index XXXXXXX..XXXXXXX 100644
52
+ *
46
--- a/include/hw/arm/bcm2835_peripherals.h
53
+ * machine-version-major: updated when changes breaking fw compatibility
47
+++ b/include/hw/arm/bcm2835_peripherals.h
54
+ * are introduced.
48
@@ -XXX,XX +XXX,XX @@
55
+ * machine-version-minor: updated when features are added that don't break
49
#include "hw/dma/bcm2835_dma.h"
56
+ * fw compatibility.
50
#include "hw/intc/bcm2835_ic.h"
57
+ */
51
#include "hw/misc/bcm2835_property.h"
58
+ qemu_fdt_setprop_cell(fdt, "/", "machine-version-major", 0);
52
+#include "hw/misc/bcm2835_rng.h"
59
+ qemu_fdt_setprop_cell(fdt, "/", "machine-version-minor", 0);
53
#include "hw/misc/bcm2835_mbox.h"
54
#include "hw/sd/sdhci.h"
55
56
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
57
BCM2835DMAState dma;
58
BCM2835ICState ic;
59
BCM2835PropertyState property;
60
+ BCM2835RngState rng;
61
BCM2835MboxState mboxes;
62
SDHCIState sdhci;
63
} BCM2835PeripheralState;
64
diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/bcm2835_rng.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * BCM2835 Random Number Generator emulation
72
+ *
73
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
74
+ *
75
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
76
+ * See the COPYING file in the top-level directory.
77
+ */
78
+
60
+
79
+#ifndef BCM2835_RNG_H
61
if (ms->numa_state->have_numa_distance) {
80
+#define BCM2835_RNG_H
62
int size = nb_numa_nodes * nb_numa_nodes * 3 * sizeof(uint32_t);
81
+
63
uint32_t *matrix = g_malloc0(size);
82
+#include "hw/sysbus.h"
83
+
84
+#define TYPE_BCM2835_RNG "bcm2835-rng"
85
+#define BCM2835_RNG(obj) \
86
+ OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG)
87
+
88
+typedef struct {
89
+ SysBusDevice busdev;
90
+ MemoryRegion iomem;
91
+
92
+ uint32_t rng_ctrl;
93
+ uint32_t rng_status;
94
+} BCM2835RngState;
95
+
96
+#endif
97
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/hw/arm/bcm2835_peripherals.c
100
+++ b/hw/arm/bcm2835_peripherals.c
101
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
102
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
103
OBJECT(&s->gpu_bus_mr), &error_abort);
104
105
+ /* Random Number Generator */
106
+ object_initialize(&s->rng, sizeof(s->rng), TYPE_BCM2835_RNG);
107
+ object_property_add_child(obj, "rng", OBJECT(&s->rng), NULL);
108
+ qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default());
109
+
110
/* Extended Mass Media Controller */
111
object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
112
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
113
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
114
sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
115
qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
116
117
+ /* Random Number Generator */
118
+ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
119
+ if (err) {
120
+ error_propagate(errp, err);
121
+ return;
122
+ }
123
+
124
+ memory_region_add_subregion(&s->peri_mr, RNG_OFFSET,
125
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
126
+
127
/* Extended Mass Media Controller */
128
object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
129
&err);
130
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
131
new file mode 100644
132
index XXXXXXX..XXXXXXX
133
--- /dev/null
134
+++ b/hw/misc/bcm2835_rng.c
135
@@ -XXX,XX +XXX,XX @@
136
+/*
137
+ * BCM2835 Random Number Generator emulation
138
+ *
139
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
140
+ *
141
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
142
+ * See the COPYING file in the top-level directory.
143
+ */
144
+
145
+#include "qemu/osdep.h"
146
+#include "qemu/log.h"
147
+#include "hw/misc/bcm2835_rng.h"
148
+
149
+static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
150
+ unsigned size)
151
+{
152
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
153
+ uint32_t res = 0;
154
+
155
+ assert(size == 4);
156
+
157
+ switch (offset) {
158
+ case 0x0: /* rng_ctrl */
159
+ res = s->rng_ctrl;
160
+ break;
161
+ case 0x4: /* rng_status */
162
+ res = s->rng_status | (1 << 24);
163
+ break;
164
+ case 0x8: /* rng_data */
165
+ res = rand();
166
+ break;
167
+
168
+ default:
169
+ qemu_log_mask(LOG_GUEST_ERROR,
170
+ "bcm2835_rng_read: Bad offset %x\n",
171
+ (int)offset);
172
+ res = 0;
173
+ break;
174
+ }
175
+
176
+ return res;
177
+}
178
+
179
+static void bcm2835_rng_write(void *opaque, hwaddr offset,
180
+ uint64_t value, unsigned size)
181
+{
182
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
183
+
184
+ assert(size == 4);
185
+
186
+ switch (offset) {
187
+ case 0x0: /* rng_ctrl */
188
+ s->rng_ctrl = value;
189
+ break;
190
+ case 0x4: /* rng_status */
191
+ /* we shouldn't let the guest write to bits [31..20] */
192
+ s->rng_status &= ~0xFFFFF; /* clear 20 lower bits */
193
+ s->rng_status |= value & 0xFFFFF; /* set them to new value */
194
+ break;
195
+
196
+ default:
197
+ qemu_log_mask(LOG_GUEST_ERROR,
198
+ "bcm2835_rng_write: Bad offset %x\n",
199
+ (int)offset);
200
+ break;
201
+ }
202
+}
203
+
204
+static const MemoryRegionOps bcm2835_rng_ops = {
205
+ .read = bcm2835_rng_read,
206
+ .write = bcm2835_rng_write,
207
+ .endianness = DEVICE_NATIVE_ENDIAN,
208
+};
209
+
210
+static const VMStateDescription vmstate_bcm2835_rng = {
211
+ .name = TYPE_BCM2835_RNG,
212
+ .version_id = 1,
213
+ .minimum_version_id = 1,
214
+ .fields = (VMStateField[]) {
215
+ VMSTATE_UINT32(rng_ctrl, BCM2835RngState),
216
+ VMSTATE_UINT32(rng_status, BCM2835RngState),
217
+ VMSTATE_END_OF_LIST()
218
+ }
219
+};
220
+
221
+static void bcm2835_rng_init(Object *obj)
222
+{
223
+ BCM2835RngState *s = BCM2835_RNG(obj);
224
+
225
+ memory_region_init_io(&s->iomem, obj, &bcm2835_rng_ops, s,
226
+ TYPE_BCM2835_RNG, 0x10);
227
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
228
+}
229
+
230
+static void bcm2835_rng_reset(DeviceState *dev)
231
+{
232
+ BCM2835RngState *s = BCM2835_RNG(dev);
233
+
234
+ s->rng_ctrl = 0;
235
+ s->rng_status = 0;
236
+}
237
+
238
+static void bcm2835_rng_class_init(ObjectClass *klass, void *data)
239
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
242
+ dc->reset = bcm2835_rng_reset;
243
+ dc->vmsd = &vmstate_bcm2835_rng;
244
+}
245
+
246
+static TypeInfo bcm2835_rng_info = {
247
+ .name = TYPE_BCM2835_RNG,
248
+ .parent = TYPE_SYS_BUS_DEVICE,
249
+ .instance_size = sizeof(BCM2835RngState),
250
+ .class_init = bcm2835_rng_class_init,
251
+ .instance_init = bcm2835_rng_init,
252
+};
253
+
254
+static void bcm2835_rng_register_types(void)
255
+{
256
+ type_register_static(&bcm2835_rng_info);
257
+}
258
+
259
+type_init(bcm2835_rng_register_types)
260
--
64
--
261
2.7.4
65
2.25.1
262
66
263
67
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Gavin Shan <gshan@redhat.com>
2
2
3
This adds the BCM2835 SDHost controller from Arasan.
3
This adds cluster-id in CPU instance properties, which will be used
4
by arm/virt machine. Besides, the cluster-id is also verified or
5
dumped in various spots:
4
6
5
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
7
* hw/core/machine.c::machine_set_cpu_numa_node() to associate
6
Message-id: 20170224164021.9066-2-clement.deschamps@antfield.fr
8
CPU with its NUMA node.
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
10
* hw/core/machine.c::machine_numa_finish_cpu_init() to record
11
CPU slots with no NUMA mapping set.
12
13
* hw/core/machine-hmp-cmds.c::hmp_hotpluggable_cpus() to dump
14
cluster-id.
15
16
Signed-off-by: Gavin Shan <gshan@redhat.com>
17
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
18
Acked-by: Igor Mammedov <imammedo@redhat.com>
19
Message-id: 20220503140304.855514-2-gshan@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
21
---
10
hw/sd/Makefile.objs | 1 +
22
qapi/machine.json | 6 ++++--
11
include/hw/sd/bcm2835_sdhost.h | 48 +++++
23
hw/core/machine-hmp-cmds.c | 4 ++++
12
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++++++++++++++++++++++++++
24
hw/core/machine.c | 16 ++++++++++++++++
13
3 files changed, 478 insertions(+)
25
3 files changed, 24 insertions(+), 2 deletions(-)
14
create mode 100644 include/hw/sd/bcm2835_sdhost.h
15
create mode 100644 hw/sd/bcm2835_sdhost.c
16
26
17
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
27
diff --git a/qapi/machine.json b/qapi/machine.json
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/sd/Makefile.objs
29
--- a/qapi/machine.json
20
+++ b/hw/sd/Makefile.objs
30
+++ b/qapi/machine.json
21
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SDHCI) += sdhci.o
22
obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
23
obj-$(CONFIG_OMAP) += omap_mmc.o
24
obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
25
+obj-$(CONFIG_RASPI) += bcm2835_sdhost.o
26
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
27
new file mode 100644
28
index XXXXXXX..XXXXXXX
29
--- /dev/null
30
+++ b/include/hw/sd/bcm2835_sdhost.h
31
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
32
+/*
32
# @node-id: NUMA node ID the CPU belongs to
33
+ * Raspberry Pi (BCM2835) SD Host Controller
33
# @socket-id: socket number within node/board the CPU belongs to
34
+ *
34
# @die-id: die number within socket the CPU belongs to (since 4.1)
35
+ * Copyright (c) 2017 Antfield SAS
35
-# @core-id: core number within die the CPU belongs to
36
+ *
36
+# @cluster-id: cluster number within die the CPU belongs to (since 7.1)
37
+ * Authors:
37
+# @core-id: core number within cluster the CPU belongs to
38
+ * Clement Deschamps <clement.deschamps@antfield.fr>
38
# @thread-id: thread number within core the CPU belongs to
39
+ * Luc Michel <luc.michel@antfield.fr>
39
#
40
+ *
40
-# Note: currently there are 5 properties that could be present
41
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
41
+# Note: currently there are 6 properties that could be present
42
+ * See the COPYING file in the top-level directory.
42
# but management should be prepared to pass through other
43
+ */
43
# properties with device_add command to allow for future
44
+
44
# interface extension. This also requires the filed names to be kept in
45
+#ifndef BCM2835_SDHOST_H
46
+#define BCM2835_SDHOST_H
47
+
48
+#include "hw/sysbus.h"
49
+#include "hw/sd/sd.h"
50
+
51
+#define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
52
+#define BCM2835_SDHOST(obj) \
53
+ OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST)
54
+
55
+#define BCM2835_SDHOST_FIFO_LEN 16
56
+
57
+typedef struct {
58
+ SysBusDevice busdev;
59
+ SDBus sdbus;
60
+ MemoryRegion iomem;
61
+
62
+ uint32_t cmd;
63
+ uint32_t cmdarg;
64
+ uint32_t status;
65
+ uint32_t rsp[4];
66
+ uint32_t config;
67
+ uint32_t edm;
68
+ uint32_t vdd;
69
+ uint32_t hbct;
70
+ uint32_t hblc;
71
+ int32_t fifo_pos;
72
+ int32_t fifo_len;
73
+ uint32_t fifo[BCM2835_SDHOST_FIFO_LEN];
74
+ uint32_t datacnt;
75
+
76
+ qemu_irq irq;
77
+} BCM2835SDHostState;
78
+
79
+#endif
80
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
81
new file mode 100644
82
index XXXXXXX..XXXXXXX
83
--- /dev/null
84
+++ b/hw/sd/bcm2835_sdhost.c
85
@@ -XXX,XX +XXX,XX @@
45
@@ -XXX,XX +XXX,XX @@
86
+/*
46
'data': { '*node-id': 'int',
87
+ * Raspberry Pi (BCM2835) SD Host Controller
47
'*socket-id': 'int',
88
+ *
48
'*die-id': 'int',
89
+ * Copyright (c) 2017 Antfield SAS
49
+ '*cluster-id': 'int',
90
+ *
50
'*core-id': 'int',
91
+ * Authors:
51
'*thread-id': 'int'
92
+ * Clement Deschamps <clement.deschamps@antfield.fr>
52
}
93
+ * Luc Michel <luc.michel@antfield.fr>
53
diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c
94
+ *
54
index XXXXXXX..XXXXXXX 100644
95
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
55
--- a/hw/core/machine-hmp-cmds.c
96
+ * See the COPYING file in the top-level directory.
56
+++ b/hw/core/machine-hmp-cmds.c
97
+ */
57
@@ -XXX,XX +XXX,XX @@ void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict)
98
+
58
if (c->has_die_id) {
99
+#include "qemu/osdep.h"
59
monitor_printf(mon, " die-id: \"%" PRIu64 "\"\n", c->die_id);
100
+#include "qemu/log.h"
60
}
101
+#include "sysemu/blockdev.h"
61
+ if (c->has_cluster_id) {
102
+#include "hw/sd/bcm2835_sdhost.h"
62
+ monitor_printf(mon, " cluster-id: \"%" PRIu64 "\"\n",
103
+
63
+ c->cluster_id);
104
+#define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus"
105
+#define BCM2835_SDHOST_BUS(obj) \
106
+ OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS)
107
+
108
+#define SDCMD 0x00 /* Command to SD card - 16 R/W */
109
+#define SDARG 0x04 /* Argument to SD card - 32 R/W */
110
+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
111
+#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
112
+#define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */
113
+#define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */
114
+#define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */
115
+#define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */
116
+#define SDHSTS 0x20 /* SD host status - 11 R */
117
+#define SDVDD 0x30 /* SD card power control - 1 R/W */
118
+#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
119
+#define SDHCFG 0x38 /* Host configuration - 2 R/W */
120
+#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
121
+#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
122
+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
123
+
124
+#define SDCMD_NEW_FLAG 0x8000
125
+#define SDCMD_FAIL_FLAG 0x4000
126
+#define SDCMD_BUSYWAIT 0x800
127
+#define SDCMD_NO_RESPONSE 0x400
128
+#define SDCMD_LONG_RESPONSE 0x200
129
+#define SDCMD_WRITE_CMD 0x80
130
+#define SDCMD_READ_CMD 0x40
131
+#define SDCMD_CMD_MASK 0x3f
132
+
133
+#define SDCDIV_MAX_CDIV 0x7ff
134
+
135
+#define SDHSTS_BUSY_IRPT 0x400
136
+#define SDHSTS_BLOCK_IRPT 0x200
137
+#define SDHSTS_SDIO_IRPT 0x100
138
+#define SDHSTS_REW_TIME_OUT 0x80
139
+#define SDHSTS_CMD_TIME_OUT 0x40
140
+#define SDHSTS_CRC16_ERROR 0x20
141
+#define SDHSTS_CRC7_ERROR 0x10
142
+#define SDHSTS_FIFO_ERROR 0x08
143
+/* Reserved */
144
+/* Reserved */
145
+#define SDHSTS_DATA_FLAG 0x01
146
+
147
+#define SDHCFG_BUSY_IRPT_EN (1 << 10)
148
+#define SDHCFG_BLOCK_IRPT_EN (1 << 8)
149
+#define SDHCFG_SDIO_IRPT_EN (1 << 5)
150
+#define SDHCFG_DATA_IRPT_EN (1 << 4)
151
+#define SDHCFG_SLOW_CARD (1 << 3)
152
+#define SDHCFG_WIDE_EXT_BUS (1 << 2)
153
+#define SDHCFG_WIDE_INT_BUS (1 << 1)
154
+#define SDHCFG_REL_CMD_LINE (1 << 0)
155
+
156
+#define SDEDM_FORCE_DATA_MODE (1 << 19)
157
+#define SDEDM_CLOCK_PULSE (1 << 20)
158
+#define SDEDM_BYPASS (1 << 21)
159
+
160
+#define SDEDM_WRITE_THRESHOLD_SHIFT 9
161
+#define SDEDM_READ_THRESHOLD_SHIFT 14
162
+#define SDEDM_THRESHOLD_MASK 0x1f
163
+
164
+#define SDEDM_FSM_MASK 0xf
165
+#define SDEDM_FSM_IDENTMODE 0x0
166
+#define SDEDM_FSM_DATAMODE 0x1
167
+#define SDEDM_FSM_READDATA 0x2
168
+#define SDEDM_FSM_WRITEDATA 0x3
169
+#define SDEDM_FSM_READWAIT 0x4
170
+#define SDEDM_FSM_READCRC 0x5
171
+#define SDEDM_FSM_WRITECRC 0x6
172
+#define SDEDM_FSM_WRITEWAIT1 0x7
173
+#define SDEDM_FSM_POWERDOWN 0x8
174
+#define SDEDM_FSM_POWERUP 0x9
175
+#define SDEDM_FSM_WRITESTART1 0xa
176
+#define SDEDM_FSM_WRITESTART2 0xb
177
+#define SDEDM_FSM_GENPULSES 0xc
178
+#define SDEDM_FSM_WRITEWAIT2 0xd
179
+#define SDEDM_FSM_STARTPOWDOWN 0xf
180
+
181
+#define SDDATA_FIFO_WORDS 16
182
+
183
+static void bcm2835_sdhost_update_irq(BCM2835SDHostState *s)
184
+{
185
+ uint32_t irq = s->status &
186
+ (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | SDHSTS_SDIO_IRPT);
187
+ qemu_set_irq(s->irq, !!irq);
188
+}
189
+
190
+static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
191
+{
192
+ SDRequest request;
193
+ uint8_t rsp[16];
194
+ int rlen;
195
+
196
+ request.cmd = s->cmd & SDCMD_CMD_MASK;
197
+ request.arg = s->cmdarg;
198
+
199
+ rlen = sdbus_do_command(&s->sdbus, &request, rsp);
200
+ if (rlen < 0) {
201
+ goto error;
202
+ }
203
+ if (!(s->cmd & SDCMD_NO_RESPONSE)) {
204
+#define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \
205
+ | (rsp[n + 2] << 8) | rsp[n + 3])
206
+ if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) {
207
+ goto error;
208
+ }
64
+ }
209
+ if (rlen != 4 && rlen != 16) {
65
if (c->has_core_id) {
210
+ goto error;
66
monitor_printf(mon, " core-id: \"%" PRIu64 "\"\n", c->core_id);
211
+ }
67
}
212
+ if (rlen == 4) {
68
diff --git a/hw/core/machine.c b/hw/core/machine.c
213
+ s->rsp[0] = RWORD(0);
69
index XXXXXXX..XXXXXXX 100644
214
+ s->rsp[1] = s->rsp[2] = s->rsp[3] = 0;
70
--- a/hw/core/machine.c
215
+ } else {
71
+++ b/hw/core/machine.c
216
+ s->rsp[0] = RWORD(12);
72
@@ -XXX,XX +XXX,XX @@ void machine_set_cpu_numa_node(MachineState *machine,
217
+ s->rsp[1] = RWORD(8);
73
return;
218
+ s->rsp[2] = RWORD(4);
74
}
219
+ s->rsp[3] = RWORD(0);
75
220
+ }
76
+ if (props->has_cluster_id && !slot->props.has_cluster_id) {
221
+#undef RWORD
77
+ error_setg(errp, "cluster-id is not supported");
222
+ }
78
+ return;
223
+ return;
224
+
225
+error:
226
+ s->cmd |= SDCMD_FAIL_FLAG;
227
+ s->status |= SDHSTS_CMD_TIME_OUT;
228
+}
229
+
230
+static void bcm2835_sdhost_fifo_push(BCM2835SDHostState *s, uint32_t value)
231
+{
232
+ int n;
233
+
234
+ if (s->fifo_len == BCM2835_SDHOST_FIFO_LEN) {
235
+ /* FIFO overflow */
236
+ return;
237
+ }
238
+ n = (s->fifo_pos + s->fifo_len) & (BCM2835_SDHOST_FIFO_LEN - 1);
239
+ s->fifo_len++;
240
+ s->fifo[n] = value;
241
+}
242
+
243
+static uint32_t bcm2835_sdhost_fifo_pop(BCM2835SDHostState *s)
244
+{
245
+ uint32_t value;
246
+
247
+ if (s->fifo_len == 0) {
248
+ /* FIFO underflow */
249
+ return 0;
250
+ }
251
+ value = s->fifo[s->fifo_pos];
252
+ s->fifo_len--;
253
+ s->fifo_pos = (s->fifo_pos + 1) & (BCM2835_SDHOST_FIFO_LEN - 1);
254
+ return value;
255
+}
256
+
257
+static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
258
+{
259
+ uint32_t value = 0;
260
+ int n;
261
+ int is_read;
262
+
263
+ is_read = (s->cmd & SDCMD_READ_CMD) != 0;
264
+ if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))) {
265
+ if (is_read) {
266
+ n = 0;
267
+ while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) {
268
+ value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8);
269
+ s->datacnt--;
270
+ n++;
271
+ if (n == 4) {
272
+ bcm2835_sdhost_fifo_push(s, value);
273
+ n = 0;
274
+ value = 0;
275
+ }
276
+ }
277
+ if (n != 0) {
278
+ bcm2835_sdhost_fifo_push(s, value);
279
+ }
280
+ } else { /* write */
281
+ n = 0;
282
+ while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
283
+ if (n == 0) {
284
+ value = bcm2835_sdhost_fifo_pop(s);
285
+ n = 4;
286
+ }
287
+ n--;
288
+ s->datacnt--;
289
+ sdbus_write_data(&s->sdbus, value & 0xff);
290
+ value >>= 8;
291
+ }
292
+ }
293
+ }
294
+ if (s->datacnt == 0) {
295
+ s->status |= SDHSTS_DATA_FLAG;
296
+
297
+ s->edm &= ~0xf;
298
+ s->edm |= SDEDM_FSM_DATAMODE;
299
+
300
+ if (s->config & SDHCFG_DATA_IRPT_EN) {
301
+ s->status |= SDHSTS_SDIO_IRPT;
302
+ }
79
+ }
303
+
80
+
304
+ if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)) {
81
if (props->has_socket_id && !slot->props.has_socket_id) {
305
+ s->status |= SDHSTS_BUSY_IRPT;
82
error_setg(errp, "socket-id is not supported");
83
return;
84
@@ -XXX,XX +XXX,XX @@ void machine_set_cpu_numa_node(MachineState *machine,
85
continue;
86
}
87
88
+ if (props->has_cluster_id &&
89
+ props->cluster_id != slot->props.cluster_id) {
90
+ continue;
306
+ }
91
+ }
307
+
92
+
308
+ if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_EN)) {
93
if (props->has_die_id && props->die_id != slot->props.die_id) {
309
+ s->status |= SDHSTS_BLOCK_IRPT;
94
continue;
95
}
96
@@ -XXX,XX +XXX,XX @@ static char *cpu_slot_to_string(const CPUArchId *cpu)
97
}
98
g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id);
99
}
100
+ if (cpu->props.has_cluster_id) {
101
+ if (s->len) {
102
+ g_string_append_printf(s, ", ");
310
+ }
103
+ }
311
+
104
+ g_string_append_printf(s, "cluster-id: %"PRId64, cpu->props.cluster_id);
312
+ bcm2835_sdhost_update_irq(s);
313
+ }
105
+ }
314
+
106
if (cpu->props.has_core_id) {
315
+ s->edm &= ~(0x1f << 4);
107
if (s->len) {
316
+ s->edm |= ((s->fifo_len & 0x1f) << 4);
108
g_string_append_printf(s, ", ");
317
+}
318
+
319
+static uint64_t bcm2835_sdhost_read(void *opaque, hwaddr offset,
320
+ unsigned size)
321
+{
322
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
323
+ uint32_t res = 0;
324
+
325
+ switch (offset) {
326
+ case SDCMD:
327
+ res = s->cmd;
328
+ break;
329
+ case SDHSTS:
330
+ res = s->status;
331
+ break;
332
+ case SDRSP0:
333
+ res = s->rsp[0];
334
+ break;
335
+ case SDRSP1:
336
+ res = s->rsp[1];
337
+ break;
338
+ case SDRSP2:
339
+ res = s->rsp[2];
340
+ break;
341
+ case SDRSP3:
342
+ res = s->rsp[3];
343
+ break;
344
+ case SDEDM:
345
+ res = s->edm;
346
+ break;
347
+ case SDVDD:
348
+ res = s->vdd;
349
+ break;
350
+ case SDDATA:
351
+ res = bcm2835_sdhost_fifo_pop(s);
352
+ bcm2835_sdhost_fifo_run(s);
353
+ break;
354
+ case SDHBCT:
355
+ res = s->hbct;
356
+ break;
357
+ case SDHBLC:
358
+ res = s->hblc;
359
+ break;
360
+
361
+ default:
362
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
363
+ __func__, offset);
364
+ res = 0;
365
+ break;
366
+ }
367
+
368
+ return res;
369
+}
370
+
371
+static void bcm2835_sdhost_write(void *opaque, hwaddr offset,
372
+ uint64_t value, unsigned size)
373
+{
374
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
375
+
376
+ switch (offset) {
377
+ case SDCMD:
378
+ s->cmd = value;
379
+ if (value & SDCMD_NEW_FLAG) {
380
+ bcm2835_sdhost_send_command(s);
381
+ bcm2835_sdhost_fifo_run(s);
382
+ s->cmd &= ~SDCMD_NEW_FLAG;
383
+ }
384
+ break;
385
+ case SDTOUT:
386
+ break;
387
+ case SDCDIV:
388
+ break;
389
+ case SDHSTS:
390
+ s->status &= ~value;
391
+ bcm2835_sdhost_update_irq(s);
392
+ break;
393
+ case SDARG:
394
+ s->cmdarg = value;
395
+ break;
396
+ case SDEDM:
397
+ if ((value & 0xf) == 0xf) {
398
+ /* power down */
399
+ value &= ~0xf;
400
+ }
401
+ s->edm = value;
402
+ break;
403
+ case SDHCFG:
404
+ s->config = value;
405
+ bcm2835_sdhost_fifo_run(s);
406
+ break;
407
+ case SDVDD:
408
+ s->vdd = value;
409
+ break;
410
+ case SDDATA:
411
+ bcm2835_sdhost_fifo_push(s, value);
412
+ bcm2835_sdhost_fifo_run(s);
413
+ break;
414
+ case SDHBCT:
415
+ s->hbct = value;
416
+ break;
417
+ case SDHBLC:
418
+ s->hblc = value;
419
+ s->datacnt = s->hblc * s->hbct;
420
+ bcm2835_sdhost_fifo_run(s);
421
+ break;
422
+
423
+ default:
424
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
425
+ __func__, offset);
426
+ break;
427
+ }
428
+}
429
+
430
+static const MemoryRegionOps bcm2835_sdhost_ops = {
431
+ .read = bcm2835_sdhost_read,
432
+ .write = bcm2835_sdhost_write,
433
+ .endianness = DEVICE_NATIVE_ENDIAN,
434
+};
435
+
436
+static const VMStateDescription vmstate_bcm2835_sdhost = {
437
+ .name = TYPE_BCM2835_SDHOST,
438
+ .version_id = 1,
439
+ .minimum_version_id = 1,
440
+ .fields = (VMStateField[]) {
441
+ VMSTATE_UINT32(cmd, BCM2835SDHostState),
442
+ VMSTATE_UINT32(cmdarg, BCM2835SDHostState),
443
+ VMSTATE_UINT32(status, BCM2835SDHostState),
444
+ VMSTATE_UINT32_ARRAY(rsp, BCM2835SDHostState, 4),
445
+ VMSTATE_UINT32(config, BCM2835SDHostState),
446
+ VMSTATE_UINT32(edm, BCM2835SDHostState),
447
+ VMSTATE_UINT32(vdd, BCM2835SDHostState),
448
+ VMSTATE_UINT32(hbct, BCM2835SDHostState),
449
+ VMSTATE_UINT32(hblc, BCM2835SDHostState),
450
+ VMSTATE_INT32(fifo_pos, BCM2835SDHostState),
451
+ VMSTATE_INT32(fifo_len, BCM2835SDHostState),
452
+ VMSTATE_UINT32_ARRAY(fifo, BCM2835SDHostState, BCM2835_SDHOST_FIFO_LEN),
453
+ VMSTATE_UINT32(datacnt, BCM2835SDHostState),
454
+ VMSTATE_END_OF_LIST()
455
+ }
456
+};
457
+
458
+static void bcm2835_sdhost_init(Object *obj)
459
+{
460
+ BCM2835SDHostState *s = BCM2835_SDHOST(obj);
461
+
462
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
463
+ TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus");
464
+
465
+ memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s,
466
+ TYPE_BCM2835_SDHOST, 0x1000);
467
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
468
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
469
+}
470
+
471
+static void bcm2835_sdhost_reset(DeviceState *dev)
472
+{
473
+ BCM2835SDHostState *s = BCM2835_SDHOST(dev);
474
+
475
+ s->cmd = 0;
476
+ s->cmdarg = 0;
477
+ s->edm = 0x0000c60f;
478
+ s->config = 0;
479
+ s->hbct = 0;
480
+ s->hblc = 0;
481
+ s->datacnt = 0;
482
+ s->fifo_pos = 0;
483
+ s->fifo_len = 0;
484
+}
485
+
486
+static void bcm2835_sdhost_class_init(ObjectClass *klass, void *data)
487
+{
488
+ DeviceClass *dc = DEVICE_CLASS(klass);
489
+
490
+ dc->reset = bcm2835_sdhost_reset;
491
+ dc->vmsd = &vmstate_bcm2835_sdhost;
492
+}
493
+
494
+static TypeInfo bcm2835_sdhost_info = {
495
+ .name = TYPE_BCM2835_SDHOST,
496
+ .parent = TYPE_SYS_BUS_DEVICE,
497
+ .instance_size = sizeof(BCM2835SDHostState),
498
+ .class_init = bcm2835_sdhost_class_init,
499
+ .instance_init = bcm2835_sdhost_init,
500
+};
501
+
502
+static const TypeInfo bcm2835_sdhost_bus_info = {
503
+ .name = TYPE_BCM2835_SDHOST_BUS,
504
+ .parent = TYPE_SD_BUS,
505
+ .instance_size = sizeof(SDBus),
506
+};
507
+
508
+static void bcm2835_sdhost_register_types(void)
509
+{
510
+ type_register_static(&bcm2835_sdhost_info);
511
+ type_register_static(&bcm2835_sdhost_bus_info);
512
+}
513
+
514
+type_init(bcm2835_sdhost_register_types)
515
--
109
--
516
2.7.4
110
2.25.1
517
518
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Gavin Shan <gshan@redhat.com>
2
2
3
In SDHCI protocol, the transfer mode register is defined
3
The CPU topology isn't enabled on arm/virt machine yet, but we're
4
to be of 6 bits. Mask its value with '0x0037' so that an
4
going to do it in next patch. After the CPU topology is enabled by
5
invalid value could not be assigned.
5
next patch, "thread-id=1" becomes invalid because the CPU core is
6
preferred on arm/virt machine. It means these two CPUs have 0/1
7
as their core IDs, but their thread IDs are all 0. It will trigger
8
test failure as the following message indicates:
6
9
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
10
[14/21 qemu:qtest+qtest-aarch64 / qtest-aarch64/numa-test ERROR
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
11
1.48s killed by signal 6 SIGABRT
9
Message-id: 20170214185225.7994-2-ppandit@redhat.com
12
>>> G_TEST_DBUS_DAEMON=/home/gavin/sandbox/qemu.main/tests/dbus-vmstate-daemon.sh \
13
QTEST_QEMU_STORAGE_DAEMON_BINARY=./storage-daemon/qemu-storage-daemon \
14
QTEST_QEMU_BINARY=./qemu-system-aarch64 \
15
QTEST_QEMU_IMG=./qemu-img MALLOC_PERTURB_=83 \
16
/home/gavin/sandbox/qemu.main/build/tests/qtest/numa-test --tap -k
17
――――――――――――――――――――――――――――――――――――――――――――――
18
stderr:
19
qemu-system-aarch64: -numa cpu,node-id=0,thread-id=1: no match found
20
21
This fixes the issue by providing comprehensive SMP configurations
22
in aarch64_numa_cpu(). The SMP configurations aren't used before
23
the CPU topology is enabled in next patch.
24
25
Signed-off-by: Gavin Shan <gshan@redhat.com>
26
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
27
Message-id: 20220503140304.855514-3-gshan@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
29
---
12
hw/sd/sdhci.c | 3 ++-
30
tests/qtest/numa-test.c | 3 ++-
13
1 file changed, 2 insertions(+), 1 deletion(-)
31
1 file changed, 2 insertions(+), 1 deletion(-)
14
32
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
33
diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c
16
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
35
--- a/tests/qtest/numa-test.c
18
+++ b/hw/sd/sdhci.c
36
+++ b/tests/qtest/numa-test.c
19
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ static void aarch64_numa_cpu(const void *data)
20
(SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
38
QTestState *qts;
21
(SDHC_CAPAB_TOCLKFREQ))
39
g_autofree char *cli = NULL;
22
40
23
+#define MASK_TRNMOD 0x0037
41
- cli = make_cli(data, "-machine smp.cpus=2 "
24
#define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val))
42
+ cli = make_cli(data, "-machine "
25
43
+ "smp.cpus=2,smp.sockets=1,smp.clusters=1,smp.cores=1,smp.threads=2 "
26
static uint8_t sdhci_slotint(SDHCIState *s)
44
"-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 "
27
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
45
"-numa cpu,node-id=1,thread-id=0 "
28
if (!(s->capareg & SDHC_CAN_DO_DMA)) {
46
"-numa cpu,node-id=0,thread-id=1");
29
value &= ~SDHC_TRNS_DMA;
30
}
31
- MASKED_WRITE(s->trnmod, mask, value);
32
+ MASKED_WRITE(s->trnmod, mask, value & MASK_TRNMOD);
33
MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
34
35
/* Writing to the upper byte of CMDREG triggers SD command generation */
36
--
47
--
37
2.7.4
48
2.25.1
38
49
39
50
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
From: Gavin Shan <gshan@redhat.com>
2
2
3
object_new(FOO) returns an object with ref_cnt == 1
3
Currently, the SMP configuration isn't considered when the CPU
4
and following
4
topology is populated. In this case, it's impossible to provide
5
object_property_set_bool(cpuobj, true, "realized", NULL)
5
the default CPU-to-NUMA mapping or association based on the socket
6
set parent of cpuobj to '/machine/unattached' which makes
6
ID of the given CPU.
7
ref_cnt == 2.
8
7
9
Since machvirt_init() doesn't take ownership of cpuobj
8
This takes account of SMP configuration when the CPU topology
10
returned by object_new() it should explicitly drop
9
is populated. The die ID for the given CPU isn't assigned since
11
reference to cpuobj when dangling pointer is about to
10
it's not supported on arm/virt machine. Besides, the used SMP
12
go out of scope like it's done pc_new_cpu() to avoid
11
configuration in qtest/numa-test/aarch64_numa_cpu() is corrcted
13
object leak.
12
to avoid testing failure
14
13
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
14
Signed-off-by: Gavin Shan <gshan@redhat.com>
16
Message-id: 1487253461-269218-1-git-send-email-imammedo@redhat.com
15
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Acked-by: Igor Mammedov <imammedo@redhat.com>
17
Message-id: 20220503140304.855514-4-gshan@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
19
---
20
hw/arm/virt.c | 1 +
20
hw/arm/virt.c | 15 ++++++++++++++-
21
1 file changed, 1 insertion(+)
21
1 file changed, 14 insertions(+), 1 deletion(-)
22
22
23
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
23
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
24
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/virt.c
25
--- a/hw/arm/virt.c
26
+++ b/hw/arm/virt.c
26
+++ b/hw/arm/virt.c
27
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
27
@@ -XXX,XX +XXX,XX @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
28
}
28
int n;
29
29
unsigned int max_cpus = ms->smp.max_cpus;
30
object_property_set_bool(cpuobj, true, "realized", NULL);
30
VirtMachineState *vms = VIRT_MACHINE(ms);
31
+ object_unref(cpuobj);
31
+ MachineClass *mc = MACHINE_GET_CLASS(vms);
32
33
if (ms->possible_cpus) {
34
assert(ms->possible_cpus->len == max_cpus);
35
@@ -XXX,XX +XXX,XX @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
36
ms->possible_cpus->cpus[n].type = ms->cpu_type;
37
ms->possible_cpus->cpus[n].arch_id =
38
virt_cpu_mp_affinity(vms, n);
39
+
40
+ assert(!mc->smp_props.dies_supported);
41
+ ms->possible_cpus->cpus[n].props.has_socket_id = true;
42
+ ms->possible_cpus->cpus[n].props.socket_id =
43
+ n / (ms->smp.clusters * ms->smp.cores * ms->smp.threads);
44
+ ms->possible_cpus->cpus[n].props.has_cluster_id = true;
45
+ ms->possible_cpus->cpus[n].props.cluster_id =
46
+ (n / (ms->smp.cores * ms->smp.threads)) % ms->smp.clusters;
47
+ ms->possible_cpus->cpus[n].props.has_core_id = true;
48
+ ms->possible_cpus->cpus[n].props.core_id =
49
+ (n / ms->smp.threads) % ms->smp.cores;
50
ms->possible_cpus->cpus[n].props.has_thread_id = true;
51
- ms->possible_cpus->cpus[n].props.thread_id = n;
52
+ ms->possible_cpus->cpus[n].props.thread_id =
53
+ n % ms->smp.threads;
32
}
54
}
33
fdt_add_timer_nodes(vms);
55
return ms->possible_cpus;
34
fdt_add_cpu_nodes(vms);
56
}
35
--
57
--
36
2.7.4
58
2.25.1
37
38
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Gavin Shan <gshan@redhat.com>
2
2
3
In the SDHCI protocol, the transfer mode register value
3
In aarch64_numa_cpu(), the CPU and NUMA association is something
4
is used during multi block transfer to check if block count
4
like below. Two threads in the same core/cluster/socket are
5
register is enabled and should be updated. Transfer mode
5
associated with two individual NUMA nodes, which is unreal as
6
register could be set such that, block count register would
6
Igor Mammedov mentioned. We don't expect the association to break
7
not be updated, thus leading to an infinite loop. Add check
7
NUMA-to-socket boundary, which matches with the real world.
8
to avoid it.
9
8
10
Reported-by: Wjjzhang <wjjzhang@tencent.com>
9
NUMA-node socket cluster core thread
11
Reported-by: Jiang Xin <jiangxin1@huawei.com>
10
------------------------------------------
12
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
11
0 0 0 0 0
13
Message-id: 20170214185225.7994-3-ppandit@redhat.com
12
1 0 0 0 1
14
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
13
14
This corrects the topology for CPUs and their association with
15
NUMA nodes. After this patch is applied, the CPU and NUMA
16
association becomes something like below, which looks real.
17
Besides, socket/cluster/core/thread IDs are all checked when
18
the NUMA node IDs are verified. It helps to check if the CPU
19
topology is properly populated or not.
20
21
NUMA-node socket cluster core thread
22
------------------------------------------
23
0 1 0 0 0
24
1 0 0 0 0
25
26
Suggested-by: Igor Mammedov <imammedo@redhat.com>
27
Signed-off-by: Gavin Shan <gshan@redhat.com>
28
Acked-by: Igor Mammedov <imammedo@redhat.com>
29
Message-id: 20220503140304.855514-5-gshan@redhat.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
31
---
17
hw/sd/sdhci.c | 10 +++++-----
32
tests/qtest/numa-test.c | 18 ++++++++++++------
18
1 file changed, 5 insertions(+), 5 deletions(-)
33
1 file changed, 12 insertions(+), 6 deletions(-)
19
34
20
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
35
diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c
21
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/sd/sdhci.c
37
--- a/tests/qtest/numa-test.c
23
+++ b/hw/sd/sdhci.c
38
+++ b/tests/qtest/numa-test.c
24
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
39
@@ -XXX,XX +XXX,XX @@ static void aarch64_numa_cpu(const void *data)
25
uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12);
40
g_autofree char *cli = NULL;
26
uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk);
41
27
42
cli = make_cli(data, "-machine "
28
+ if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) {
43
- "smp.cpus=2,smp.sockets=1,smp.clusters=1,smp.cores=1,smp.threads=2 "
29
+ qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n");
44
+ "smp.cpus=2,smp.sockets=2,smp.clusters=1,smp.cores=1,smp.threads=1 "
30
+ return;
45
"-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 "
31
+ }
46
- "-numa cpu,node-id=1,thread-id=0 "
32
+
47
- "-numa cpu,node-id=0,thread-id=1");
33
/* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for
48
+ "-numa cpu,node-id=0,socket-id=1,cluster-id=0,core-id=0,thread-id=0 "
34
* possible stop at page boundary if initial address is not page aligned,
49
+ "-numa cpu,node-id=1,socket-id=0,cluster-id=0,core-id=0,thread-id=0");
35
* allow them to work properly */
50
qts = qtest_init(cli);
36
@@ -XXX,XX +XXX,XX @@ static void sdhci_data_transfer(void *opaque)
51
cpus = get_cpus(qts, &resp);
37
if (s->trnmod & SDHC_TRNS_DMA) {
52
g_assert(cpus);
38
switch (SDHC_DMA_TYPE(s->hostctl)) {
53
39
case SDHC_CTRL_SDMA:
54
while ((e = qlist_pop(cpus))) {
40
- if ((s->trnmod & SDHC_TRNS_MULTI) &&
55
QDict *cpu, *props;
41
- (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) {
56
- int64_t thread, node;
42
- break;
57
+ int64_t socket, cluster, core, thread, node;
43
- }
58
44
-
59
cpu = qobject_to(QDict, e);
45
if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
60
g_assert(qdict_haskey(cpu, "props"));
46
sdhci_sdma_transfer_single_block(s);
61
@@ -XXX,XX +XXX,XX @@ static void aarch64_numa_cpu(const void *data)
47
} else {
62
63
g_assert(qdict_haskey(props, "node-id"));
64
node = qdict_get_int(props, "node-id");
65
+ g_assert(qdict_haskey(props, "socket-id"));
66
+ socket = qdict_get_int(props, "socket-id");
67
+ g_assert(qdict_haskey(props, "cluster-id"));
68
+ cluster = qdict_get_int(props, "cluster-id");
69
+ g_assert(qdict_haskey(props, "core-id"));
70
+ core = qdict_get_int(props, "core-id");
71
g_assert(qdict_haskey(props, "thread-id"));
72
thread = qdict_get_int(props, "thread-id");
73
74
- if (thread == 0) {
75
+ if (socket == 0 && cluster == 0 && core == 0 && thread == 0) {
76
g_assert_cmpint(node, ==, 1);
77
- } else if (thread == 1) {
78
+ } else if (socket == 1 && cluster == 0 && core == 0 && thread == 0) {
79
g_assert_cmpint(node, ==, 0);
80
} else {
81
g_assert(false);
48
--
82
--
49
2.7.4
83
2.25.1
50
51
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Gavin Shan <gshan@redhat.com>
2
2
3
Now that the NVIC is its own separate implementation, we can
3
When CPU-to-NUMA association isn't explicitly provided by users,
4
clean up the GIC code by removing REV_NVIC and conditionals
4
the default one is given by mc->get_default_cpu_node_id(). However,
5
which use it.
5
the CPU topology isn't fully considered in the default association
6
and this causes CPU topology broken warnings on booting Linux guest.
6
7
7
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
8
For example, the following warning messages are observed when the
9
Linux guest is booted with the following command lines.
10
11
/home/gavin/sandbox/qemu.main/build/qemu-system-aarch64 \
12
-accel kvm -machine virt,gic-version=host \
13
-cpu host \
14
-smp 6,sockets=2,cores=3,threads=1 \
15
-m 1024M,slots=16,maxmem=64G \
16
-object memory-backend-ram,id=mem0,size=128M \
17
-object memory-backend-ram,id=mem1,size=128M \
18
-object memory-backend-ram,id=mem2,size=128M \
19
-object memory-backend-ram,id=mem3,size=128M \
20
-object memory-backend-ram,id=mem4,size=128M \
21
-object memory-backend-ram,id=mem4,size=384M \
22
-numa node,nodeid=0,memdev=mem0 \
23
-numa node,nodeid=1,memdev=mem1 \
24
-numa node,nodeid=2,memdev=mem2 \
25
-numa node,nodeid=3,memdev=mem3 \
26
-numa node,nodeid=4,memdev=mem4 \
27
-numa node,nodeid=5,memdev=mem5
28
:
29
alternatives: patching kernel code
30
BUG: arch topology borken
31
the CLS domain not a subset of the MC domain
32
<the above error log repeats>
33
BUG: arch topology borken
34
the DIE domain not a subset of the NODE domain
35
36
With current implementation of mc->get_default_cpu_node_id(),
37
CPU#0 to CPU#5 are associated with NODE#0 to NODE#5 separately.
38
That's incorrect because CPU#0/1/2 should be associated with same
39
NUMA node because they're seated in same socket.
40
41
This fixes the issue by considering the socket ID when the default
42
CPU-to-NUMA association is provided in virt_possible_cpu_arch_ids().
43
With this applied, no more CPU topology broken warnings are seen
44
from the Linux guest. The 6 CPUs are associated with NODE#0/1, but
45
there are no CPUs associated with NODE#2/3/4/5.
46
47
Signed-off-by: Gavin Shan <gshan@redhat.com>
48
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
49
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
50
Message-id: 20220503140304.855514-6-gshan@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
51
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
---
52
---
11
hw/intc/gic_internal.h | 7 ++-----
53
hw/arm/virt.c | 4 +++-
12
hw/intc/arm_gic.c | 31 +++++--------------------------
54
1 file changed, 3 insertions(+), 1 deletion(-)
13
hw/intc/arm_gic_common.c | 23 ++++++++---------------
14
3 files changed, 15 insertions(+), 46 deletions(-)
15
55
16
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
56
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
17
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/gic_internal.h
58
--- a/hw/arm/virt.c
19
+++ b/hw/intc/gic_internal.h
59
+++ b/hw/arm/virt.c
20
@@ -XXX,XX +XXX,XX @@
60
@@ -XXX,XX +XXX,XX @@ virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
21
61
22
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
62
static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
23
24
-/* The NVIC has 16 internal vectors. However these are not exposed
25
- through the normal GIC interface. */
26
-#define GIC_BASE_IRQ ((s->revision == REV_NVIC) ? 32 : 0)
27
+#define GIC_BASE_IRQ 0
28
29
#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
30
#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
31
@@ -XXX,XX +XXX,XX @@
32
33
/* The special cases for the revision property: */
34
#define REV_11MPCORE 0
35
-#define REV_NVIC 0xffffffff
36
37
void gic_set_pending_private(GICState *s, int cpu, int irq);
38
uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs);
39
@@ -XXX,XX +XXX,XX @@ void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val,
40
41
static inline bool gic_test_pending(GICState *s, int irq, int cm)
42
{
63
{
43
- if (s->revision == REV_NVIC || s->revision == REV_11MPCORE) {
64
- return idx % ms->numa_state->num_nodes;
44
+ if (s->revision == REV_11MPCORE) {
65
+ int64_t socket_id = ms->possible_cpus->cpus[idx].props.socket_id;
45
return s->irq_state[irq].pending & cm;
66
+
46
} else {
67
+ return socket_id % ms->numa_state->num_nodes;
47
/* Edge-triggered interrupts are marked pending on a rising edge, but
48
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/intc/arm_gic.c
51
+++ b/hw/intc/arm_gic.c
52
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq_11mpcore(GICState *s, int irq, int level,
53
}
54
}
68
}
55
69
56
-static void gic_set_irq_nvic(GICState *s, int irq, int level,
70
static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
57
- int cm, int target)
58
-{
59
- if (level) {
60
- GIC_SET_LEVEL(irq, cm);
61
- GIC_SET_PENDING(irq, target);
62
- } else {
63
- GIC_CLEAR_LEVEL(irq, cm);
64
- }
65
-}
66
-
67
static void gic_set_irq_generic(GICState *s, int irq, int level,
68
int cm, int target)
69
{
70
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq(void *opaque, int irq, int level)
71
72
if (s->revision == REV_11MPCORE) {
73
gic_set_irq_11mpcore(s, irq, level, cm, target);
74
- } else if (s->revision == REV_NVIC) {
75
- gic_set_irq_nvic(s, irq, level, cm, target);
76
} else {
77
gic_set_irq_generic(s, irq, level, cm, target);
78
}
79
@@ -XXX,XX +XXX,XX @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
80
return 1023;
81
}
82
83
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
84
+ if (s->revision == REV_11MPCORE) {
85
/* Clear pending flags for both level and edge triggered interrupts.
86
* Level triggered IRQs will be reasserted once they become inactive.
87
*/
88
@@ -XXX,XX +XXX,XX @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
89
DPRINTF("Set %d pending mask %x\n", irq, cm);
90
GIC_SET_PENDING(irq, cm);
91
}
92
- } else if (s->revision == REV_NVIC) {
93
- if (GIC_TEST_LEVEL(irq, cm)) {
94
- DPRINTF("Set nvic %d pending mask %x\n", irq, cm);
95
- GIC_SET_PENDING(irq, cm);
96
- }
97
}
98
99
group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
100
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
101
} else if (offset < 0xf10) {
102
goto bad_reg;
103
} else if (offset < 0xf30) {
104
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
105
+ if (s->revision == REV_11MPCORE) {
106
goto bad_reg;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
110
case 2:
111
res = gic_id_gicv2[(offset - 0xfd0) >> 2];
112
break;
113
- case REV_NVIC:
114
- /* Shouldn't be able to get here */
115
- abort();
116
default:
117
res = 0;
118
}
119
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
120
continue; /* Ignore Non-secure access of Group0 IRQ */
121
}
122
123
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
124
+ if (s->revision == REV_11MPCORE) {
125
if (value & (1 << (i * 2))) {
126
GIC_SET_MODEL(irq + i);
127
} else {
128
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
129
goto bad_reg;
130
} else if (offset < 0xf20) {
131
/* GICD_CPENDSGIRn */
132
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
133
+ if (s->revision == REV_11MPCORE) {
134
goto bad_reg;
135
}
136
irq = (offset - 0xf10);
137
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
138
}
139
} else if (offset < 0xf30) {
140
/* GICD_SPENDSGIRn */
141
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
142
+ if (s->revision == REV_11MPCORE) {
143
goto bad_reg;
144
}
145
irq = (offset - 0xf20);
146
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/intc/arm_gic_common.c
149
+++ b/hw/intc/arm_gic_common.c
150
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
151
* [N+32..N+63] PPIs for CPU 1
152
* ...
153
*/
154
- if (s->revision != REV_NVIC) {
155
- i += (GIC_INTERNAL * s->num_cpu);
156
- }
157
+ i += (GIC_INTERNAL * s->num_cpu);
158
qdev_init_gpio_in(DEVICE(s), handler, i);
159
160
for (i = 0; i < s->num_cpu; i++) {
161
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
162
memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
163
sysbus_init_mmio(sbd, &s->iomem);
164
165
- if (s->revision != REV_NVIC) {
166
- /* This is the main CPU interface "for this core". It is always
167
- * present because it is required by both software emulation and KVM.
168
- * NVIC is not handled here because its CPU interface is different,
169
- * neither it can use KVM.
170
- */
171
- memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
172
- s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
173
- sysbus_init_mmio(sbd, &s->cpuiomem[0]);
174
- }
175
+ /* This is the main CPU interface "for this core". It is always
176
+ * present because it is required by both software emulation and KVM.
177
+ */
178
+ memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
179
+ s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
180
+ sysbus_init_mmio(sbd, &s->cpuiomem[0]);
181
}
182
183
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
184
@@ -XXX,XX +XXX,XX @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
185
}
186
187
if (s->security_extn &&
188
- (s->revision == REV_11MPCORE || s->revision == REV_NVIC)) {
189
+ (s->revision == REV_11MPCORE)) {
190
error_setg(errp, "this GIC revision does not implement "
191
"the security extensions");
192
return;
193
@@ -XXX,XX +XXX,XX @@ static Property arm_gic_common_properties[] = {
194
DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
195
/* Revision can be 1 or 2 for GIC architecture specification
196
* versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC.
197
- * (Internally, 0xffffffff also indicates "not a GIC but an NVIC".)
198
*/
199
DEFINE_PROP_UINT32("revision", GICState, revision, 1),
200
/* True if the GIC should implement the security extensions */
201
--
71
--
202
2.7.4
72
2.25.1
203
204
diff view generated by jsdifflib
1
From: Kurban Mallachiev <mallachiev@ispras.ru>
1
From: Gavin Shan <gshan@redhat.com>
2
2
3
The i.MX timer device can be reset by writing to the SWR bit
3
When the PPTT table is built, the CPU topology is re-calculated, but
4
of the CR register. This has to behave differently from hard
4
it's unecessary because the CPU topology has been populated in
5
(power-on) reset because it does not reset all of the bits
5
virt_possible_cpu_arch_ids() on arm/virt machine.
6
in the CR register.
7
6
8
We were incorrectly implementing soft reset and hard reset
7
This reworks build_pptt() to avoid by reusing the existing IDs in
9
the same way, and in addition had a logic error which meant
8
ms->possible_cpus. Currently, the only user of build_pptt() is
10
that we were clearing the bits that soft-reset is supposed
9
arm/virt machine.
11
to preserve and not touching the bits that soft-reset clears.
12
This was not correct behaviour for either kind of reset.
13
10
14
Separate out the soft reset and hard reset code paths, and
11
Signed-off-by: Gavin Shan <gshan@redhat.com>
15
correct the handling of reset of the CR register so that it
12
Tested-by: Yanan Wang <wangyanan55@huawei.com>
16
is correct in both cases.
13
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
17
14
Acked-by: Igor Mammedov <imammedo@redhat.com>
18
Signed-off-by: Kurban Mallachiev <mallachiev@ispras.ru>
15
Acked-by: Michael S. Tsirkin <mst@redhat.com>
19
[PMM: rephrased commit message, spacing on operators;
16
Message-id: 20220503140304.855514-7-gshan@redhat.com
20
use bool rather than int for is_soft_reset]
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
18
---
24
hw/timer/imx_gpt.c | 33 +++++++++++++++++++++++++--------
19
hw/acpi/aml-build.c | 111 +++++++++++++++++++-------------------------
25
1 file changed, 25 insertions(+), 8 deletions(-)
20
1 file changed, 48 insertions(+), 63 deletions(-)
26
21
27
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
22
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
28
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/timer/imx_gpt.c
24
--- a/hw/acpi/aml-build.c
30
+++ b/hw/timer/imx_gpt.c
25
+++ b/hw/acpi/aml-build.c
31
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
26
@@ -XXX,XX +XXX,XX @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
32
return reg_value;
27
const char *oem_id, const char *oem_table_id)
28
{
29
MachineClass *mc = MACHINE_GET_CLASS(ms);
30
- GQueue *list = g_queue_new();
31
- guint pptt_start = table_data->len;
32
- guint parent_offset;
33
- guint length, i;
34
- int uid = 0;
35
- int socket;
36
+ CPUArchIdList *cpus = ms->possible_cpus;
37
+ int64_t socket_id = -1, cluster_id = -1, core_id = -1;
38
+ uint32_t socket_offset = 0, cluster_offset = 0, core_offset = 0;
39
+ uint32_t pptt_start = table_data->len;
40
+ int n;
41
AcpiTable table = { .sig = "PPTT", .rev = 2,
42
.oem_id = oem_id, .oem_table_id = oem_table_id };
43
44
acpi_table_begin(&table, table_data);
45
46
- for (socket = 0; socket < ms->smp.sockets; socket++) {
47
- g_queue_push_tail(list,
48
- GUINT_TO_POINTER(table_data->len - pptt_start));
49
- build_processor_hierarchy_node(
50
- table_data,
51
- /*
52
- * Physical package - represents the boundary
53
- * of a physical package
54
- */
55
- (1 << 0),
56
- 0, socket, NULL, 0);
57
- }
58
-
59
- if (mc->smp_props.clusters_supported) {
60
- length = g_queue_get_length(list);
61
- for (i = 0; i < length; i++) {
62
- int cluster;
63
-
64
- parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
65
- for (cluster = 0; cluster < ms->smp.clusters; cluster++) {
66
- g_queue_push_tail(list,
67
- GUINT_TO_POINTER(table_data->len - pptt_start));
68
- build_processor_hierarchy_node(
69
- table_data,
70
- (0 << 0), /* not a physical package */
71
- parent_offset, cluster, NULL, 0);
72
- }
73
+ /*
74
+ * This works with the assumption that cpus[n].props.*_id has been
75
+ * sorted from top to down levels in mc->possible_cpu_arch_ids().
76
+ * Otherwise, the unexpected and duplicated containers will be
77
+ * created.
78
+ */
79
+ for (n = 0; n < cpus->len; n++) {
80
+ if (cpus->cpus[n].props.socket_id != socket_id) {
81
+ assert(cpus->cpus[n].props.socket_id > socket_id);
82
+ socket_id = cpus->cpus[n].props.socket_id;
83
+ cluster_id = -1;
84
+ core_id = -1;
85
+ socket_offset = table_data->len - pptt_start;
86
+ build_processor_hierarchy_node(table_data,
87
+ (1 << 0), /* Physical package */
88
+ 0, socket_id, NULL, 0);
89
}
90
- }
91
92
- length = g_queue_get_length(list);
93
- for (i = 0; i < length; i++) {
94
- int core;
95
-
96
- parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
97
- for (core = 0; core < ms->smp.cores; core++) {
98
- if (ms->smp.threads > 1) {
99
- g_queue_push_tail(list,
100
- GUINT_TO_POINTER(table_data->len - pptt_start));
101
- build_processor_hierarchy_node(
102
- table_data,
103
- (0 << 0), /* not a physical package */
104
- parent_offset, core, NULL, 0);
105
- } else {
106
- build_processor_hierarchy_node(
107
- table_data,
108
- (1 << 1) | /* ACPI Processor ID valid */
109
- (1 << 3), /* Node is a Leaf */
110
- parent_offset, uid++, NULL, 0);
111
+ if (mc->smp_props.clusters_supported) {
112
+ if (cpus->cpus[n].props.cluster_id != cluster_id) {
113
+ assert(cpus->cpus[n].props.cluster_id > cluster_id);
114
+ cluster_id = cpus->cpus[n].props.cluster_id;
115
+ core_id = -1;
116
+ cluster_offset = table_data->len - pptt_start;
117
+ build_processor_hierarchy_node(table_data,
118
+ (0 << 0), /* Not a physical package */
119
+ socket_offset, cluster_id, NULL, 0);
120
}
121
+ } else {
122
+ cluster_offset = socket_offset;
123
}
124
- }
125
126
- length = g_queue_get_length(list);
127
- for (i = 0; i < length; i++) {
128
- int thread;
129
+ if (ms->smp.threads == 1) {
130
+ build_processor_hierarchy_node(table_data,
131
+ (1 << 1) | /* ACPI Processor ID valid */
132
+ (1 << 3), /* Node is a Leaf */
133
+ cluster_offset, n, NULL, 0);
134
+ } else {
135
+ if (cpus->cpus[n].props.core_id != core_id) {
136
+ assert(cpus->cpus[n].props.core_id > core_id);
137
+ core_id = cpus->cpus[n].props.core_id;
138
+ core_offset = table_data->len - pptt_start;
139
+ build_processor_hierarchy_node(table_data,
140
+ (0 << 0), /* Not a physical package */
141
+ cluster_offset, core_id, NULL, 0);
142
+ }
143
144
- parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
145
- for (thread = 0; thread < ms->smp.threads; thread++) {
146
- build_processor_hierarchy_node(
147
- table_data,
148
+ build_processor_hierarchy_node(table_data,
149
(1 << 1) | /* ACPI Processor ID valid */
150
(1 << 2) | /* Processor is a Thread */
151
(1 << 3), /* Node is a Leaf */
152
- parent_offset, uid++, NULL, 0);
153
+ core_offset, n, NULL, 0);
154
}
155
}
156
157
- g_queue_free(list);
158
acpi_table_end(linker, &table);
33
}
159
}
34
160
35
-static void imx_gpt_reset(DeviceState *dev)
36
-{
37
- IMXGPTState *s = IMX_GPT(dev);
38
39
+static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
40
+{
41
/* stop timer */
42
ptimer_stop(s->timer);
43
44
- /*
45
- * Soft reset doesn't touch some bits; hard reset clears them
46
+ /* Soft reset and hard reset differ only in their handling of the CR
47
+ * register -- soft reset preserves the values of some bits there.
48
*/
49
- s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
50
- GPT_CR_WAITEN|GPT_CR_DBGEN);
51
+ if (is_soft_reset) {
52
+ /* Clear all CR bits except those that are preserved by soft reset. */
53
+ s->cr &= GPT_CR_EN | GPT_CR_ENMOD | GPT_CR_STOPEN | GPT_CR_DOZEN |
54
+ GPT_CR_WAITEN | GPT_CR_DBGEN |
55
+ (GPT_CR_CLKSRC_MASK << GPT_CR_CLKSRC_SHIFT);
56
+ } else {
57
+ s->cr = 0;
58
+ }
59
s->sr = 0;
60
s->pr = 0;
61
s->ir = 0;
62
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_reset(DeviceState *dev)
63
}
64
}
65
66
+static void imx_gpt_soft_reset(DeviceState *dev)
67
+{
68
+ IMXGPTState *s = IMX_GPT(dev);
69
+ imx_gpt_reset_common(s, true);
70
+}
71
+
72
+static void imx_gpt_reset(DeviceState *dev)
73
+{
74
+ IMXGPTState *s = IMX_GPT(dev);
75
+ imx_gpt_reset_common(s, false);
76
+}
77
+
78
static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
79
unsigned size)
80
{
81
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
82
s->cr = value & ~0x7c14;
83
if (s->cr & GPT_CR_SWR) { /* force reset */
84
/* handle the reset */
85
- imx_gpt_reset(DEVICE(s));
86
+ imx_gpt_soft_reset(DEVICE(s));
87
} else {
88
/* set our freq, as the source might have changed */
89
imx_gpt_set_freq(s);
90
--
161
--
91
2.7.4
162
2.25.1
92
93
diff view generated by jsdifflib