1
Another lump of target-arm patches. I still have some patches in
1
First arm pullreq for 7.1. The bulk of this is the qemu_split_irq
2
my to-review queue, but this is a big enough set that I wanted
2
removal.
3
to send it out.
3
4
I have enough stuff in my to-review queue that I expect to do another
5
pullreq early next week, but 31 patches is enough to not hang on to.
4
6
5
thanks
7
thanks
6
-- PMM
8
-- PMM
7
9
8
The following changes since commit 04bb7fe2bf55bdf66d5b7a5a719b40bbb4048178:
10
The following changes since commit 9c125d17e9402c232c46610802e5931b3639d77b:
9
11
10
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180208' into staging (2018-02-08 17:41:15 +0000)
12
Merge tag 'pull-tcg-20220420' of https://gitlab.com/rth7680/qemu into staging (2022-04-20 16:43:11 -0700)
11
13
12
are available in the Git repository at:
14
are available in the Git repository at:
13
15
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180209
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220421
15
17
16
for you to fetch changes up to bbba7757bacc9f890a3f028d328b4b429dbe78ec:
18
for you to fetch changes up to 5b415dd61bdbf61fb4be0e9f1a7172b8bce682c6:
17
19
18
hw/core/generic-loader: Allow PC to be set on command line (2018-02-09 10:55:40 +0000)
20
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs (2022-04-21 11:37:05 +0100)
19
21
20
----------------------------------------------------------------
22
----------------------------------------------------------------
21
target-arm queue:
23
target-arm queue:
22
* Support M profile derived exceptions on exception entry and exit
24
* hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
23
* Implement AArch64 v8.2 crypto insns (SHA-512, SHA-3, SM3, SM4)
25
* versal: Add the Cortex-R5s in the Real-Time Processing Unit (RPU) subsystem
24
* Implement working i.MX6 SD controller
26
* versal: model enough of the Clock/Reset Low-power domain (CRL) to allow control of the Cortex-R5s
25
* Various devices preparatory to i.MX7 support
27
* xlnx-zynqmp: Connect 4 TTC timers
26
* Preparatory patches for SVE emulation
28
* exynos4210: Refactor GIC/combiner code to stop using qemu_split_irq
27
* v8M: Fix bug in implementation of 'TT' insn
29
* realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
28
* Give useful error if user tries to use userspace GICv3 with KVM
30
* stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
31
* hw/core/irq: remove unused 'qemu_irq_split' function
32
* npcm7xx: use symbolic constants for PWRON STRAP bit fields
33
* virt: document impact of gic-version on max CPUs
29
34
30
----------------------------------------------------------------
35
----------------------------------------------------------------
31
Andrey Smirnov (10):
36
Edgar E. Iglesias (6):
32
sdhci: Add i.MX specific subtype of SDHCI
37
timer: cadence_ttc: Break out header file to allow embedding
33
hw: i.MX: Convert i.MX6 to use TYPE_IMX_USDHC
38
hw/arm/xlnx-zynqmp: Connect 4 TTC timers
34
i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks
39
hw/arm: versal: Create an APU CPU Cluster
35
i.MX: Add code to emulate i.MX2 watchdog IP block
40
hw/arm: versal: Add the Cortex-R5Fs
36
i.MX: Add code to emulate i.MX7 SNVS IP-block
41
hw/misc: Add a model of the Xilinx Versal CRL
37
i.MX: Add code to emulate GPCv2 IP block
42
hw/arm: versal: Connect the CRL
38
i.MX: Add i.MX7 GPT variant
39
i.MX: Add implementation of i.MX7 GPR IP block
40
usb: Add basic code to emulate Chipidea USB IP
41
hw/arm: Move virt's PSCI DT fixup code to arm/boot.c
42
43
43
Ard Biesheuvel (5):
44
Hao Wu (2):
44
target/arm: implement SHA-512 instructions
45
hw/misc: Add PWRON STRAP bit fields in GCR module
45
target/arm: implement SHA-3 instructions
46
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs
46
target/arm: implement SM3 instructions
47
target/arm: implement SM4 instructions
48
target/arm: enable user-mode SHA-3, SM3, SM4 and SHA-512 instruction support
49
47
50
Christoffer Dall (1):
48
Heinrich Schuchardt (1):
51
target/arm/kvm: gic: Prevent creating userspace GICv3 with KVM
49
hw/arm/virt: impact of gic-version on max CPUs
52
50
53
Peter Maydell (9):
51
Peter Maydell (19):
54
target/arm: Add armv7m_nvic_set_pending_derived()
52
hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
55
target/arm: Split "get pending exception info" from "acknowledge it"
53
hw/arm/exynos4210: Use TYPE_OR_IRQ instead of custom OR-gate device
56
target/arm: Add ignore_stackfaults argument to v7m_exception_taken()
54
hw/intc/exynos4210_gic: Remove unused TYPE_EXYNOS4210_IRQ_GATE
57
target/arm: Make v7M exception entry stack push check MPU
55
hw/arm/exynos4210: Put a9mpcore device into state struct
58
target/arm: Make v7m_push_callee_stack() honour MPU
56
hw/arm/exynos4210: Drop int_gic_irq[] from Exynos4210Irq struct
59
target/arm: Make exception vector loads honour the SAU
57
hw/arm/exynos4210: Coalesce board_irqs and irq_table
60
target/arm: Handle exceptions during exception stack pop
58
hw/arm/exynos4210: Fix code style nit in combiner_grp_to_gic_id[]
61
target/arm/translate.c: Fix missing 'break' for TT insns
59
hw/arm/exynos4210: Move exynos4210_init_board_irqs() into exynos4210.c
62
hw/core/generic-loader: Allow PC to be set on command line
60
hw/arm/exynos4210: Put external GIC into state struct
61
hw/arm/exynos4210: Drop ext_gic_irq[] from Exynos4210Irq struct
62
hw/arm/exynos4210: Move exynos4210_combiner_get_gpioin() into exynos4210.c
63
hw/arm/exynos4210: Delete unused macro definitions
64
hw/arm/exynos4210: Use TYPE_SPLIT_IRQ in exynos4210_init_board_irqs()
65
hw/arm/exynos4210: Fill in irq_table[] for internal-combiner-only IRQ lines
66
hw/arm/exynos4210: Connect MCT_G0 and MCT_G1 to both combiners
67
hw/arm/exynos4210: Don't connect multiple lines to external GIC inputs
68
hw/arm/exynos4210: Fold combiner splits into exynos4210_init_board_irqs()
69
hw/arm/exynos4210: Put combiners into state struct
70
hw/arm/exynos4210: Drop Exynos4210Irq struct
63
71
64
Richard Henderson (5):
72
Zongyuan Li (3):
65
target/arm: Expand vector registers for SVE
73
hw/arm/realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
66
target/arm: Add predicate registers for SVE
74
hw/arm/stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
67
target/arm: Add SVE to migration state
75
hw/core/irq: remove unused 'qemu_irq_split' function
68
target/arm: Add ZCR_ELx
69
target/arm: Add SVE state to TB->FLAGS
70
76
71
hw/intc/Makefile.objs | 2 +-
77
docs/system/arm/virt.rst | 4 +-
72
hw/misc/Makefile.objs | 4 +
78
include/hw/arm/exynos4210.h | 50 ++--
73
hw/usb/Makefile.objs | 1 +
79
include/hw/arm/xlnx-versal.h | 16 ++
74
hw/sd/sdhci-internal.h | 23 ++
80
include/hw/arm/xlnx-zynqmp.h | 4 +
75
include/hw/intc/imx_gpcv2.h | 22 ++
81
include/hw/intc/exynos4210_combiner.h | 57 +++++
76
include/hw/misc/imx2_wdt.h | 33 +++
82
include/hw/intc/exynos4210_gic.h | 43 ++++
77
include/hw/misc/imx7_ccm.h | 139 +++++++++++
83
include/hw/irq.h | 5 -
78
include/hw/misc/imx7_gpr.h | 28 +++
84
include/hw/misc/npcm7xx_gcr.h | 30 +++
79
include/hw/misc/imx7_snvs.h | 35 +++
85
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++++
80
include/hw/sd/sdhci.h | 13 ++
86
include/hw/timer/cadence_ttc.h | 54 +++++
81
include/hw/timer/imx_gpt.h | 1 +
87
hw/arm/exynos4210.c | 430 ++++++++++++++++++++++++++++++----
82
include/hw/usb/chipidea.h | 16 ++
88
hw/arm/npcm7xx_boards.c | 24 +-
83
target/arm/cpu.h | 120 ++++++++--
89
hw/arm/realview.c | 33 ++-
84
target/arm/helper.h | 12 +
90
hw/arm/stellaris.c | 15 +-
85
target/arm/kvm_arm.h | 4 +
91
hw/arm/virt.c | 7 +
86
target/arm/translate.h | 2 +
92
hw/arm/xlnx-versal-virt.c | 6 +-
87
hw/arm/boot.c | 65 ++++++
93
hw/arm/xlnx-versal.c | 99 +++++++-
88
hw/arm/fsl-imx6.c | 2 +-
94
hw/arm/xlnx-zynqmp.c | 22 ++
89
hw/arm/virt.c | 61 -----
95
hw/core/irq.c | 15 --
90
hw/core/generic-loader.c | 2 +-
96
hw/intc/exynos4210_combiner.c | 108 +--------
91
hw/intc/armv7m_nvic.c | 98 +++++++-
97
hw/intc/exynos4210_gic.c | 344 +--------------------------
92
hw/intc/imx_gpcv2.c | 125 ++++++++++
98
hw/misc/xlnx-versal-crl.c | 421 +++++++++++++++++++++++++++++++++
93
hw/misc/imx2_wdt.c | 89 +++++++
99
hw/timer/cadence_ttc.c | 32 +--
94
hw/misc/imx7_ccm.c | 277 ++++++++++++++++++++++
100
MAINTAINERS | 2 +-
95
hw/misc/imx7_gpr.c | 124 ++++++++++
101
hw/misc/meson.build | 1 +
96
hw/misc/imx7_snvs.c | 83 +++++++
102
25 files changed, 1457 insertions(+), 600 deletions(-)
97
hw/sd/sdhci.c | 230 ++++++++++++++++++-
103
create mode 100644 include/hw/intc/exynos4210_combiner.h
98
hw/timer/imx_gpt.c | 25 ++
104
create mode 100644 include/hw/intc/exynos4210_gic.h
99
hw/usb/chipidea.c | 176 ++++++++++++++
105
create mode 100644 include/hw/misc/xlnx-versal-crl.h
100
linux-user/elfload.c | 19 ++
106
create mode 100644 include/hw/timer/cadence_ttc.h
101
target/arm/cpu64.c | 4 +
107
create mode 100644 hw/misc/xlnx-versal-crl.c
102
target/arm/crypto_helper.c | 277 +++++++++++++++++++++-
103
target/arm/helper.c | 548 +++++++++++++++++++++++++++++++++++++-------
104
target/arm/machine.c | 88 ++++++-
105
target/arm/translate-a64.c | 350 +++++++++++++++++++++++++++-
106
target/arm/translate.c | 8 +-
107
hw/intc/trace-events | 5 +-
108
hw/misc/trace-events | 4 +
109
38 files changed, 2928 insertions(+), 187 deletions(-)
110
create mode 100644 include/hw/intc/imx_gpcv2.h
111
create mode 100644 include/hw/misc/imx2_wdt.h
112
create mode 100644 include/hw/misc/imx7_ccm.h
113
create mode 100644 include/hw/misc/imx7_gpr.h
114
create mode 100644 include/hw/misc/imx7_snvs.h
115
create mode 100644 include/hw/usb/chipidea.h
116
create mode 100644 hw/intc/imx_gpcv2.c
117
create mode 100644 hw/misc/imx2_wdt.c
118
create mode 100644 hw/misc/imx7_ccm.c
119
create mode 100644 hw/misc/imx7_gpr.c
120
create mode 100644 hw/misc/imx7_snvs.c
121
create mode 100644 hw/usb/chipidea.c
122
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
It's not possible to provide the guest with the Security extensions
2
(TrustZone) when using KVM or HVF, because the hardware
3
virtualization extensions don't permit running EL3 guest code.
4
However, we weren't checking for this combination, with the result
5
that QEMU would assert if you tried it:
2
6
3
Add code to emulate Chipidea USB IP (used in i.MX SoCs). Tested to
7
$ qemu-system-aarch64 -enable-kvm -machine virt,secure=on -cpu host -display none
4
work against:
8
Unexpected error in object_property_find_err() at ../../qom/object.c:1304:
9
qemu-system-aarch64: Property 'host-arm-cpu.secure-memory' not found
10
Aborted
5
11
6
-usb -drive if=none,id=stick,file=usb.img,format=raw -device \
12
Check for this combination of options and report an error, in the
7
usb-storage,bus=usb-bus.0,drive=stick
13
same way we already do for attempts to give a KVM or HVF guest the
14
Virtualization or MTE extensions. Now we will report:
8
15
9
Cc: Peter Maydell <peter.maydell@linaro.org>
16
qemu-system-aarch64: mach-virt: KVM does not support providing Security extensions (TrustZone) to the guest CPU
10
Cc: Jason Wang <jasowang@redhat.com>
17
11
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/961
12
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
13
Cc: Michael S. Tsirkin <mst@redhat.com>
14
Cc: qemu-devel@nongnu.org
15
Cc: qemu-arm@nongnu.org
16
Cc: yurovsky@gmail.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20220404155301.566542-1-peter.maydell@linaro.org
20
---
22
---
21
hw/usb/Makefile.objs | 1 +
23
hw/arm/virt.c | 7 +++++++
22
include/hw/usb/chipidea.h | 16 +++++
24
1 file changed, 7 insertions(+)
23
hw/usb/chipidea.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++
24
3 files changed, 193 insertions(+)
25
create mode 100644 include/hw/usb/chipidea.h
26
create mode 100644 hw/usb/chipidea.c
27
25
28
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
26
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
29
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/usb/Makefile.objs
28
--- a/hw/arm/virt.c
31
+++ b/hw/usb/Makefile.objs
29
+++ b/hw/arm/virt.c
32
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
33
common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
31
exit(1);
34
32
}
35
obj-$(CONFIG_TUSB6010) += tusb6010.o
33
36
+obj-$(CONFIG_IMX) += chipidea.o
34
+ if (vms->secure && (kvm_enabled() || hvf_enabled())) {
37
35
+ error_report("mach-virt: %s does not support providing "
38
# emulated usb devices
36
+ "Security extensions (TrustZone) to the guest CPU",
39
common-obj-$(CONFIG_USB) += dev-hub.o
37
+ kvm_enabled() ? "KVM" : "HVF");
40
diff --git a/include/hw/usb/chipidea.h b/include/hw/usb/chipidea.h
38
+ exit(1);
41
new file mode 100644
42
index XXXXXXX..XXXXXXX
43
--- /dev/null
44
+++ b/include/hw/usb/chipidea.h
45
@@ -XXX,XX +XXX,XX @@
46
+#ifndef CHIPIDEA_H
47
+#define CHIPIDEA_H
48
+
49
+#include "hw/usb/hcd-ehci.h"
50
+
51
+typedef struct ChipideaState {
52
+ /*< private >*/
53
+ EHCISysBusState parent_obj;
54
+
55
+ MemoryRegion iomem[3];
56
+} ChipideaState;
57
+
58
+#define TYPE_CHIPIDEA "usb-chipidea"
59
+#define CHIPIDEA(obj) OBJECT_CHECK(ChipideaState, (obj), TYPE_CHIPIDEA)
60
+
61
+#endif /* CHIPIDEA_H */
62
diff --git a/hw/usb/chipidea.c b/hw/usb/chipidea.c
63
new file mode 100644
64
index XXXXXXX..XXXXXXX
65
--- /dev/null
66
+++ b/hw/usb/chipidea.c
67
@@ -XXX,XX +XXX,XX @@
68
+/*
69
+ * Copyright (c) 2018, Impinj, Inc.
70
+ *
71
+ * Chipidea USB block emulation code
72
+ *
73
+ * Author: Andrey Smirnov <andrew.smirnov@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
+
79
+#include "qemu/osdep.h"
80
+#include "hw/usb/hcd-ehci.h"
81
+#include "hw/usb/chipidea.h"
82
+#include "qemu/log.h"
83
+
84
+enum {
85
+ CHIPIDEA_USBx_DCIVERSION = 0x000,
86
+ CHIPIDEA_USBx_DCCPARAMS = 0x004,
87
+ CHIPIDEA_USBx_DCCPARAMS_HC = BIT(8),
88
+};
89
+
90
+static uint64_t chipidea_read(void *opaque, hwaddr offset,
91
+ unsigned size)
92
+{
93
+ return 0;
94
+}
95
+
96
+static void chipidea_write(void *opaque, hwaddr offset,
97
+ uint64_t value, unsigned size)
98
+{
99
+}
100
+
101
+static const struct MemoryRegionOps chipidea_ops = {
102
+ .read = chipidea_read,
103
+ .write = chipidea_write,
104
+ .endianness = DEVICE_NATIVE_ENDIAN,
105
+ .impl = {
106
+ /*
107
+ * Our device would not work correctly if the guest was doing
108
+ * unaligned access. This might not be a limitation on the
109
+ * real device but in practice there is no reason for a guest
110
+ * to access this device unaligned.
111
+ */
112
+ .min_access_size = 4,
113
+ .max_access_size = 4,
114
+ .unaligned = false,
115
+ },
116
+};
117
+
118
+static uint64_t chipidea_dc_read(void *opaque, hwaddr offset,
119
+ unsigned size)
120
+{
121
+ switch (offset) {
122
+ case CHIPIDEA_USBx_DCIVERSION:
123
+ return 0x1;
124
+ case CHIPIDEA_USBx_DCCPARAMS:
125
+ /*
126
+ * Real hardware (at least i.MX7) will also report the
127
+ * controller as "Device Capable" (and 8 supported endpoints),
128
+ * but there doesn't seem to be much point in doing so, since
129
+ * we don't emulate that part.
130
+ */
131
+ return CHIPIDEA_USBx_DCCPARAMS_HC;
132
+ }
39
+ }
133
+
40
+
134
+ return 0;
41
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
135
+}
42
error_report("mach-virt: %s does not support providing "
136
+
43
"Virtualization extensions to the guest CPU",
137
+static void chipidea_dc_write(void *opaque, hwaddr offset,
138
+ uint64_t value, unsigned size)
139
+{
140
+}
141
+
142
+static const struct MemoryRegionOps chipidea_dc_ops = {
143
+ .read = chipidea_dc_read,
144
+ .write = chipidea_dc_write,
145
+ .endianness = DEVICE_NATIVE_ENDIAN,
146
+ .impl = {
147
+ /*
148
+ * Our device would not work correctly if the guest was doing
149
+ * unaligned access. This might not be a limitation on the real
150
+ * device but in practice there is no reason for a guest to access
151
+ * this device unaligned.
152
+ */
153
+ .min_access_size = 4,
154
+ .max_access_size = 4,
155
+ .unaligned = false,
156
+ },
157
+};
158
+
159
+static void chipidea_init(Object *obj)
160
+{
161
+ EHCIState *ehci = &SYS_BUS_EHCI(obj)->ehci;
162
+ ChipideaState *ci = CHIPIDEA(obj);
163
+ int i;
164
+
165
+ for (i = 0; i < ARRAY_SIZE(ci->iomem); i++) {
166
+ const struct {
167
+ const char *name;
168
+ hwaddr offset;
169
+ uint64_t size;
170
+ const struct MemoryRegionOps *ops;
171
+ } regions[ARRAY_SIZE(ci->iomem)] = {
172
+ /*
173
+ * Registers located between offsets 0x000 and 0xFC
174
+ */
175
+ {
176
+ .name = TYPE_CHIPIDEA ".misc",
177
+ .offset = 0x000,
178
+ .size = 0x100,
179
+ .ops = &chipidea_ops,
180
+ },
181
+ /*
182
+ * Registers located between offsets 0x1A4 and 0x1DC
183
+ */
184
+ {
185
+ .name = TYPE_CHIPIDEA ".endpoints",
186
+ .offset = 0x1A4,
187
+ .size = 0x1DC - 0x1A4 + 4,
188
+ .ops = &chipidea_ops,
189
+ },
190
+ /*
191
+ * USB_x_DCIVERSION and USB_x_DCCPARAMS
192
+ */
193
+ {
194
+ .name = TYPE_CHIPIDEA ".dc",
195
+ .offset = 0x120,
196
+ .size = 8,
197
+ .ops = &chipidea_dc_ops,
198
+ },
199
+ };
200
+
201
+ memory_region_init_io(&ci->iomem[i],
202
+ obj,
203
+ regions[i].ops,
204
+ ci,
205
+ regions[i].name,
206
+ regions[i].size);
207
+
208
+ memory_region_add_subregion(&ehci->mem,
209
+ regions[i].offset,
210
+ &ci->iomem[i]);
211
+ }
212
+}
213
+
214
+static void chipidea_class_init(ObjectClass *klass, void *data)
215
+{
216
+ DeviceClass *dc = DEVICE_CLASS(klass);
217
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
218
+
219
+ /*
220
+ * Offsets used were taken from i.MX7Dual Applications Processor
221
+ * Reference Manual, Rev 0.1, p. 3177, Table 11-59
222
+ */
223
+ sec->capsbase = 0x100;
224
+ sec->opregbase = 0x140;
225
+ sec->portnr = 1;
226
+
227
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
228
+ dc->desc = "Chipidea USB Module";
229
+}
230
+
231
+static const TypeInfo chipidea_info = {
232
+ .name = TYPE_CHIPIDEA,
233
+ .parent = TYPE_SYS_BUS_EHCI,
234
+ .instance_size = sizeof(ChipideaState),
235
+ .instance_init = chipidea_init,
236
+ .class_init = chipidea_class_init,
237
+};
238
+
239
+static void chipidea_register_type(void)
240
+{
241
+ type_register_static(&chipidea_info);
242
+}
243
+type_init(chipidea_register_type)
244
--
44
--
245
2.16.1
45
2.25.1
246
247
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Add code to emulate SNVS IP-block. Currently only the bits needed to
3
Break out header file to allow embedding of the the TTC.
4
be able to emulate machine shutdown are implemented.
5
4
6
Cc: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
Cc: Jason Wang <jasowang@redhat.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
10
Cc: Michael S. Tsirkin <mst@redhat.com>
9
Message-id: 20220331222017.2914409-2-edgar.iglesias@gmail.com
11
Cc: qemu-devel@nongnu.org
12
Cc: qemu-arm@nongnu.org
13
Cc: yurovsky@gmail.com
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
11
---
18
hw/misc/Makefile.objs | 1 +
12
include/hw/timer/cadence_ttc.h | 54 ++++++++++++++++++++++++++++++++++
19
include/hw/misc/imx7_snvs.h | 35 +++++++++++++++++++
13
hw/timer/cadence_ttc.c | 32 ++------------------
20
hw/misc/imx7_snvs.c | 83 +++++++++++++++++++++++++++++++++++++++++++++
14
2 files changed, 56 insertions(+), 30 deletions(-)
21
3 files changed, 119 insertions(+)
15
create mode 100644 include/hw/timer/cadence_ttc.h
22
create mode 100644 include/hw/misc/imx7_snvs.h
23
create mode 100644 hw/misc/imx7_snvs.c
24
16
25
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
17
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/misc/Makefile.objs
28
+++ b/hw/misc/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx6_ccm.o
30
obj-$(CONFIG_IMX) += imx6_src.o
31
obj-$(CONFIG_IMX) += imx7_ccm.o
32
obj-$(CONFIG_IMX) += imx2_wdt.o
33
+obj-$(CONFIG_IMX) += imx7_snvs.o
34
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
35
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
36
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
37
diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h
38
new file mode 100644
18
new file mode 100644
39
index XXXXXXX..XXXXXXX
19
index XXXXXXX..XXXXXXX
40
--- /dev/null
20
--- /dev/null
41
+++ b/include/hw/misc/imx7_snvs.h
21
+++ b/include/hw/timer/cadence_ttc.h
42
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
43
+/*
23
+/*
44
+ * Copyright (c) 2017, Impinj, Inc.
24
+ * Xilinx Zynq cadence TTC model
45
+ *
25
+ *
46
+ * i.MX7 SNVS block emulation code
26
+ * Copyright (c) 2011 Xilinx Inc.
27
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
28
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
29
+ * Written By Haibing Ma
30
+ * M. Habib
47
+ *
31
+ *
48
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
32
+ * This program is free software; you can redistribute it and/or
33
+ * modify it under the terms of the GNU General Public License
34
+ * as published by the Free Software Foundation; either version
35
+ * 2 of the License, or (at your option) any later version.
49
+ *
36
+ *
50
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
37
+ * You should have received a copy of the GNU General Public License along
51
+ * See the COPYING file in the top-level directory.
38
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
52
+ */
39
+ */
40
+#ifndef HW_TIMER_CADENCE_TTC_H
41
+#define HW_TIMER_CADENCE_TTC_H
53
+
42
+
54
+#ifndef IMX7_SNVS_H
43
+#include "hw/sysbus.h"
55
+#define IMX7_SNVS_H
44
+#include "qemu/timer.h"
56
+
45
+
57
+#include "qemu/bitops.h"
46
+typedef struct {
58
+#include "hw/sysbus.h"
47
+ QEMUTimer *timer;
48
+ int freq;
59
+
49
+
50
+ uint32_t reg_clock;
51
+ uint32_t reg_count;
52
+ uint32_t reg_value;
53
+ uint16_t reg_interval;
54
+ uint16_t reg_match[3];
55
+ uint32_t reg_intr;
56
+ uint32_t reg_intr_en;
57
+ uint32_t reg_event_ctrl;
58
+ uint32_t reg_event;
60
+
59
+
61
+enum IMX7SNVSRegisters {
60
+ uint64_t cpu_time;
62
+ SNVS_LPCR = 0x38,
61
+ unsigned int cpu_time_valid;
63
+ SNVS_LPCR_TOP = BIT(6),
62
+
64
+ SNVS_LPCR_DP_EN = BIT(5)
63
+ qemu_irq irq;
64
+} CadenceTimerState;
65
+
66
+#define TYPE_CADENCE_TTC "cadence_ttc"
67
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
68
+
69
+struct CadenceTTCState {
70
+ SysBusDevice parent_obj;
71
+
72
+ MemoryRegion iomem;
73
+ CadenceTimerState timer[3];
65
+};
74
+};
66
+
75
+
67
+#define TYPE_IMX7_SNVS "imx7.snvs"
76
+#endif
68
+#define IMX7_SNVS(obj) OBJECT_CHECK(IMX7SNVSState, (obj), TYPE_IMX7_SNVS)
77
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/timer/cadence_ttc.c
80
+++ b/hw/timer/cadence_ttc.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "qemu/timer.h"
83
#include "qom/object.h"
84
85
+#include "hw/timer/cadence_ttc.h"
69
+
86
+
70
+typedef struct IMX7SNVSState {
87
#ifdef CADENCE_TTC_ERR_DEBUG
71
+ /* <private> */
88
#define DB_PRINT(...) do { \
72
+ SysBusDevice parent_obj;
89
fprintf(stderr, ": %s: ", __func__); \
73
+
74
+ MemoryRegion mmio;
75
+} IMX7SNVSState;
76
+
77
+#endif /* IMX7_SNVS_H */
78
diff --git a/hw/misc/imx7_snvs.c b/hw/misc/imx7_snvs.c
79
new file mode 100644
80
index XXXXXXX..XXXXXXX
81
--- /dev/null
82
+++ b/hw/misc/imx7_snvs.c
83
@@ -XXX,XX +XXX,XX @@
90
@@ -XXX,XX +XXX,XX @@
84
+/*
91
#define CLOCK_CTRL_PS_EN 0x00000001
85
+ * IMX7 Secure Non-Volatile Storage
92
#define CLOCK_CTRL_PS_V 0x0000001e
86
+ *
93
87
+ * Copyright (c) 2018, Impinj, Inc.
94
-typedef struct {
88
+ *
95
- QEMUTimer *timer;
89
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
96
- int freq;
90
+ *
97
-
91
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
98
- uint32_t reg_clock;
92
+ * See the COPYING file in the top-level directory.
99
- uint32_t reg_count;
93
+ *
100
- uint32_t reg_value;
94
+ * Bare minimum emulation code needed to support being able to shut
101
- uint16_t reg_interval;
95
+ * down linux guest gracefully.
102
- uint16_t reg_match[3];
96
+ */
103
- uint32_t reg_intr;
97
+
104
- uint32_t reg_intr_en;
98
+#include "qemu/osdep.h"
105
- uint32_t reg_event_ctrl;
99
+#include "hw/misc/imx7_snvs.h"
106
- uint32_t reg_event;
100
+#include "qemu/log.h"
107
-
101
+#include "sysemu/sysemu.h"
108
- uint64_t cpu_time;
102
+
109
- unsigned int cpu_time_valid;
103
+static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
110
-
104
+{
111
- qemu_irq irq;
105
+ return 0;
112
-} CadenceTimerState;
106
+}
113
-
107
+
114
-#define TYPE_CADENCE_TTC "cadence_ttc"
108
+static void imx7_snvs_write(void *opaque, hwaddr offset,
115
-OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
109
+ uint64_t v, unsigned size)
116
-
110
+{
117
-struct CadenceTTCState {
111
+ const uint32_t value = v;
118
- SysBusDevice parent_obj;
112
+ const uint32_t mask = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
119
-
113
+
120
- MemoryRegion iomem;
114
+ if (offset == SNVS_LPCR && ((value & mask) == mask)) {
121
- CadenceTimerState timer[3];
115
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
122
-};
116
+ }
123
-
117
+}
124
static void cadence_timer_update(CadenceTimerState *s)
118
+
125
{
119
+static const struct MemoryRegionOps imx7_snvs_ops = {
126
qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
120
+ .read = imx7_snvs_read,
121
+ .write = imx7_snvs_write,
122
+ .endianness = DEVICE_NATIVE_ENDIAN,
123
+ .impl = {
124
+ /*
125
+ * Our device would not work correctly if the guest was doing
126
+ * unaligned access. This might not be a limitation on the real
127
+ * device but in practice there is no reason for a guest to access
128
+ * this device unaligned.
129
+ */
130
+ .min_access_size = 4,
131
+ .max_access_size = 4,
132
+ .unaligned = false,
133
+ },
134
+};
135
+
136
+static void imx7_snvs_init(Object *obj)
137
+{
138
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
139
+ IMX7SNVSState *s = IMX7_SNVS(obj);
140
+
141
+ memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
142
+ TYPE_IMX7_SNVS, 0x1000);
143
+
144
+ sysbus_init_mmio(sd, &s->mmio);
145
+}
146
+
147
+static void imx7_snvs_class_init(ObjectClass *klass, void *data)
148
+{
149
+ DeviceClass *dc = DEVICE_CLASS(klass);
150
+
151
+ dc->desc = "i.MX7 Secure Non-Volatile Storage Module";
152
+}
153
+
154
+static const TypeInfo imx7_snvs_info = {
155
+ .name = TYPE_IMX7_SNVS,
156
+ .parent = TYPE_SYS_BUS_DEVICE,
157
+ .instance_size = sizeof(IMX7SNVSState),
158
+ .instance_init = imx7_snvs_init,
159
+ .class_init = imx7_snvs_class_init,
160
+};
161
+
162
+static void imx7_snvs_register_type(void)
163
+{
164
+ type_register_static(&imx7_snvs_info);
165
+}
166
+type_init(imx7_snvs_register_type)
167
--
127
--
168
2.16.1
128
2.25.1
169
170
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Add minimal code needed to allow upstream Linux guest to boot.
3
Connect the 4 TTC timers on the ZynqMP.
4
4
5
Cc: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Cc: Jason Wang <jasowang@redhat.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Cc: Michael S. Tsirkin <mst@redhat.com>
9
Message-id: 20220331222017.2914409-3-edgar.iglesias@gmail.com
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
11
---
18
include/hw/timer/imx_gpt.h | 1 +
12
include/hw/arm/xlnx-zynqmp.h | 4 ++++
19
hw/timer/imx_gpt.c | 25 +++++++++++++++++++++++++
13
hw/arm/xlnx-zynqmp.c | 22 ++++++++++++++++++++++
20
2 files changed, 26 insertions(+)
14
2 files changed, 26 insertions(+)
21
15
22
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/timer/imx_gpt.h
18
--- a/include/hw/arm/xlnx-zynqmp.h
25
+++ b/include/hw/timer/imx_gpt.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
26
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
27
#define TYPE_IMX25_GPT "imx25.gpt"
21
#include "hw/or-irq.h"
28
#define TYPE_IMX31_GPT "imx31.gpt"
22
#include "hw/misc/xlnx-zynqmp-apu-ctrl.h"
29
#define TYPE_IMX6_GPT "imx6.gpt"
23
#include "hw/misc/xlnx-zynqmp-crf.h"
30
+#define TYPE_IMX7_GPT "imx7.gpt"
24
+#include "hw/timer/cadence_ttc.h"
31
25
32
#define TYPE_IMX_GPT TYPE_IMX25_GPT
26
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
33
27
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
34
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
29
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
30
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
31
32
+#define XLNX_ZYNQMP_NUM_TTC 4
33
+
34
/*
35
* Unimplemented mmio regions needed to boot some images.
36
*/
37
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
38
qemu_or_irq qspi_irq_orgate;
39
XlnxZynqMPAPUCtrl apu_ctrl;
40
XlnxZynqMPCRF crf;
41
+ CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC];
42
43
char *boot_cpu;
44
ARMCPU *boot_cpu_ptr;
45
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
35
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/timer/imx_gpt.c
47
--- a/hw/arm/xlnx-zynqmp.c
37
+++ b/hw/timer/imx_gpt.c
48
+++ b/hw/arm/xlnx-zynqmp.c
38
@@ -XXX,XX +XXX,XX @@ static const IMXClk imx6_gpt_clocks[] = {
49
@@ -XXX,XX +XXX,XX @@
39
CLK_HIGH, /* 111 reference clock */
50
#define APU_ADDR 0xfd5c0000
40
};
51
#define APU_IRQ 153
41
52
42
+static const IMXClk imx7_gpt_clocks[] = {
53
+#define TTC0_ADDR 0xFF110000
43
+ CLK_NONE, /* 000 No clock source */
54
+#define TTC0_IRQ 36
44
+ CLK_IPG, /* 001 ipg_clk, 532MHz*/
45
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
46
+ CLK_EXT, /* 011 External clock */
47
+ CLK_32k, /* 100 ipg_clk_32k */
48
+ CLK_HIGH, /* 101 reference clock */
49
+ CLK_NONE, /* 110 not defined */
50
+ CLK_NONE, /* 111 not defined */
51
+};
52
+
55
+
53
static void imx_gpt_set_freq(IMXGPTState *s)
56
#define IPI_ADDR 0xFF300000
54
{
57
#define IPI_IRQ 64
55
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
58
56
@@ -XXX,XX +XXX,XX @@ static void imx6_gpt_init(Object *obj)
59
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_crf(XlnxZynqMPState *s, qemu_irq *gic)
57
s->clocks = imx6_gpt_clocks;
60
sysbus_connect_irq(sbd, 0, gic[CRF_IRQ]);
58
}
61
}
59
62
60
+static void imx7_gpt_init(Object *obj)
63
+static void xlnx_zynqmp_create_ttc(XlnxZynqMPState *s, qemu_irq *gic)
61
+{
64
+{
62
+ IMXGPTState *s = IMX_GPT(obj);
65
+ SysBusDevice *sbd;
66
+ int i, irq;
63
+
67
+
64
+ s->clocks = imx7_gpt_clocks;
68
+ for (i = 0; i < XLNX_ZYNQMP_NUM_TTC; i++) {
69
+ object_initialize_child(OBJECT(s), "ttc[*]", &s->ttc[i],
70
+ TYPE_CADENCE_TTC);
71
+ sbd = SYS_BUS_DEVICE(&s->ttc[i]);
72
+
73
+ sysbus_realize(sbd, &error_fatal);
74
+ sysbus_mmio_map(sbd, 0, TTC0_ADDR + i * 0x10000);
75
+ for (irq = 0; irq < 3; irq++) {
76
+ sysbus_connect_irq(sbd, irq, gic[TTC0_IRQ + i * 3 + irq]);
77
+ }
78
+ }
65
+}
79
+}
66
+
80
+
67
static const TypeInfo imx25_gpt_info = {
81
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
68
.name = TYPE_IMX25_GPT,
69
.parent = TYPE_SYS_BUS_DEVICE,
70
@@ -XXX,XX +XXX,XX @@ static const TypeInfo imx6_gpt_info = {
71
.instance_init = imx6_gpt_init,
72
};
73
74
+static const TypeInfo imx7_gpt_info = {
75
+ .name = TYPE_IMX7_GPT,
76
+ .parent = TYPE_IMX25_GPT,
77
+ .instance_init = imx7_gpt_init,
78
+};
79
+
80
static void imx_gpt_register_types(void)
81
{
82
{
82
type_register_static(&imx25_gpt_info);
83
static const struct UnimpInfo {
83
type_register_static(&imx31_gpt_info);
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
84
type_register_static(&imx6_gpt_info);
85
xlnx_zynqmp_create_efuse(s, gic_spi);
85
+ type_register_static(&imx7_gpt_info);
86
xlnx_zynqmp_create_apu_ctrl(s, gic_spi);
86
}
87
xlnx_zynqmp_create_crf(s, gic_spi);
87
88
+ xlnx_zynqmp_create_ttc(s, gic_spi);
88
type_init(imx_gpt_register_types)
89
xlnx_zynqmp_create_unimp_mmio(s);
90
91
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
89
--
92
--
90
2.16.1
93
2.25.1
91
92
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Change vfp.regs as a uint64_t to vfp.zregs as an ARMVectorReg.
3
Create an APU CPU Cluster. This is in preparation to add the RPU.
4
The previous patches have made the change in representation
5
relatively painless.
6
4
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220406174303.2022038-2-edgar.iglesias@xilinx.com
10
Message-id: 20180123035349.24538-2-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
target/arm/cpu.h | 59 +++++++++++++++++++++++++++++++---------------
10
include/hw/arm/xlnx-versal.h | 2 ++
14
target/arm/machine.c | 35 ++++++++++++++++++++++++++-
11
hw/arm/xlnx-versal.c | 9 ++++++++-
15
target/arm/translate-a64.c | 8 +++----
12
2 files changed, 10 insertions(+), 1 deletion(-)
16
target/arm/translate.c | 7 +++---
17
4 files changed, 81 insertions(+), 28 deletions(-)
18
13
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
16
--- a/include/hw/arm/xlnx-versal.h
22
+++ b/target/arm/cpu.h
17
+++ b/include/hw/arm/xlnx-versal.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
@@ -XXX,XX +XXX,XX @@
24
uint32_t base_mask;
19
25
} TCR;
20
#include "hw/sysbus.h"
26
21
#include "hw/arm/boot.h"
27
+/* Define a maximum sized vector register.
22
+#include "hw/cpu/cluster.h"
28
+ * For 32-bit, this is a 128-bit NEON/AdvSIMD register.
23
#include "hw/or-irq.h"
29
+ * For 64-bit, this is a 2048-bit SVE register.
24
#include "hw/sd/sdhci.h"
30
+ *
25
#include "hw/intc/arm_gicv3.h"
31
+ * Note that the mapping between S, D, and Q views of the register bank
26
@@ -XXX,XX +XXX,XX @@ struct Versal {
32
+ * differs between AArch64 and AArch32.
27
struct {
33
+ * In AArch32:
28
struct {
34
+ * Qn = regs[n].d[1]:regs[n].d[0]
29
MemoryRegion mr;
35
+ * Dn = regs[n / 2].d[n & 1]
30
+ CPUClusterState cluster;
36
+ * Sn = regs[n / 4].d[n % 4 / 2],
31
ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
37
+ * bits 31..0 for even n, and bits 63..32 for odd n
32
GICv3State gic;
38
+ * (and regs[16] to regs[31] are inaccessible)
33
} apu;
39
+ * In AArch64:
34
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
40
+ * Zn = regs[n].d[*]
35
index XXXXXXX..XXXXXXX 100644
41
+ * Qn = regs[n].d[1]:regs[n].d[0]
36
--- a/hw/arm/xlnx-versal.c
42
+ * Dn = regs[n].d[0]
37
+++ b/hw/arm/xlnx-versal.c
43
+ * Sn = regs[n].d[0] bits 31..0
38
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
44
+ *
39
{
45
+ * This corresponds to the architecturally defined mapping between
40
int i;
46
+ * the two execution states, and means we do not need to explicitly
41
47
+ * map these registers when changing states.
42
+ object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
48
+ *
43
+ TYPE_CPU_CLUSTER);
49
+ * Align the data for use with TCG host vector operations.
44
+ qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
50
+ */
51
+
45
+
52
+#ifdef TARGET_AARCH64
46
for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
53
+# define ARM_MAX_VQ 16
47
Object *obj;
54
+#else
48
55
+# define ARM_MAX_VQ 1
49
- object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
56
+#endif
50
+ object_initialize_child(OBJECT(&s->fpd.apu.cluster),
51
+ "apu-cpu[*]", &s->fpd.apu.cpu[i],
52
XLNX_VERSAL_ACPU_TYPE);
53
obj = OBJECT(&s->fpd.apu.cpu[i]);
54
if (i) {
55
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
56
&error_abort);
57
qdev_realize(DEVICE(obj), NULL, &error_fatal);
58
}
57
+
59
+
58
+typedef struct ARMVectorReg {
60
+ qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
59
+ uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
60
+} ARMVectorReg;
61
+
62
+
63
typedef struct CPUARMState {
64
/* Regs for current mode. */
65
uint32_t regs[16];
66
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
67
68
/* VFP coprocessor state. */
69
struct {
70
- /* VFP/Neon register state. Note that the mapping between S, D and Q
71
- * views of the register bank differs between AArch64 and AArch32:
72
- * In AArch32:
73
- * Qn = regs[2n+1]:regs[2n]
74
- * Dn = regs[n]
75
- * Sn = regs[n/2] bits 31..0 for even n, and bits 63..32 for odd n
76
- * (and regs[32] to regs[63] are inaccessible)
77
- * In AArch64:
78
- * Qn = regs[2n+1]:regs[2n]
79
- * Dn = regs[2n]
80
- * Sn = regs[2n] bits 31..0
81
- * This corresponds to the architecturally defined mapping between
82
- * the two execution states, and means we do not need to explicitly
83
- * map these registers when changing states.
84
- */
85
- uint64_t regs[64] QEMU_ALIGNED(16);
86
+ ARMVectorReg zregs[32];
87
88
uint32_t xregs[16];
89
/* We store these fpcsr fields separately for convenience. */
90
@@ -XXX,XX +XXX,XX @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU *cpu)
91
*/
92
static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
93
{
94
- return &env->vfp.regs[regno];
95
+ return &env->vfp.zregs[regno >> 1].d[regno & 1];
96
}
61
}
97
62
98
/**
63
static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
99
@@ -XXX,XX +XXX,XX @@ static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
100
*/
101
static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
102
{
103
- return &env->vfp.regs[2 * regno];
104
+ return &env->vfp.zregs[regno].d[0];
105
}
106
107
/**
108
@@ -XXX,XX +XXX,XX @@ static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
109
*/
110
static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
111
{
112
- return &env->vfp.regs[2 * regno];
113
+ return &env->vfp.zregs[regno].d[0];
114
}
115
116
#endif
117
diff --git a/target/arm/machine.c b/target/arm/machine.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/machine.c
120
+++ b/target/arm/machine.c
121
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_vfp = {
122
.minimum_version_id = 3,
123
.needed = vfp_needed,
124
.fields = (VMStateField[]) {
125
- VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64),
126
+ /* For compatibility, store Qn out of Zn here. */
127
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[0].d, ARMCPU, 0, 2),
128
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[1].d, ARMCPU, 0, 2),
129
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[2].d, ARMCPU, 0, 2),
130
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[3].d, ARMCPU, 0, 2),
131
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[4].d, ARMCPU, 0, 2),
132
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[5].d, ARMCPU, 0, 2),
133
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[6].d, ARMCPU, 0, 2),
134
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[7].d, ARMCPU, 0, 2),
135
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[8].d, ARMCPU, 0, 2),
136
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[9].d, ARMCPU, 0, 2),
137
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[10].d, ARMCPU, 0, 2),
138
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[11].d, ARMCPU, 0, 2),
139
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[12].d, ARMCPU, 0, 2),
140
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[13].d, ARMCPU, 0, 2),
141
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[14].d, ARMCPU, 0, 2),
142
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[15].d, ARMCPU, 0, 2),
143
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[16].d, ARMCPU, 0, 2),
144
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[17].d, ARMCPU, 0, 2),
145
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[18].d, ARMCPU, 0, 2),
146
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[19].d, ARMCPU, 0, 2),
147
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[20].d, ARMCPU, 0, 2),
148
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[21].d, ARMCPU, 0, 2),
149
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[22].d, ARMCPU, 0, 2),
150
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[23].d, ARMCPU, 0, 2),
151
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[24].d, ARMCPU, 0, 2),
152
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[25].d, ARMCPU, 0, 2),
153
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[26].d, ARMCPU, 0, 2),
154
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[27].d, ARMCPU, 0, 2),
155
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[28].d, ARMCPU, 0, 2),
156
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[29].d, ARMCPU, 0, 2),
157
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[30].d, ARMCPU, 0, 2),
158
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[31].d, ARMCPU, 0, 2),
159
+
160
/* The xregs array is a little awkward because element 1 (FPSCR)
161
* requires a specific accessor, so we have to split it up in
162
* the vmstate:
163
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/arm/translate-a64.c
166
+++ b/target/arm/translate-a64.c
167
@@ -XXX,XX +XXX,XX @@ static inline int vec_reg_offset(DisasContext *s, int regno,
168
{
169
int offs = 0;
170
#ifdef HOST_WORDS_BIGENDIAN
171
- /* This is complicated slightly because vfp.regs[2n] is
172
- * still the low half and vfp.regs[2n+1] the high half
173
+ /* This is complicated slightly because vfp.zregs[n].d[0] is
174
+ * still the low half and vfp.zregs[n].d[1] the high half
175
* of the 128 bit vector, even on big endian systems.
176
* Calculate the offset assuming a fully bigendian 128 bits,
177
* then XOR to account for the order of the two 64 bit halves.
178
@@ -XXX,XX +XXX,XX @@ static inline int vec_reg_offset(DisasContext *s, int regno,
179
#else
180
offs += element * (1 << size);
181
#endif
182
- offs += offsetof(CPUARMState, vfp.regs[regno * 2]);
183
+ offs += offsetof(CPUARMState, vfp.zregs[regno]);
184
assert_fp_access_checked(s);
185
return offs;
186
}
187
@@ -XXX,XX +XXX,XX @@ static inline int vec_reg_offset(DisasContext *s, int regno,
188
static inline int vec_full_reg_offset(DisasContext *s, int regno)
189
{
190
assert_fp_access_checked(s);
191
- return offsetof(CPUARMState, vfp.regs[regno * 2]);
192
+ return offsetof(CPUARMState, vfp.zregs[regno]);
193
}
194
195
/* Return a newly allocated pointer to the vector register. */
196
diff --git a/target/arm/translate.c b/target/arm/translate.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/target/arm/translate.c
199
+++ b/target/arm/translate.c
200
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
201
}
202
}
203
204
-static inline long
205
-vfp_reg_offset (int dp, int reg)
206
+static inline long vfp_reg_offset(bool dp, unsigned reg)
207
{
208
if (dp) {
209
- return offsetof(CPUARMState, vfp.regs[reg]);
210
+ return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
211
} else {
212
- long ofs = offsetof(CPUARMState, vfp.regs[reg >> 1]);
213
+ long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
214
if (reg & 1) {
215
ofs += offsetof(CPU_DoubleU, l.upper);
216
} else {
217
--
64
--
218
2.16.1
65
2.25.1
219
220
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Move virt's PSCI DT fixup code to arm/boot.c and set this fixup to
3
Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit)
4
happen automatically for every board that doesn't mark "psci-conduit"
4
subsystem.
5
as disabled. This way emulated boards other than "virt" that rely on
6
PSIC for SMP could benefit from that code.
7
5
8
Cc: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
9
Cc: Jason Wang <jasowang@redhat.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
10
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20220406174303.2022038-3-edgar.iglesias@xilinx.com
11
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
12
Cc: Michael S. Tsirkin <mst@redhat.com>
13
Cc: qemu-devel@nongnu.org
14
Cc: qemu-arm@nongnu.org
15
Cc: yurovsky@gmail.com
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
10
---
21
hw/arm/boot.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11
include/hw/arm/xlnx-versal.h | 10 ++++++++++
22
hw/arm/virt.c | 61 -------------------------------------------------------
12
hw/arm/xlnx-versal-virt.c | 6 +++---
23
2 files changed, 65 insertions(+), 61 deletions(-)
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++
14
3 files changed, 49 insertions(+), 3 deletions(-)
24
15
25
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
26
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/boot.c
18
--- a/include/hw/arm/xlnx-versal.h
28
+++ b/hw/arm/boot.c
19
+++ b/include/hw/arm/xlnx-versal.h
29
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info)
20
@@ -XXX,XX +XXX,XX @@
21
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
22
23
#define XLNX_VERSAL_NR_ACPUS 2
24
+#define XLNX_VERSAL_NR_RCPUS 2
25
#define XLNX_VERSAL_NR_UARTS 2
26
#define XLNX_VERSAL_NR_GEMS 2
27
#define XLNX_VERSAL_NR_ADMAS 8
28
@@ -XXX,XX +XXX,XX @@ struct Versal {
29
VersalUsb2 usb;
30
} iou;
31
32
+ /* Real-time Processing Unit. */
33
+ struct {
34
+ MemoryRegion mr;
35
+ MemoryRegion mr_ps_alias;
36
+
37
+ CPUClusterState cluster;
38
+ ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
39
+ } rpu;
40
+
41
struct {
42
qemu_or_irq irq_orgate;
43
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
44
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal-virt.c
47
+++ b/hw/arm/xlnx-versal-virt.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
49
50
mc->desc = "Xilinx Versal Virtual development board";
51
mc->init = versal_virt_init;
52
- mc->min_cpus = XLNX_VERSAL_NR_ACPUS;
53
- mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
54
- mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
55
+ mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
56
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
57
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
58
mc->no_cdrom = true;
59
mc->default_ram_id = "ddr";
60
}
61
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/xlnx-versal.c
64
+++ b/hw/arm/xlnx-versal.c
65
@@ -XXX,XX +XXX,XX @@
66
#include "hw/sysbus.h"
67
68
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
69
+#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
70
#define GEM_REVISION 0x40070106
71
72
#define VERSAL_NUM_PMC_APB_IRQS 3
73
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
30
}
74
}
31
}
75
}
32
76
33
+static void fdt_add_psci_node(void *fdt)
77
+static void versal_create_rpu_cpus(Versal *s)
34
+{
78
+{
35
+ uint32_t cpu_suspend_fn;
79
+ int i;
36
+ uint32_t cpu_off_fn;
37
+ uint32_t cpu_on_fn;
38
+ uint32_t migrate_fn;
39
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
40
+ const char *psci_method;
41
+ int64_t psci_conduit;
42
+
80
+
43
+ psci_conduit = object_property_get_int(OBJECT(armcpu),
81
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
44
+ "psci-conduit",
82
+ TYPE_CPU_CLUSTER);
45
+ &error_abort);
83
+ qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
46
+ switch (psci_conduit) {
84
+
47
+ case QEMU_PSCI_CONDUIT_DISABLED:
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
48
+ return;
86
+ Object *obj;
49
+ case QEMU_PSCI_CONDUIT_HVC:
87
+
50
+ psci_method = "hvc";
88
+ object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
51
+ break;
89
+ "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
52
+ case QEMU_PSCI_CONDUIT_SMC:
90
+ XLNX_VERSAL_RCPU_TYPE);
53
+ psci_method = "smc";
91
+ obj = OBJECT(&s->lpd.rpu.cpu[i]);
54
+ break;
92
+ object_property_set_bool(obj, "start-powered-off", true,
55
+ default:
93
+ &error_abort);
56
+ g_assert_not_reached();
94
+
95
+ object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort);
96
+ object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu),
97
+ &error_abort);
98
+ object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr),
99
+ &error_abort);
100
+ qdev_realize(DEVICE(obj), NULL, &error_fatal);
57
+ }
101
+ }
58
+
102
+
59
+ qemu_fdt_add_subnode(fdt, "/psci");
103
+ qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
60
+ if (armcpu->psci_version == 2) {
61
+ const char comp[] = "arm,psci-0.2\0arm,psci";
62
+ qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
63
+
64
+ cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
65
+ if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
66
+ cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
67
+ cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON;
68
+ migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE;
69
+ } else {
70
+ cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND;
71
+ cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON;
72
+ migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE;
73
+ }
74
+ } else {
75
+ qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
76
+
77
+ cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
78
+ cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
79
+ cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
80
+ migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE;
81
+ }
82
+
83
+ /* We adopt the PSCI spec's nomenclature, and use 'conduit' to refer
84
+ * to the instruction that should be used to invoke PSCI functions.
85
+ * However, the device tree binding uses 'method' instead, so that is
86
+ * what we should use here.
87
+ */
88
+ qemu_fdt_setprop_string(fdt, "/psci", "method", psci_method);
89
+
90
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
91
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
92
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn);
93
+ qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
94
+}
104
+}
95
+
105
+
96
/**
106
static void versal_create_uarts(Versal *s, qemu_irq *pic)
97
* load_dtb() - load a device tree binary image into memory
107
{
98
* @addr: the address to load the image at
108
int i;
99
@@ -XXX,XX +XXX,XX @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
109
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
100
}
110
101
}
111
versal_create_apu_cpus(s);
102
112
versal_create_apu_gic(s, pic);
103
+ fdt_add_psci_node(fdt);
113
+ versal_create_rpu_cpus(s);
104
+
114
versal_create_uarts(s, pic);
105
if (binfo->modify_dtb) {
115
versal_create_usbs(s, pic);
106
binfo->modify_dtb(binfo, fdt);
116
versal_create_gems(s, pic);
107
}
117
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
108
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
118
109
index XXXXXXX..XXXXXXX 100644
119
memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
110
--- a/hw/arm/virt.c
120
memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
111
+++ b/hw/arm/virt.c
121
+ memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
112
@@ -XXX,XX +XXX,XX @@ static void create_fdt(VirtMachineState *vms)
122
+ &s->lpd.rpu.mr_ps_alias, 0);
113
}
114
}
123
}
115
124
116
-static void fdt_add_psci_node(const VirtMachineState *vms)
125
static void versal_init(Object *obj)
117
-{
126
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
118
- uint32_t cpu_suspend_fn;
127
Versal *s = XLNX_VERSAL(obj);
119
- uint32_t cpu_off_fn;
128
120
- uint32_t cpu_on_fn;
129
memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
121
- uint32_t migrate_fn;
130
+ memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
122
- void *fdt = vms->fdt;
131
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
123
- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
132
+ memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
124
- const char *psci_method;
133
+ "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
125
-
134
}
126
- switch (vms->psci_conduit) {
135
127
- case QEMU_PSCI_CONDUIT_DISABLED:
136
static Property versal_properties[] = {
128
- return;
129
- case QEMU_PSCI_CONDUIT_HVC:
130
- psci_method = "hvc";
131
- break;
132
- case QEMU_PSCI_CONDUIT_SMC:
133
- psci_method = "smc";
134
- break;
135
- default:
136
- g_assert_not_reached();
137
- }
138
-
139
- qemu_fdt_add_subnode(fdt, "/psci");
140
- if (armcpu->psci_version == 2) {
141
- const char comp[] = "arm,psci-0.2\0arm,psci";
142
- qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
143
-
144
- cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
145
- if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
146
- cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
147
- cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON;
148
- migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE;
149
- } else {
150
- cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND;
151
- cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON;
152
- migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE;
153
- }
154
- } else {
155
- qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
156
-
157
- cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
158
- cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
159
- cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
160
- migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE;
161
- }
162
-
163
- /* We adopt the PSCI spec's nomenclature, and use 'conduit' to refer
164
- * to the instruction that should be used to invoke PSCI functions.
165
- * However, the device tree binding uses 'method' instead, so that is
166
- * what we should use here.
167
- */
168
- qemu_fdt_setprop_string(fdt, "/psci", "method", psci_method);
169
-
170
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
171
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
172
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn);
173
- qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
174
-}
175
-
176
static void fdt_add_timer_nodes(const VirtMachineState *vms)
177
{
178
/* On real hardware these interrupts are level-triggered.
179
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
180
}
181
fdt_add_timer_nodes(vms);
182
fdt_add_cpu_nodes(vms);
183
- fdt_add_psci_node(vms);
184
185
memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
186
machine->ram_size);
187
--
137
--
188
2.16.1
138
2.25.1
189
190
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Add minimal code needed to allow upstream Linux guest to boot.
3
Add a model of the Xilinx Versal CRL.
4
4
5
Cc: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Cc: Jason Wang <jasowang@redhat.com>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
7
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
8
Message-id: 20220406174303.2022038-4-edgar.iglesias@xilinx.com
9
Cc: Michael S. Tsirkin <mst@redhat.com>
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
hw/intc/Makefile.objs | 2 +-
11
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
18
include/hw/intc/imx_gpcv2.h | 22 ++++++++
12
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
19
hw/intc/imx_gpcv2.c | 125 ++++++++++++++++++++++++++++++++++++++++++++
13
hw/misc/meson.build | 1 +
20
3 files changed, 148 insertions(+), 1 deletion(-)
14
3 files changed, 657 insertions(+)
21
create mode 100644 include/hw/intc/imx_gpcv2.h
15
create mode 100644 include/hw/misc/xlnx-versal-crl.h
22
create mode 100644 hw/intc/imx_gpcv2.c
16
create mode 100644 hw/misc/xlnx-versal-crl.c
23
17
24
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
18
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/Makefile.objs
27
+++ b/hw/intc/Makefile.objs
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XILINX) += xilinx_intc.o
29
common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-pmu-iomod-intc.o
30
common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-ipi.o
31
common-obj-$(CONFIG_ETRAXFS) += etraxfs_pic.o
32
-common-obj-$(CONFIG_IMX) += imx_avic.o
33
+common-obj-$(CONFIG_IMX) += imx_avic.o imx_gpcv2.o
34
common-obj-$(CONFIG_LM32) += lm32_pic.o
35
common-obj-$(CONFIG_REALVIEW) += realview_gic.o
36
common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o
37
diff --git a/include/hw/intc/imx_gpcv2.h b/include/hw/intc/imx_gpcv2.h
38
new file mode 100644
19
new file mode 100644
39
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
40
--- /dev/null
21
--- /dev/null
41
+++ b/include/hw/intc/imx_gpcv2.h
22
+++ b/include/hw/misc/xlnx-versal-crl.h
42
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
43
+#ifndef IMX_GPCV2_H
24
+/*
44
+#define IMX_GPCV2_H
25
+ * QEMU model of the Clock-Reset-LPD (CRL).
26
+ *
27
+ * Copyright (c) 2022 Xilinx Inc.
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
29
+ *
30
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
31
+ */
32
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
33
+#define HW_MISC_XLNX_VERSAL_CRL_H
45
+
34
+
46
+#include "hw/sysbus.h"
35
+#include "hw/sysbus.h"
47
+
36
+#include "hw/register.h"
48
+enum IMXGPCv2Registers {
37
+#include "target/arm/cpu.h"
49
+ GPC_NUM = 0xE00 / sizeof(uint32_t),
38
+
39
+#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"
40
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
41
+
42
+REG32(ERR_CTRL, 0x0)
43
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
44
+REG32(IR_STATUS, 0x4)
45
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
46
+REG32(IR_MASK, 0x8)
47
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
48
+REG32(IR_ENABLE, 0xc)
49
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
50
+REG32(IR_DISABLE, 0x10)
51
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
52
+REG32(WPROT, 0x1c)
53
+ FIELD(WPROT, ACTIVE, 0, 1)
54
+REG32(PLL_CLK_OTHER_DMN, 0x20)
55
+ FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1)
56
+REG32(RPLL_CTRL, 0x40)
57
+ FIELD(RPLL_CTRL, POST_SRC, 24, 3)
58
+ FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
59
+ FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
60
+ FIELD(RPLL_CTRL, FBDIV, 8, 8)
61
+ FIELD(RPLL_CTRL, BYPASS, 3, 1)
62
+ FIELD(RPLL_CTRL, RESET, 0, 1)
63
+REG32(RPLL_CFG, 0x44)
64
+ FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
65
+ FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
66
+ FIELD(RPLL_CFG, LFHF, 10, 2)
67
+ FIELD(RPLL_CFG, CP, 5, 4)
68
+ FIELD(RPLL_CFG, RES, 0, 4)
69
+REG32(RPLL_FRAC_CFG, 0x48)
70
+ FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1)
71
+ FIELD(RPLL_FRAC_CFG, SEED, 22, 3)
72
+ FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1)
73
+ FIELD(RPLL_FRAC_CFG, ORDER, 18, 1)
74
+ FIELD(RPLL_FRAC_CFG, DATA, 0, 16)
75
+REG32(PLL_STATUS, 0x50)
76
+ FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
77
+ FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
78
+REG32(RPLL_TO_XPD_CTRL, 0x100)
79
+ FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1)
80
+ FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
81
+REG32(LPD_TOP_SWITCH_CTRL, 0x104)
82
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
83
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1)
84
+ FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
85
+ FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
86
+REG32(LPD_LSBUS_CTRL, 0x108)
87
+ FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1)
88
+ FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10)
89
+ FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3)
90
+REG32(CPU_R5_CTRL, 0x10c)
91
+ FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1)
92
+ FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1)
93
+ FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1)
94
+ FIELD(CPU_R5_CTRL, CLKACT, 25, 1)
95
+ FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10)
96
+ FIELD(CPU_R5_CTRL, SRCSEL, 0, 3)
97
+REG32(IOU_SWITCH_CTRL, 0x114)
98
+ FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1)
99
+ FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10)
100
+ FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3)
101
+REG32(GEM0_REF_CTRL, 0x118)
102
+ FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
103
+ FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
104
+ FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
105
+ FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
106
+ FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
107
+REG32(GEM1_REF_CTRL, 0x11c)
108
+ FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
109
+ FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
110
+ FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
111
+ FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
112
+ FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
113
+REG32(GEM_TSU_REF_CTRL, 0x120)
114
+ FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1)
115
+ FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10)
116
+ FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3)
117
+REG32(USB0_BUS_REF_CTRL, 0x124)
118
+ FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1)
119
+ FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10)
120
+ FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3)
121
+REG32(UART0_REF_CTRL, 0x128)
122
+ FIELD(UART0_REF_CTRL, CLKACT, 25, 1)
123
+ FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10)
124
+ FIELD(UART0_REF_CTRL, SRCSEL, 0, 3)
125
+REG32(UART1_REF_CTRL, 0x12c)
126
+ FIELD(UART1_REF_CTRL, CLKACT, 25, 1)
127
+ FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10)
128
+ FIELD(UART1_REF_CTRL, SRCSEL, 0, 3)
129
+REG32(SPI0_REF_CTRL, 0x130)
130
+ FIELD(SPI0_REF_CTRL, CLKACT, 25, 1)
131
+ FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10)
132
+ FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3)
133
+REG32(SPI1_REF_CTRL, 0x134)
134
+ FIELD(SPI1_REF_CTRL, CLKACT, 25, 1)
135
+ FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10)
136
+ FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3)
137
+REG32(CAN0_REF_CTRL, 0x138)
138
+ FIELD(CAN0_REF_CTRL, CLKACT, 25, 1)
139
+ FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10)
140
+ FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3)
141
+REG32(CAN1_REF_CTRL, 0x13c)
142
+ FIELD(CAN1_REF_CTRL, CLKACT, 25, 1)
143
+ FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10)
144
+ FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3)
145
+REG32(I2C0_REF_CTRL, 0x140)
146
+ FIELD(I2C0_REF_CTRL, CLKACT, 25, 1)
147
+ FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10)
148
+ FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3)
149
+REG32(I2C1_REF_CTRL, 0x144)
150
+ FIELD(I2C1_REF_CTRL, CLKACT, 25, 1)
151
+ FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10)
152
+ FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3)
153
+REG32(DBG_LPD_CTRL, 0x148)
154
+ FIELD(DBG_LPD_CTRL, CLKACT, 25, 1)
155
+ FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10)
156
+ FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3)
157
+REG32(TIMESTAMP_REF_CTRL, 0x14c)
158
+ FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
159
+ FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
160
+ FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
161
+REG32(CRL_SAFETY_CHK, 0x150)
162
+REG32(PSM_REF_CTRL, 0x154)
163
+ FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10)
164
+ FIELD(PSM_REF_CTRL, SRCSEL, 0, 3)
165
+REG32(DBG_TSTMP_CTRL, 0x158)
166
+ FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1)
167
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10)
168
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
169
+REG32(CPM_TOPSW_REF_CTRL, 0x15c)
170
+ FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1)
171
+ FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10)
172
+ FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3)
173
+REG32(USB3_DUAL_REF_CTRL, 0x160)
174
+ FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1)
175
+ FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10)
176
+ FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3)
177
+REG32(RST_CPU_R5, 0x300)
178
+ FIELD(RST_CPU_R5, RESET_PGE, 4, 1)
179
+ FIELD(RST_CPU_R5, RESET_AMBA, 2, 1)
180
+ FIELD(RST_CPU_R5, RESET_CPU1, 1, 1)
181
+ FIELD(RST_CPU_R5, RESET_CPU0, 0, 1)
182
+REG32(RST_ADMA, 0x304)
183
+ FIELD(RST_ADMA, RESET, 0, 1)
184
+REG32(RST_GEM0, 0x308)
185
+ FIELD(RST_GEM0, RESET, 0, 1)
186
+REG32(RST_GEM1, 0x30c)
187
+ FIELD(RST_GEM1, RESET, 0, 1)
188
+REG32(RST_SPARE, 0x310)
189
+ FIELD(RST_SPARE, RESET, 0, 1)
190
+REG32(RST_USB0, 0x314)
191
+ FIELD(RST_USB0, RESET, 0, 1)
192
+REG32(RST_UART0, 0x318)
193
+ FIELD(RST_UART0, RESET, 0, 1)
194
+REG32(RST_UART1, 0x31c)
195
+ FIELD(RST_UART1, RESET, 0, 1)
196
+REG32(RST_SPI0, 0x320)
197
+ FIELD(RST_SPI0, RESET, 0, 1)
198
+REG32(RST_SPI1, 0x324)
199
+ FIELD(RST_SPI1, RESET, 0, 1)
200
+REG32(RST_CAN0, 0x328)
201
+ FIELD(RST_CAN0, RESET, 0, 1)
202
+REG32(RST_CAN1, 0x32c)
203
+ FIELD(RST_CAN1, RESET, 0, 1)
204
+REG32(RST_I2C0, 0x330)
205
+ FIELD(RST_I2C0, RESET, 0, 1)
206
+REG32(RST_I2C1, 0x334)
207
+ FIELD(RST_I2C1, RESET, 0, 1)
208
+REG32(RST_DBG_LPD, 0x338)
209
+ FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1)
210
+ FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1)
211
+ FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1)
212
+ FIELD(RST_DBG_LPD, RESET, 0, 1)
213
+REG32(RST_GPIO, 0x33c)
214
+ FIELD(RST_GPIO, RESET, 0, 1)
215
+REG32(RST_TTC, 0x344)
216
+ FIELD(RST_TTC, TTC3_RESET, 3, 1)
217
+ FIELD(RST_TTC, TTC2_RESET, 2, 1)
218
+ FIELD(RST_TTC, TTC1_RESET, 1, 1)
219
+ FIELD(RST_TTC, TTC0_RESET, 0, 1)
220
+REG32(RST_TIMESTAMP, 0x348)
221
+ FIELD(RST_TIMESTAMP, RESET, 0, 1)
222
+REG32(RST_SWDT, 0x34c)
223
+ FIELD(RST_SWDT, RESET, 0, 1)
224
+REG32(RST_OCM, 0x350)
225
+ FIELD(RST_OCM, RESET, 0, 1)
226
+REG32(RST_IPI, 0x354)
227
+ FIELD(RST_IPI, RESET, 0, 1)
228
+REG32(RST_SYSMON, 0x358)
229
+ FIELD(RST_SYSMON, SEQ_RST, 1, 1)
230
+ FIELD(RST_SYSMON, CFG_RST, 0, 1)
231
+REG32(RST_FPD, 0x360)
232
+ FIELD(RST_FPD, SRST, 1, 1)
233
+ FIELD(RST_FPD, POR, 0, 1)
234
+REG32(PSM_RST_MODE, 0x370)
235
+ FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
236
+ FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
237
+
238
+#define CRL_R_MAX (R_PSM_RST_MODE + 1)
239
+
240
+#define RPU_MAX_CPU 2
241
+
242
+struct XlnxVersalCRL {
243
+ SysBusDevice parent_obj;
244
+ qemu_irq irq;
245
+
246
+ struct {
247
+ ARMCPU *cpu_r5[RPU_MAX_CPU];
248
+ DeviceState *adma[8];
249
+ DeviceState *uart[2];
250
+ DeviceState *gem[2];
251
+ DeviceState *usb;
252
+ } cfg;
253
+
254
+ RegisterInfoArray *reg_array;
255
+ uint32_t regs[CRL_R_MAX];
256
+ RegisterInfo regs_info[CRL_R_MAX];
50
+};
257
+};
51
+
258
+#endif
52
+typedef struct IMXGPCv2State {
259
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
53
+ /*< private >*/
54
+ SysBusDevice parent_obj;
55
+
56
+ /*< public >*/
57
+ MemoryRegion iomem;
58
+ uint32_t regs[GPC_NUM];
59
+} IMXGPCv2State;
60
+
61
+#define TYPE_IMX_GPCV2 "imx-gpcv2"
62
+#define IMX_GPCV2(obj) OBJECT_CHECK(IMXGPCv2State, (obj), TYPE_IMX_GPCV2)
63
+
64
+#endif /* IMX_GPCV2_H */
65
diff --git a/hw/intc/imx_gpcv2.c b/hw/intc/imx_gpcv2.c
66
new file mode 100644
260
new file mode 100644
67
index XXXXXXX..XXXXXXX
261
index XXXXXXX..XXXXXXX
68
--- /dev/null
262
--- /dev/null
69
+++ b/hw/intc/imx_gpcv2.c
263
+++ b/hw/misc/xlnx-versal-crl.c
70
@@ -XXX,XX +XXX,XX @@
264
@@ -XXX,XX +XXX,XX @@
71
+/*
265
+/*
72
+ * Copyright (c) 2018, Impinj, Inc.
266
+ * QEMU model of the Clock-Reset-LPD (CRL).
73
+ *
267
+ *
74
+ * i.MX7 GPCv2 block emulation code
268
+ * Copyright (c) 2022 Advanced Micro Devices, Inc.
269
+ * SPDX-License-Identifier: GPL-2.0-or-later
75
+ *
270
+ *
76
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
271
+ * Written by Edgar E. Iglesias <edgar.iglesias@amd.com>
77
+ *
78
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
79
+ * See the COPYING file in the top-level directory.
80
+ */
272
+ */
81
+
273
+
82
+#include "qemu/osdep.h"
274
+#include "qemu/osdep.h"
83
+#include "hw/intc/imx_gpcv2.h"
275
+#include "qapi/error.h"
84
+#include "qemu/log.h"
276
+#include "qemu/log.h"
85
+
277
+#include "qemu/bitops.h"
86
+#define GPC_PU_PGC_SW_PUP_REQ 0x0f8
278
+#include "migration/vmstate.h"
87
+#define GPC_PU_PGC_SW_PDN_REQ 0x104
279
+#include "hw/qdev-properties.h"
88
+
280
+#include "hw/sysbus.h"
89
+#define USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
281
+#include "hw/irq.h"
90
+#define USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
282
+#include "hw/register.h"
91
+#define USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
283
+#include "hw/resettable.h"
92
+#define PCIE_PHY_SW_Pxx_REQ BIT(1)
284
+
93
+#define MIPI_PHY_SW_Pxx_REQ BIT(0)
285
+#include "target/arm/arm-powerctl.h"
94
+
286
+#include "hw/misc/xlnx-versal-crl.h"
95
+
287
+
96
+static void imx_gpcv2_reset(DeviceState *dev)
288
+#ifndef XLNX_VERSAL_CRL_ERR_DEBUG
97
+{
289
+#define XLNX_VERSAL_CRL_ERR_DEBUG 0
98
+ IMXGPCv2State *s = IMX_GPCV2(dev);
290
+#endif
99
+
291
+
100
+ memset(s->regs, 0, sizeof(s->regs));
292
+static void crl_update_irq(XlnxVersalCRL *s)
101
+}
293
+{
102
+
294
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
103
+static uint64_t imx_gpcv2_read(void *opaque, hwaddr offset,
295
+ qemu_set_irq(s->irq, pending);
104
+ unsigned size)
296
+}
105
+{
297
+
106
+ IMXGPCv2State *s = opaque;
298
+static void crl_status_postw(RegisterInfo *reg, uint64_t val64)
107
+
299
+{
108
+ return s->regs[offset / sizeof(uint32_t)];
300
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
109
+}
301
+ crl_update_irq(s);
110
+
302
+}
111
+static void imx_gpcv2_write(void *opaque, hwaddr offset,
303
+
112
+ uint64_t value, unsigned size)
304
+static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64)
113
+{
305
+{
114
+ IMXGPCv2State *s = opaque;
306
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
115
+ const size_t idx = offset / sizeof(uint32_t);
307
+ uint32_t val = val64;
116
+
308
+
117
+ s->regs[idx] = value;
309
+ s->regs[R_IR_MASK] &= ~val;
118
+
310
+ crl_update_irq(s);
119
+ /*
311
+ return 0;
120
+ * Real HW will clear those bits once as a way to indicate that
312
+}
121
+ * power up request is complete
313
+
122
+ */
314
+static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
123
+ if (offset == GPC_PU_PGC_SW_PUP_REQ ||
315
+{
124
+ offset == GPC_PU_PGC_SW_PDN_REQ) {
316
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
125
+ s->regs[idx] &= ~(USB_HSIC_PHY_SW_Pxx_REQ |
317
+ uint32_t val = val64;
126
+ USB_OTG2_PHY_SW_Pxx_REQ |
318
+
127
+ USB_OTG1_PHY_SW_Pxx_REQ |
319
+ s->regs[R_IR_MASK] |= val;
128
+ PCIE_PHY_SW_Pxx_REQ |
320
+ crl_update_irq(s);
129
+ MIPI_PHY_SW_Pxx_REQ);
321
+ return 0;
130
+ }
322
+}
131
+}
323
+
132
+
324
+static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev,
133
+static const struct MemoryRegionOps imx_gpcv2_ops = {
325
+ bool rst_old, bool rst_new)
134
+ .read = imx_gpcv2_read,
326
+{
135
+ .write = imx_gpcv2_write,
327
+ device_cold_reset(dev);
136
+ .endianness = DEVICE_NATIVE_ENDIAN,
328
+}
137
+ .impl = {
329
+
138
+ /*
330
+static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu,
139
+ * Our device would not work correctly if the guest was doing
331
+ bool rst_old, bool rst_new)
140
+ * unaligned access. This might not be a limitation on the real
332
+{
141
+ * device but in practice there is no reason for a guest to access
333
+ if (rst_new) {
142
+ * this device unaligned.
334
+ arm_set_cpu_off(armcpu->mp_affinity);
143
+ */
335
+ } else {
336
+ arm_set_cpu_on_and_reset(armcpu->mp_affinity);
337
+ }
338
+}
339
+
340
+#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \
341
+ bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \
342
+ bool new_f = FIELD_EX32(new_val, reg, f); \
343
+ \
344
+ /* Detect edges. */ \
345
+ if (dev && old_f != new_f) { \
346
+ crl_reset_ ## type(s, dev, old_f, new_f); \
347
+ } \
348
+}
349
+
350
+static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
351
+{
352
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
353
+
354
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
355
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
356
+ return val64;
357
+}
358
+
359
+static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
360
+{
361
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
362
+ int i;
363
+
364
+ /* A single register fans out to all ADMA reset inputs. */
365
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
366
+ REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
367
+ }
368
+ return val64;
369
+}
370
+
371
+static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
372
+{
373
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
374
+
375
+ REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
376
+ return val64;
377
+}
378
+
379
+static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
380
+{
381
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
382
+
383
+ REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
384
+ return val64;
385
+}
386
+
387
+static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
388
+{
389
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
390
+
391
+ REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
392
+ return val64;
393
+}
394
+
395
+static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
396
+{
397
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
398
+
399
+ REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
400
+ return val64;
401
+}
402
+
403
+static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
404
+{
405
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
406
+
407
+ REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
408
+ return val64;
409
+}
410
+
411
+static const RegisterAccessInfo crl_regs_info[] = {
412
+ { .name = "ERR_CTRL", .addr = A_ERR_CTRL,
413
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
414
+ .w1c = 0x1,
415
+ .post_write = crl_status_postw,
416
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
417
+ .reset = 0x1,
418
+ .ro = 0x1,
419
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
420
+ .pre_write = crl_enable_prew,
421
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
422
+ .pre_write = crl_disable_prew,
423
+ },{ .name = "WPROT", .addr = A_WPROT,
424
+ },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN,
425
+ .reset = 0x1,
426
+ .rsvd = 0xe,
427
+ },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL,
428
+ .reset = 0x24809,
429
+ .rsvd = 0xf88c00f6,
430
+ },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG,
431
+ .reset = 0x2000000,
432
+ .rsvd = 0x1801210,
433
+ },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG,
434
+ .rsvd = 0x7e330000,
435
+ },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS,
436
+ .reset = R_PLL_STATUS_RPLL_STABLE_MASK |
437
+ R_PLL_STATUS_RPLL_LOCK_MASK,
438
+ .rsvd = 0xfa,
439
+ .ro = 0x5,
440
+ },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL,
441
+ .reset = 0x2000100,
442
+ .rsvd = 0xfdfc00ff,
443
+ },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL,
444
+ .reset = 0x6000300,
445
+ .rsvd = 0xf9fc00f8,
446
+ },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL,
447
+ .reset = 0x2000800,
448
+ .rsvd = 0xfdfc00f8,
449
+ },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL,
450
+ .reset = 0xe000300,
451
+ .rsvd = 0xe1fc00f8,
452
+ },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL,
453
+ .reset = 0x2000500,
454
+ .rsvd = 0xfdfc00f8,
455
+ },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL,
456
+ .reset = 0xe000a00,
457
+ .rsvd = 0xf1fc00f8,
458
+ },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL,
459
+ .reset = 0xe000a00,
460
+ .rsvd = 0xf1fc00f8,
461
+ },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL,
462
+ .reset = 0x300,
463
+ .rsvd = 0xfdfc00f8,
464
+ },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL,
465
+ .reset = 0x2001900,
466
+ .rsvd = 0xfdfc00f8,
467
+ },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL,
468
+ .reset = 0xc00,
469
+ .rsvd = 0xfdfc00f8,
470
+ },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL,
471
+ .reset = 0xc00,
472
+ .rsvd = 0xfdfc00f8,
473
+ },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL,
474
+ .reset = 0x600,
475
+ .rsvd = 0xfdfc00f8,
476
+ },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL,
477
+ .reset = 0x600,
478
+ .rsvd = 0xfdfc00f8,
479
+ },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL,
480
+ .reset = 0xc00,
481
+ .rsvd = 0xfdfc00f8,
482
+ },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL,
483
+ .reset = 0xc00,
484
+ .rsvd = 0xfdfc00f8,
485
+ },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL,
486
+ .reset = 0xc00,
487
+ .rsvd = 0xfdfc00f8,
488
+ },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL,
489
+ .reset = 0xc00,
490
+ .rsvd = 0xfdfc00f8,
491
+ },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL,
492
+ .reset = 0x300,
493
+ .rsvd = 0xfdfc00f8,
494
+ },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL,
495
+ .reset = 0x2000c00,
496
+ .rsvd = 0xfdfc00f8,
497
+ },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK,
498
+ },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL,
499
+ .reset = 0xf04,
500
+ .rsvd = 0xfffc00f8,
501
+ },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL,
502
+ .reset = 0x300,
503
+ .rsvd = 0xfdfc00f8,
504
+ },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL,
505
+ .reset = 0x300,
506
+ .rsvd = 0xfdfc00f8,
507
+ },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL,
508
+ .reset = 0x3c00,
509
+ .rsvd = 0xfdfc00f8,
510
+ },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5,
511
+ .reset = 0x17,
512
+ .rsvd = 0x8,
513
+ .pre_write = crl_rst_r5_prew,
514
+ },{ .name = "RST_ADMA", .addr = A_RST_ADMA,
515
+ .reset = 0x1,
516
+ .pre_write = crl_rst_adma_prew,
517
+ },{ .name = "RST_GEM0", .addr = A_RST_GEM0,
518
+ .reset = 0x1,
519
+ .pre_write = crl_rst_gem0_prew,
520
+ },{ .name = "RST_GEM1", .addr = A_RST_GEM1,
521
+ .reset = 0x1,
522
+ .pre_write = crl_rst_gem1_prew,
523
+ },{ .name = "RST_SPARE", .addr = A_RST_SPARE,
524
+ .reset = 0x1,
525
+ },{ .name = "RST_USB0", .addr = A_RST_USB0,
526
+ .reset = 0x1,
527
+ .pre_write = crl_rst_usb_prew,
528
+ },{ .name = "RST_UART0", .addr = A_RST_UART0,
529
+ .reset = 0x1,
530
+ .pre_write = crl_rst_uart0_prew,
531
+ },{ .name = "RST_UART1", .addr = A_RST_UART1,
532
+ .reset = 0x1,
533
+ .pre_write = crl_rst_uart1_prew,
534
+ },{ .name = "RST_SPI0", .addr = A_RST_SPI0,
535
+ .reset = 0x1,
536
+ },{ .name = "RST_SPI1", .addr = A_RST_SPI1,
537
+ .reset = 0x1,
538
+ },{ .name = "RST_CAN0", .addr = A_RST_CAN0,
539
+ .reset = 0x1,
540
+ },{ .name = "RST_CAN1", .addr = A_RST_CAN1,
541
+ .reset = 0x1,
542
+ },{ .name = "RST_I2C0", .addr = A_RST_I2C0,
543
+ .reset = 0x1,
544
+ },{ .name = "RST_I2C1", .addr = A_RST_I2C1,
545
+ .reset = 0x1,
546
+ },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD,
547
+ .reset = 0x33,
548
+ .rsvd = 0xcc,
549
+ },{ .name = "RST_GPIO", .addr = A_RST_GPIO,
550
+ .reset = 0x1,
551
+ },{ .name = "RST_TTC", .addr = A_RST_TTC,
552
+ .reset = 0xf,
553
+ },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP,
554
+ .reset = 0x1,
555
+ },{ .name = "RST_SWDT", .addr = A_RST_SWDT,
556
+ .reset = 0x1,
557
+ },{ .name = "RST_OCM", .addr = A_RST_OCM,
558
+ },{ .name = "RST_IPI", .addr = A_RST_IPI,
559
+ },{ .name = "RST_FPD", .addr = A_RST_FPD,
560
+ .reset = 0x3,
561
+ },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE,
562
+ .reset = 0x1,
563
+ .rsvd = 0xf8,
564
+ }
565
+};
566
+
567
+static void crl_reset_enter(Object *obj, ResetType type)
568
+{
569
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
570
+ unsigned int i;
571
+
572
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
573
+ register_reset(&s->regs_info[i]);
574
+ }
575
+}
576
+
577
+static void crl_reset_hold(Object *obj)
578
+{
579
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
580
+
581
+ crl_update_irq(s);
582
+}
583
+
584
+static const MemoryRegionOps crl_ops = {
585
+ .read = register_read_memory,
586
+ .write = register_write_memory,
587
+ .endianness = DEVICE_LITTLE_ENDIAN,
588
+ .valid = {
144
+ .min_access_size = 4,
589
+ .min_access_size = 4,
145
+ .max_access_size = 4,
590
+ .max_access_size = 4,
146
+ .unaligned = false,
147
+ },
591
+ },
148
+};
592
+};
149
+
593
+
150
+static void imx_gpcv2_init(Object *obj)
594
+static void crl_init(Object *obj)
151
+{
595
+{
152
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
596
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
153
+ IMXGPCv2State *s = IMX_GPCV2(obj);
597
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
154
+
598
+ int i;
155
+ memory_region_init_io(&s->iomem,
599
+
156
+ obj,
600
+ s->reg_array =
157
+ &imx_gpcv2_ops,
601
+ register_init_block32(DEVICE(obj), crl_regs_info,
158
+ s,
602
+ ARRAY_SIZE(crl_regs_info),
159
+ TYPE_IMX_GPCV2 ".iomem",
603
+ s->regs_info, s->regs,
160
+ sizeof(s->regs));
604
+ &crl_ops,
161
+ sysbus_init_mmio(sd, &s->iomem);
605
+ XLNX_VERSAL_CRL_ERR_DEBUG,
162
+}
606
+ CRL_R_MAX * 4);
163
+
607
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
164
+static const VMStateDescription vmstate_imx_gpcv2 = {
608
+ sysbus_init_irq(sbd, &s->irq);
165
+ .name = TYPE_IMX_GPCV2,
609
+
610
+ for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
611
+ object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
612
+ (Object **)&s->cfg.cpu_r5[i],
613
+ qdev_prop_allow_set_link_before_realize,
614
+ OBJ_PROP_LINK_STRONG);
615
+ }
616
+
617
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
618
+ object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
619
+ (Object **)&s->cfg.adma[i],
620
+ qdev_prop_allow_set_link_before_realize,
621
+ OBJ_PROP_LINK_STRONG);
622
+ }
623
+
624
+ for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
625
+ object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
626
+ (Object **)&s->cfg.uart[i],
627
+ qdev_prop_allow_set_link_before_realize,
628
+ OBJ_PROP_LINK_STRONG);
629
+ }
630
+
631
+ for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
632
+ object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
633
+ (Object **)&s->cfg.gem[i],
634
+ qdev_prop_allow_set_link_before_realize,
635
+ OBJ_PROP_LINK_STRONG);
636
+ }
637
+
638
+ object_property_add_link(obj, "usb", TYPE_DEVICE,
639
+ (Object **)&s->cfg.gem[i],
640
+ qdev_prop_allow_set_link_before_realize,
641
+ OBJ_PROP_LINK_STRONG);
642
+}
643
+
644
+static void crl_finalize(Object *obj)
645
+{
646
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
647
+ register_finalize_block(s->reg_array);
648
+}
649
+
650
+static const VMStateDescription vmstate_crl = {
651
+ .name = TYPE_XLNX_VERSAL_CRL,
166
+ .version_id = 1,
652
+ .version_id = 1,
167
+ .minimum_version_id = 1,
653
+ .minimum_version_id = 1,
168
+ .fields = (VMStateField[]) {
654
+ .fields = (VMStateField[]) {
169
+ VMSTATE_UINT32_ARRAY(regs, IMXGPCv2State, GPC_NUM),
655
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
170
+ VMSTATE_END_OF_LIST()
656
+ VMSTATE_END_OF_LIST(),
171
+ },
657
+ }
172
+};
658
+};
173
+
659
+
174
+static void imx_gpcv2_class_init(ObjectClass *klass, void *data)
660
+static void crl_class_init(ObjectClass *klass, void *data)
175
+{
661
+{
662
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
176
+ DeviceClass *dc = DEVICE_CLASS(klass);
663
+ DeviceClass *dc = DEVICE_CLASS(klass);
177
+
664
+
178
+ dc->reset = imx_gpcv2_reset;
665
+ dc->vmsd = &vmstate_crl;
179
+ dc->vmsd = &vmstate_imx_gpcv2;
666
+
180
+ dc->desc = "i.MX GPCv2 Module";
667
+ rc->phases.enter = crl_reset_enter;
181
+}
668
+ rc->phases.hold = crl_reset_hold;
182
+
669
+}
183
+static const TypeInfo imx_gpcv2_info = {
670
+
184
+ .name = TYPE_IMX_GPCV2,
671
+static const TypeInfo crl_info = {
672
+ .name = TYPE_XLNX_VERSAL_CRL,
185
+ .parent = TYPE_SYS_BUS_DEVICE,
673
+ .parent = TYPE_SYS_BUS_DEVICE,
186
+ .instance_size = sizeof(IMXGPCv2State),
674
+ .instance_size = sizeof(XlnxVersalCRL),
187
+ .instance_init = imx_gpcv2_init,
675
+ .class_init = crl_class_init,
188
+ .class_init = imx_gpcv2_class_init,
676
+ .instance_init = crl_init,
677
+ .instance_finalize = crl_finalize,
189
+};
678
+};
190
+
679
+
191
+static void imx_gpcv2_register_type(void)
680
+static void crl_register_types(void)
192
+{
681
+{
193
+ type_register_static(&imx_gpcv2_info);
682
+ type_register_static(&crl_info);
194
+}
683
+}
195
+type_init(imx_gpcv2_register_type)
684
+
685
+type_init(crl_register_types)
686
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
687
index XXXXXXX..XXXXXXX 100644
688
--- a/hw/misc/meson.build
689
+++ b/hw/misc/meson.build
690
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
691
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
692
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c'))
693
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c'))
694
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
695
softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
696
'xlnx-versal-xramc.c',
697
'xlnx-versal-pmc-iou-slcr.c',
196
--
698
--
197
2.16.1
699
2.25.1
198
199
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
This implements emulation of the new SHA-3 instructions that have
3
Connect the CRL (Clock Reset LPD) to the Versal SoC.
4
been added as an optional extensions to the ARMv8 Crypto Extensions
5
in ARM v8.2.
6
4
7
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
8
Message-id: 20180207111729.15737-3-ard.biesheuvel@linaro.org
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-5-edgar.iglesias@xilinx.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/cpu.h | 1 +
11
include/hw/arm/xlnx-versal.h | 4 +++
13
target/arm/translate-a64.c | 148 +++++++++++++++++++++++++++++++++++++++++++--
12
hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++--
14
2 files changed, 145 insertions(+), 4 deletions(-)
13
2 files changed, 56 insertions(+), 2 deletions(-)
15
14
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
17
--- a/include/hw/arm/xlnx-versal.h
19
+++ b/target/arm/cpu.h
18
+++ b/include/hw/arm/xlnx-versal.h
20
@@ -XXX,XX +XXX,XX @@ enum arm_features {
19
@@ -XXX,XX +XXX,XX @@
21
ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
20
#include "hw/nvram/xlnx-versal-efuse.h"
22
ARM_FEATURE_SVE, /* has Scalable Vector Extension */
21
#include "hw/ssi/xlnx-versal-ospi.h"
23
ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
22
#include "hw/dma/xlnx_csu_dma.h"
24
+ ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
23
+#include "hw/misc/xlnx-versal-crl.h"
25
};
24
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
26
25
27
static inline int arm_feature(CPUARMState *env, int feature)
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
28
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
27
@@ -XXX,XX +XXX,XX @@ struct Versal {
28
qemu_or_irq irq_orgate;
29
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
30
} xram;
31
+
32
+ XlnxVersalCRL crl;
33
} lpd;
34
35
/* The Platform Management Controller subsystem. */
36
@@ -XXX,XX +XXX,XX @@ struct Versal {
37
#define VERSAL_TIMER_NS_EL1_IRQ 14
38
#define VERSAL_TIMER_NS_EL2_IRQ 10
39
40
+#define VERSAL_CRL_IRQ 10
41
#define VERSAL_UART0_IRQ_0 18
42
#define VERSAL_UART1_IRQ_0 19
43
#define VERSAL_USB0_IRQ_0 22
44
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
29
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-a64.c
46
--- a/hw/arm/xlnx-versal.c
31
+++ b/target/arm/translate-a64.c
47
+++ b/hw/arm/xlnx-versal.c
32
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
48
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
33
feature = ARM_FEATURE_V8_SHA512;
49
qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
34
genfn = gen_helper_crypto_sha512su1;
50
}
35
break;
51
36
- default:
52
+static void versal_create_crl(Versal *s, qemu_irq *pic)
37
- unallocated_encoding(s);
53
+{
38
- return;
54
+ SysBusDevice *sbd;
39
+ case 3: /* RAX1 */
55
+ int i;
40
+ feature = ARM_FEATURE_V8_SHA3;
41
+ genfn = NULL;
42
+ break;
43
}
44
} else {
45
unallocated_encoding(s);
46
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
47
tcg_temp_free_ptr(tcg_rn_ptr);
48
tcg_temp_free_ptr(tcg_rm_ptr);
49
} else {
50
- g_assert_not_reached();
51
+ TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
52
+ int pass;
53
+
56
+
54
+ tcg_op1 = tcg_temp_new_i64();
57
+ object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
55
+ tcg_op2 = tcg_temp_new_i64();
58
+ TYPE_XLNX_VERSAL_CRL);
56
+ tcg_res[0] = tcg_temp_new_i64();
59
+ sbd = SYS_BUS_DEVICE(&s->lpd.crl);
57
+ tcg_res[1] = tcg_temp_new_i64();
58
+
60
+
59
+ for (pass = 0; pass < 2; pass++) {
61
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
60
+ read_vec_element(s, tcg_op1, rn, pass, MO_64);
62
+ g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i);
61
+ read_vec_element(s, tcg_op2, rm, pass, MO_64);
62
+
63
+
63
+ tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
64
+ object_property_set_link(OBJECT(&s->lpd.crl),
64
+ tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
65
+ name, OBJECT(&s->lpd.rpu.cpu[i]),
65
+ }
66
+ &error_abort);
66
+ write_vec_element(s, tcg_res[0], rd, 0, MO_64);
67
+ write_vec_element(s, tcg_res[1], rd, 1, MO_64);
68
+
69
+ tcg_temp_free_i64(tcg_op1);
70
+ tcg_temp_free_i64(tcg_op2);
71
+ tcg_temp_free_i64(tcg_res[0]);
72
+ tcg_temp_free_i64(tcg_res[1]);
73
}
74
}
75
76
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
77
tcg_temp_free_ptr(tcg_rn_ptr);
78
}
79
80
+/* Crypto four-register
81
+ * 31 23 22 21 20 16 15 14 10 9 5 4 0
82
+ * +-------------------+-----+------+---+------+------+------+
83
+ * | 1 1 0 0 1 1 1 0 0 | Op0 | Rm | 0 | Ra | Rn | Rd |
84
+ * +-------------------+-----+------+---+------+------+------+
85
+ */
86
+static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
87
+{
88
+ int op0 = extract32(insn, 21, 2);
89
+ int rm = extract32(insn, 16, 5);
90
+ int ra = extract32(insn, 10, 5);
91
+ int rn = extract32(insn, 5, 5);
92
+ int rd = extract32(insn, 0, 5);
93
+ int feature;
94
+
95
+ switch (op0) {
96
+ case 0: /* EOR3 */
97
+ case 1: /* BCAX */
98
+ feature = ARM_FEATURE_V8_SHA3;
99
+ break;
100
+ default:
101
+ unallocated_encoding(s);
102
+ return;
103
+ }
67
+ }
104
+
68
+
105
+ if (!arm_dc_feature(s, feature)) {
69
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
106
+ unallocated_encoding(s);
70
+ g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
107
+ return;
71
+
72
+ object_property_set_link(OBJECT(&s->lpd.crl),
73
+ name, OBJECT(&s->lpd.iou.gem[i]),
74
+ &error_abort);
108
+ }
75
+ }
109
+
76
+
110
+ if (!fp_access_check(s)) {
77
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
111
+ return;
78
+ g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
79
+
80
+ object_property_set_link(OBJECT(&s->lpd.crl),
81
+ name, OBJECT(&s->lpd.iou.adma[i]),
82
+ &error_abort);
112
+ }
83
+ }
113
+
84
+
114
+ if (op0 < 2) {
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
115
+ TCGv_i64 tcg_op1, tcg_op2, tcg_op3, tcg_res[2];
86
+ g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
116
+ int pass;
117
+
87
+
118
+ tcg_op1 = tcg_temp_new_i64();
88
+ object_property_set_link(OBJECT(&s->lpd.crl),
119
+ tcg_op2 = tcg_temp_new_i64();
89
+ name, OBJECT(&s->lpd.iou.uart[i]),
120
+ tcg_op3 = tcg_temp_new_i64();
90
+ &error_abort);
121
+ tcg_res[0] = tcg_temp_new_i64();
91
+ }
122
+ tcg_res[1] = tcg_temp_new_i64();
123
+
92
+
124
+ for (pass = 0; pass < 2; pass++) {
93
+ object_property_set_link(OBJECT(&s->lpd.crl),
125
+ read_vec_element(s, tcg_op1, rn, pass, MO_64);
94
+ "usb", OBJECT(&s->lpd.iou.usb),
126
+ read_vec_element(s, tcg_op2, rm, pass, MO_64);
95
+ &error_abort);
127
+ read_vec_element(s, tcg_op3, ra, pass, MO_64);
128
+
96
+
129
+ if (op0 == 0) {
97
+ sysbus_realize(sbd, &error_fatal);
130
+ /* EOR3 */
98
+ memory_region_add_subregion(&s->mr_ps, MM_CRL,
131
+ tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op3);
99
+ sysbus_mmio_get_region(sbd, 0));
132
+ } else {
100
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
133
+ /* BCAX */
134
+ tcg_gen_andc_i64(tcg_res[pass], tcg_op2, tcg_op3);
135
+ }
136
+ tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
137
+ }
138
+ write_vec_element(s, tcg_res[0], rd, 0, MO_64);
139
+ write_vec_element(s, tcg_res[1], rd, 1, MO_64);
140
+
141
+ tcg_temp_free_i64(tcg_op1);
142
+ tcg_temp_free_i64(tcg_op2);
143
+ tcg_temp_free_i64(tcg_op3);
144
+ tcg_temp_free_i64(tcg_res[0]);
145
+ tcg_temp_free_i64(tcg_res[1]);
146
+ } else {
147
+ g_assert_not_reached();
148
+ }
149
+}
101
+}
150
+
102
+
151
+/* Crypto XAR
103
/* This takes the board allocated linear DDR memory and creates aliases
152
+ * 31 21 20 16 15 10 9 5 4 0
104
* for each split DDR range/aperture on the Versal address map.
153
+ * +-----------------------+------+--------+------+------+
105
*/
154
+ * | 1 1 0 0 1 1 1 0 1 0 0 | Rm | imm6 | Rn | Rd |
106
@@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s)
155
+ * +-----------------------+------+--------+------+------+
107
156
+ */
108
versal_unimp_area(s, "psm", &s->mr_ps,
157
+static void disas_crypto_xar(DisasContext *s, uint32_t insn)
109
MM_PSM_START, MM_PSM_END - MM_PSM_START);
158
+{
110
- versal_unimp_area(s, "crl", &s->mr_ps,
159
+ int rm = extract32(insn, 16, 5);
111
- MM_CRL, MM_CRL_SIZE);
160
+ int imm6 = extract32(insn, 10, 6);
112
versal_unimp_area(s, "crf", &s->mr_ps,
161
+ int rn = extract32(insn, 5, 5);
113
MM_FPD_CRF, MM_FPD_CRF_SIZE);
162
+ int rd = extract32(insn, 0, 5);
114
versal_unimp_area(s, "apu", &s->mr_ps,
163
+ TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
115
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
164
+ int pass;
116
versal_create_efuse(s, pic);
165
+
117
versal_create_pmc_iou_slcr(s, pic);
166
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA3)) {
118
versal_create_ospi(s, pic);
167
+ unallocated_encoding(s);
119
+ versal_create_crl(s, pic);
168
+ return;
120
versal_map_ddr(s);
169
+ }
121
versal_unimp(s);
170
+
171
+ if (!fp_access_check(s)) {
172
+ return;
173
+ }
174
+
175
+ tcg_op1 = tcg_temp_new_i64();
176
+ tcg_op2 = tcg_temp_new_i64();
177
+ tcg_res[0] = tcg_temp_new_i64();
178
+ tcg_res[1] = tcg_temp_new_i64();
179
+
180
+ for (pass = 0; pass < 2; pass++) {
181
+ read_vec_element(s, tcg_op1, rn, pass, MO_64);
182
+ read_vec_element(s, tcg_op2, rm, pass, MO_64);
183
+
184
+ tcg_gen_xor_i64(tcg_res[pass], tcg_op1, tcg_op2);
185
+ tcg_gen_rotri_i64(tcg_res[pass], tcg_res[pass], imm6);
186
+ }
187
+ write_vec_element(s, tcg_res[0], rd, 0, MO_64);
188
+ write_vec_element(s, tcg_res[1], rd, 1, MO_64);
189
+
190
+ tcg_temp_free_i64(tcg_op1);
191
+ tcg_temp_free_i64(tcg_op2);
192
+ tcg_temp_free_i64(tcg_res[0]);
193
+ tcg_temp_free_i64(tcg_res[1]);
194
+}
195
+
196
/* C3.6 Data processing - SIMD, inc Crypto
197
*
198
* As the decode gets a little complex we are using a table based
199
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
200
{ 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
201
{ 0xce608000, 0xffe0b000, disas_crypto_three_reg_sha512 },
202
{ 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
203
+ { 0xce000000, 0xff808000, disas_crypto_four_reg },
204
+ { 0xce800000, 0xffe00000, disas_crypto_xar },
205
{ 0x00000000, 0x00000000, NULL }
206
};
207
122
208
--
123
--
209
2.16.1
124
2.25.1
210
211
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The Exynos4210 SoC device currently uses a custom device
2
"exynos4210.irq_gate" to model the OR gate that feeds each CPU's IRQ
3
line. We have a standard TYPE_OR_IRQ device for this now, so use
4
that instead.
2
5
3
Define ZCR_EL[1-3].
6
(This is a migration compatibility break, but that is OK for this
7
machine type.)
4
8
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180123035349.24538-5-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-2-peter.maydell@linaro.org
9
---
12
---
10
target/arm/cpu.h | 5 ++
13
include/hw/arm/exynos4210.h | 1 +
11
target/arm/helper.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++
14
hw/arm/exynos4210.c | 31 ++++++++++++++++---------------
12
2 files changed, 136 insertions(+)
15
2 files changed, 17 insertions(+), 15 deletions(-)
13
16
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
19
--- a/include/hw/arm/exynos4210.h
17
+++ b/target/arm/cpu.h
20
+++ b/include/hw/arm/exynos4210.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
21
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
19
*/
22
MemoryRegion bootreg_mem;
20
float_status fp_status;
23
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
21
float_status standard_fp_status;
24
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
22
+
25
+ qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
23
+ /* ZCR_EL[1-3] */
26
};
24
+ uint64_t zcr_el[4];
27
25
} vfp;
28
#define TYPE_EXYNOS4210_SOC "exynos4210"
26
uint64_t exclusive_addr;
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
27
uint64_t exclusive_val;
28
@@ -XXX,XX +XXX,XX @@ void pmccntr_sync(CPUARMState *env);
29
#define CPTR_TCPAC (1U << 31)
30
#define CPTR_TTA (1U << 20)
31
#define CPTR_TFP (1U << 10)
32
+#define CPTR_TZ (1U << 8) /* CPTR_EL2 */
33
+#define CPTR_EZ (1U << 8) /* CPTR_EL3 */
34
35
#define MDCR_EPMAD (1U << 21)
36
#define MDCR_EDAD (1U << 20)
37
diff --git a/target/arm/helper.c b/target/arm/helper.c
38
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/helper.c
31
--- a/hw/arm/exynos4210.c
40
+++ b/target/arm/helper.c
32
+++ b/hw/arm/exynos4210.c
41
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
42
REGINFO_SENTINEL
43
};
44
45
+/* Return the exception level to which SVE-disabled exceptions should
46
+ * be taken, or 0 if SVE is enabled.
47
+ */
48
+static int sve_exception_el(CPUARMState *env)
49
+{
50
+#ifndef CONFIG_USER_ONLY
51
+ unsigned current_el = arm_current_el(env);
52
+
53
+ /* The CPACR.ZEN controls traps to EL1:
54
+ * 0, 2 : trap EL0 and EL1 accesses
55
+ * 1 : trap only EL0 accesses
56
+ * 3 : trap no accesses
57
+ */
58
+ switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
59
+ default:
60
+ if (current_el <= 1) {
61
+ /* Trap to PL1, which might be EL1 or EL3 */
62
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
63
+ return 3;
64
+ }
65
+ return 1;
66
+ }
67
+ break;
68
+ case 1:
69
+ if (current_el == 0) {
70
+ return 1;
71
+ }
72
+ break;
73
+ case 3:
74
+ break;
75
+ }
76
+
77
+ /* Similarly for CPACR.FPEN, after having checked ZEN. */
78
+ switch (extract32(env->cp15.cpacr_el1, 20, 2)) {
79
+ default:
80
+ if (current_el <= 1) {
81
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
82
+ return 3;
83
+ }
84
+ return 1;
85
+ }
86
+ break;
87
+ case 1:
88
+ if (current_el == 0) {
89
+ return 1;
90
+ }
91
+ break;
92
+ case 3:
93
+ break;
94
+ }
95
+
96
+ /* CPTR_EL2. Check both TZ and TFP. */
97
+ if (current_el <= 2
98
+ && (env->cp15.cptr_el[2] & (CPTR_TFP | CPTR_TZ))
99
+ && !arm_is_secure_below_el3(env)) {
100
+ return 2;
101
+ }
102
+
103
+ /* CPTR_EL3. Check both EZ and TFP. */
104
+ if (!(env->cp15.cptr_el[3] & CPTR_EZ)
105
+ || (env->cp15.cptr_el[3] & CPTR_TFP)) {
106
+ return 3;
107
+ }
108
+#endif
109
+ return 0;
110
+}
111
+
112
+static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri,
113
+ bool isread)
114
+{
115
+ switch (sve_exception_el(env)) {
116
+ case 3:
117
+ return CP_ACCESS_TRAP_EL3;
118
+ case 2:
119
+ return CP_ACCESS_TRAP_EL2;
120
+ case 1:
121
+ return CP_ACCESS_TRAP;
122
+ }
123
+ return CP_ACCESS_OK;
124
+}
125
+
126
+static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
127
+ uint64_t value)
128
+{
129
+ /* Bits other than [3:0] are RAZ/WI. */
130
+ raw_write(env, ri, value & 0xf);
131
+}
132
+
133
+static const ARMCPRegInfo zcr_el1_reginfo = {
134
+ .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
135
+ .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
136
+ .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
137
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
138
+ .writefn = zcr_write, .raw_writefn = raw_write
139
+};
140
+
141
+static const ARMCPRegInfo zcr_el2_reginfo = {
142
+ .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
143
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
144
+ .access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
145
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
146
+ .writefn = zcr_write, .raw_writefn = raw_write
147
+};
148
+
149
+static const ARMCPRegInfo zcr_no_el2_reginfo = {
150
+ .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
151
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
152
+ .access = PL2_RW, .type = ARM_CP_64BIT,
153
+ .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore
154
+};
155
+
156
+static const ARMCPRegInfo zcr_el3_reginfo = {
157
+ .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
158
+ .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
159
+ .access = PL3_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
160
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
161
+ .writefn = zcr_write, .raw_writefn = raw_write
162
+};
163
+
164
void hw_watchpoint_update(ARMCPU *cpu, int n)
165
{
34
{
166
CPUARMState *env = &cpu->env;
35
Exynos4210State *s = EXYNOS4210_SOC(socdev);
167
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
36
MemoryRegion *system_mem = get_system_memory();
168
}
37
- qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
169
define_one_arm_cp_reg(cpu, &sctlr);
38
SysBusDevice *busdev;
39
DeviceState *dev, *uart[4], *pl330[3];
40
int i, n;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
42
43
/* IRQ Gate */
44
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
45
- dev = qdev_new("exynos4210.irq_gate");
46
- qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
47
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
48
- /* Get IRQ Gate input in gate_irq */
49
- for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
50
- gate_irq[i][n] = qdev_get_gpio_in(dev, n);
51
- }
52
- busdev = SYS_BUS_DEVICE(dev);
53
-
54
- /* Connect IRQ Gate output to CPU's IRQ line */
55
- sysbus_connect_irq(busdev, 0,
56
- qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
57
+ DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
58
+ object_property_set_int(OBJECT(orgate), "num-lines",
59
+ EXYNOS4210_IRQ_GATE_NINPUTS,
60
+ &error_abort);
61
+ qdev_realize(orgate, NULL, &error_abort);
62
+ qdev_connect_gpio_out(orgate, 0,
63
+ qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
64
}
65
66
/* Private memory region and Internal GIC */
67
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
68
sysbus_realize_and_unref(busdev, &error_fatal);
69
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
70
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
71
- sysbus_connect_irq(busdev, n, gate_irq[n][0]);
72
+ sysbus_connect_irq(busdev, n,
73
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
74
}
75
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
76
s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
77
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
78
/* Map Distributer interface */
79
sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
80
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
81
- sysbus_connect_irq(busdev, n, gate_irq[n][1]);
82
+ sysbus_connect_irq(busdev, n,
83
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
84
}
85
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
86
s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
87
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
88
object_initialize_child(obj, name, orgate, TYPE_OR_IRQ);
89
g_free(name);
170
}
90
}
171
+
91
+
172
+ if (arm_feature(env, ARM_FEATURE_SVE)) {
92
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_orgate); i++) {
173
+ define_one_arm_cp_reg(cpu, &zcr_el1_reginfo);
93
+ g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
174
+ if (arm_feature(env, ARM_FEATURE_EL2)) {
94
+ object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
175
+ define_one_arm_cp_reg(cpu, &zcr_el2_reginfo);
176
+ } else {
177
+ define_one_arm_cp_reg(cpu, &zcr_no_el2_reginfo);
178
+ }
179
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
180
+ define_one_arm_cp_reg(cpu, &zcr_el3_reginfo);
181
+ }
182
+ }
95
+ }
183
}
96
}
184
97
185
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
98
static void exynos4210_class_init(ObjectClass *klass, void *data)
186
--
99
--
187
2.16.1
100
2.25.1
188
189
diff view generated by jsdifflib
1
The documentation for the generic loader claims that you can
1
Now we have removed the only use of TYPE_EXYNOS4210_IRQ_GATE we can
2
set the PC for a CPU with an option of the form
2
delete the device entirely.
3
-device loader,cpu-num=0,addr=0x10000004
4
5
However if you try this QEMU complains:
6
cpu_num must be specified when setting a program counter
7
8
This is because we were testing against 0 rather than CPU_NONE.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
5
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20220404154658.565020-3-peter.maydell@linaro.org
13
Message-id: 20180205150426.20542-1-peter.maydell@linaro.org
14
---
7
---
15
hw/core/generic-loader.c | 2 +-
8
hw/intc/exynos4210_gic.c | 107 ---------------------------------------
16
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 107 deletions(-)
17
10
18
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
11
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
19
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/core/generic-loader.c
13
--- a/hw/intc/exynos4210_gic.c
21
+++ b/hw/core/generic-loader.c
14
+++ b/hw/intc/exynos4210_gic.c
22
@@ -XXX,XX +XXX,XX @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
15
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_register_types(void)
23
error_setg(errp, "data can not be specified when setting a "
16
}
24
"program counter");
17
25
return;
18
type_init(exynos4210_gic_register_types)
26
- } else if (!s->cpu_num) {
19
-
27
+ } else if (s->cpu_num == CPU_NONE) {
20
-/* IRQ OR Gate struct.
28
error_setg(errp, "cpu_num must be specified when setting a "
21
- *
29
"program counter");
22
- * This device models an OR gate. There are n_in input qdev gpio lines and one
30
return;
23
- * output sysbus IRQ line. The output IRQ level is formed as OR between all
24
- * gpio inputs.
25
- */
26
-
27
-#define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
28
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE)
29
-
30
-struct Exynos4210IRQGateState {
31
- SysBusDevice parent_obj;
32
-
33
- uint32_t n_in; /* inputs amount */
34
- uint32_t *level; /* input levels */
35
- qemu_irq out; /* output IRQ */
36
-};
37
-
38
-static Property exynos4210_irq_gate_properties[] = {
39
- DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1),
40
- DEFINE_PROP_END_OF_LIST(),
41
-};
42
-
43
-static const VMStateDescription vmstate_exynos4210_irq_gate = {
44
- .name = "exynos4210.irq_gate",
45
- .version_id = 2,
46
- .minimum_version_id = 2,
47
- .fields = (VMStateField[]) {
48
- VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in),
49
- VMSTATE_END_OF_LIST()
50
- }
51
-};
52
-
53
-/* Process a change in IRQ input. */
54
-static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
55
-{
56
- Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
57
- uint32_t i;
58
-
59
- assert(irq < s->n_in);
60
-
61
- s->level[irq] = level;
62
-
63
- for (i = 0; i < s->n_in; i++) {
64
- if (s->level[i] >= 1) {
65
- qemu_irq_raise(s->out);
66
- return;
67
- }
68
- }
69
-
70
- qemu_irq_lower(s->out);
71
-}
72
-
73
-static void exynos4210_irq_gate_reset(DeviceState *d)
74
-{
75
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
76
-
77
- memset(s->level, 0, s->n_in * sizeof(*s->level));
78
-}
79
-
80
-/*
81
- * IRQ Gate initialization.
82
- */
83
-static void exynos4210_irq_gate_init(Object *obj)
84
-{
85
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
86
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
87
-
88
- sysbus_init_irq(sbd, &s->out);
89
-}
90
-
91
-static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
92
-{
93
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
94
-
95
- /* Allocate general purpose input signals and connect a handler to each of
96
- * them */
97
- qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
98
-
99
- s->level = g_malloc0(s->n_in * sizeof(*s->level));
100
-}
101
-
102
-static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
103
-{
104
- DeviceClass *dc = DEVICE_CLASS(klass);
105
-
106
- dc->reset = exynos4210_irq_gate_reset;
107
- dc->vmsd = &vmstate_exynos4210_irq_gate;
108
- device_class_set_props(dc, exynos4210_irq_gate_properties);
109
- dc->realize = exynos4210_irq_gate_realize;
110
-}
111
-
112
-static const TypeInfo exynos4210_irq_gate_info = {
113
- .name = TYPE_EXYNOS4210_IRQ_GATE,
114
- .parent = TYPE_SYS_BUS_DEVICE,
115
- .instance_size = sizeof(Exynos4210IRQGateState),
116
- .instance_init = exynos4210_irq_gate_init,
117
- .class_init = exynos4210_irq_gate_class_init,
118
-};
119
-
120
-static void exynos4210_irq_gate_register_types(void)
121
-{
122
- type_register_static(&exynos4210_irq_gate_info);
123
-}
124
-
125
-type_init(exynos4210_irq_gate_register_types)
31
--
126
--
32
2.16.1
127
2.25.1
33
34
diff view generated by jsdifflib
1
Handle possible MPU faults, SAU faults or bus errors when
1
The exynos4210 SoC mostly creates its child devices as if it were
2
popping register state off the stack during exception return.
2
board code. This includes the a9mpcore object. Switch that to a
3
new-style "embedded in the state struct" creation, because in the
4
next commit we're going to want to refer to the object again further
5
down in the exynos4210_realize() function.
3
6
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 1517324542-6607-8-git-send-email-peter.maydell@linaro.org
9
Message-id: 20220404154658.565020-4-peter.maydell@linaro.org
7
---
10
---
8
target/arm/helper.c | 115 ++++++++++++++++++++++++++++++++++++++++++----------
11
include/hw/arm/exynos4210.h | 2 ++
9
1 file changed, 94 insertions(+), 21 deletions(-)
12
hw/arm/exynos4210.c | 11 ++++++-----
13
2 files changed, 8 insertions(+), 5 deletions(-)
10
14
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
17
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/helper.c
18
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ pend_fault:
19
@@ -XXX,XX +XXX,XX @@
16
return false;
20
21
#include "hw/or-irq.h"
22
#include "hw/sysbus.h"
23
+#include "hw/cpu/a9mpcore.h"
24
#include "target/arm/cpu-qom.h"
25
#include "qom/object.h"
26
27
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
28
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
29
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
30
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
31
+ A9MPPrivState a9mpcore;
32
};
33
34
#define TYPE_EXYNOS4210_SOC "exynos4210"
35
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/exynos4210.c
38
+++ b/hw/arm/exynos4210.c
39
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
40
}
41
42
/* Private memory region and Internal GIC */
43
- dev = qdev_new(TYPE_A9MPCORE_PRIV);
44
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
45
- busdev = SYS_BUS_DEVICE(dev);
46
- sysbus_realize_and_unref(busdev, &error_fatal);
47
+ qdev_prop_set_uint32(DEVICE(&s->a9mpcore), "num-cpu", EXYNOS4210_NCPUS);
48
+ busdev = SYS_BUS_DEVICE(&s->a9mpcore);
49
+ sysbus_realize(busdev, &error_fatal);
50
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
51
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
52
sysbus_connect_irq(busdev, n,
53
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
54
}
55
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
56
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
57
+ s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
58
}
59
60
/* Cache controller */
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
62
g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
63
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
64
}
65
+
66
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
17
}
67
}
18
68
19
+static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr,
69
static void exynos4210_class_init(ObjectClass *klass, void *data)
20
+ ARMMMUIdx mmu_idx)
21
+{
22
+ CPUState *cs = CPU(cpu);
23
+ CPUARMState *env = &cpu->env;
24
+ MemTxAttrs attrs = {};
25
+ MemTxResult txres;
26
+ target_ulong page_size;
27
+ hwaddr physaddr;
28
+ int prot;
29
+ ARMMMUFaultInfo fi;
30
+ bool secure = mmu_idx & ARM_MMU_IDX_M_S;
31
+ int exc;
32
+ bool exc_secure;
33
+ uint32_t value;
34
+
35
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
36
+ &attrs, &prot, &page_size, &fi, NULL)) {
37
+ /* MPU/SAU lookup failed */
38
+ if (fi.type == ARMFault_QEMU_SFault) {
39
+ qemu_log_mask(CPU_LOG_INT,
40
+ "...SecureFault with SFSR.AUVIOL during unstack\n");
41
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
42
+ env->v7m.sfar = addr;
43
+ exc = ARMV7M_EXCP_SECURE;
44
+ exc_secure = false;
45
+ } else {
46
+ qemu_log_mask(CPU_LOG_INT,
47
+ "...MemManageFault with CFSR.MUNSTKERR\n");
48
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MUNSTKERR_MASK;
49
+ exc = ARMV7M_EXCP_MEM;
50
+ exc_secure = secure;
51
+ }
52
+ goto pend_fault;
53
+ }
54
+
55
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
56
+ attrs, &txres);
57
+ if (txres != MEMTX_OK) {
58
+ /* BusFault trying to read the data */
59
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.UNSTKERR\n");
60
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_UNSTKERR_MASK;
61
+ exc = ARMV7M_EXCP_BUS;
62
+ exc_secure = false;
63
+ goto pend_fault;
64
+ }
65
+
66
+ *dest = value;
67
+ return true;
68
+
69
+pend_fault:
70
+ /* By pending the exception at this point we are making
71
+ * the IMPDEF choice "overridden exceptions pended" (see the
72
+ * MergeExcInfo() pseudocode). The other choice would be to not
73
+ * pend them now and then make a choice about which to throw away
74
+ * later if we have two derived exceptions.
75
+ */
76
+ armv7m_nvic_set_pending(env->nvic, exc, exc_secure);
77
+ return false;
78
+}
79
+
80
/* Return true if we're using the process stack pointer (not the MSP) */
81
static bool v7m_using_psp(CPUARMState *env)
82
{
83
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
84
!return_to_handler,
85
return_to_sp_process);
86
uint32_t frameptr = *frame_sp_p;
87
+ bool pop_ok = true;
88
+ ARMMMUIdx mmu_idx;
89
+
90
+ mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, return_to_secure,
91
+ !return_to_handler);
92
93
if (!QEMU_IS_ALIGNED(frameptr, 8) &&
94
arm_feature(env, ARM_FEATURE_V8)) {
95
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
96
return;
97
}
98
99
- env->regs[4] = ldl_phys(cs->as, frameptr + 0x8);
100
- env->regs[5] = ldl_phys(cs->as, frameptr + 0xc);
101
- env->regs[6] = ldl_phys(cs->as, frameptr + 0x10);
102
- env->regs[7] = ldl_phys(cs->as, frameptr + 0x14);
103
- env->regs[8] = ldl_phys(cs->as, frameptr + 0x18);
104
- env->regs[9] = ldl_phys(cs->as, frameptr + 0x1c);
105
- env->regs[10] = ldl_phys(cs->as, frameptr + 0x20);
106
- env->regs[11] = ldl_phys(cs->as, frameptr + 0x24);
107
+ pop_ok =
108
+ v7m_stack_read(cpu, &env->regs[4], frameptr + 0x8, mmu_idx) &&
109
+ v7m_stack_read(cpu, &env->regs[4], frameptr + 0x8, mmu_idx) &&
110
+ v7m_stack_read(cpu, &env->regs[5], frameptr + 0xc, mmu_idx) &&
111
+ v7m_stack_read(cpu, &env->regs[6], frameptr + 0x10, mmu_idx) &&
112
+ v7m_stack_read(cpu, &env->regs[7], frameptr + 0x14, mmu_idx) &&
113
+ v7m_stack_read(cpu, &env->regs[8], frameptr + 0x18, mmu_idx) &&
114
+ v7m_stack_read(cpu, &env->regs[9], frameptr + 0x1c, mmu_idx) &&
115
+ v7m_stack_read(cpu, &env->regs[10], frameptr + 0x20, mmu_idx) &&
116
+ v7m_stack_read(cpu, &env->regs[11], frameptr + 0x24, mmu_idx);
117
118
frameptr += 0x28;
119
}
120
121
- /* Pop registers. TODO: make these accesses use the correct
122
- * attributes and address space (S/NS, priv/unpriv) and handle
123
- * memory transaction failures.
124
- */
125
- env->regs[0] = ldl_phys(cs->as, frameptr);
126
- env->regs[1] = ldl_phys(cs->as, frameptr + 0x4);
127
- env->regs[2] = ldl_phys(cs->as, frameptr + 0x8);
128
- env->regs[3] = ldl_phys(cs->as, frameptr + 0xc);
129
- env->regs[12] = ldl_phys(cs->as, frameptr + 0x10);
130
- env->regs[14] = ldl_phys(cs->as, frameptr + 0x14);
131
- env->regs[15] = ldl_phys(cs->as, frameptr + 0x18);
132
+ /* Pop registers */
133
+ pop_ok = pop_ok &&
134
+ v7m_stack_read(cpu, &env->regs[0], frameptr, mmu_idx) &&
135
+ v7m_stack_read(cpu, &env->regs[1], frameptr + 0x4, mmu_idx) &&
136
+ v7m_stack_read(cpu, &env->regs[2], frameptr + 0x8, mmu_idx) &&
137
+ v7m_stack_read(cpu, &env->regs[3], frameptr + 0xc, mmu_idx) &&
138
+ v7m_stack_read(cpu, &env->regs[12], frameptr + 0x10, mmu_idx) &&
139
+ v7m_stack_read(cpu, &env->regs[14], frameptr + 0x14, mmu_idx) &&
140
+ v7m_stack_read(cpu, &env->regs[15], frameptr + 0x18, mmu_idx) &&
141
+ v7m_stack_read(cpu, &xpsr, frameptr + 0x1c, mmu_idx);
142
+
143
+ if (!pop_ok) {
144
+ /* v7m_stack_read() pended a fault, so take it (as a tail
145
+ * chained exception on the same stack frame)
146
+ */
147
+ v7m_exception_taken(cpu, excret, true, false);
148
+ return;
149
+ }
150
151
/* Returning from an exception with a PC with bit 0 set is defined
152
* behaviour on v8M (bit 0 is ignored), but for v7M it was specified
153
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
154
}
155
}
156
157
- xpsr = ldl_phys(cs->as, frameptr + 0x1c);
158
-
159
if (arm_feature(env, ARM_FEATURE_V8)) {
160
/* For v8M we have to check whether the xPSR exception field
161
* matches the EXCRET value for return to handler/thread
162
--
70
--
163
2.16.1
71
2.25.1
164
165
diff view generated by jsdifflib
New patch
1
The only time we use the int_gic_irq[] array in the Exynos4210Irq
2
struct is in the exynos4210_realize() function: we initialize it with
3
the GPIO inputs of the a9mpcore device, and then a bit later on we
4
connect those to the outputs of the internal combiner. Now that the
5
a9mpcore object is easily accessible as s->a9mpcore we can make the
6
connection directly from one device to the other without going via
7
this array.
1
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-5-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 1 -
14
hw/arm/exynos4210.c | 6 ++----
15
2 files changed, 2 insertions(+), 5 deletions(-)
16
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/exynos4210.h
20
+++ b/include/hw/arm/exynos4210.h
21
@@ -XXX,XX +XXX,XX @@
22
typedef struct Exynos4210Irq {
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
25
- qemu_irq int_gic_irq[EXYNOS4210_INT_GIC_NIRQ];
26
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
27
qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
28
} Exynos4210Irq;
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
34
sysbus_connect_irq(busdev, n,
35
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
36
}
37
- for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
38
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
39
- }
40
41
/* Cache controller */
42
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
43
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
44
busdev = SYS_BUS_DEVICE(dev);
45
sysbus_realize_and_unref(busdev, &error_fatal);
46
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
47
- sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
48
+ sysbus_connect_irq(busdev, n,
49
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
50
}
51
exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
52
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
53
--
54
2.25.1
diff view generated by jsdifflib
1
From: Christoffer Dall <christoffer.dall@linaro.org>
1
The exynos4210 code currently has two very similar arrays of IRQs:
2
2
3
KVM doesn't support emulating a GICv3 in userspace, only GICv2. We
3
* board_irqs is a field of the Exynos4210Irq struct which is filled
4
currently attempt this anyway, and as a result a KVM guest doesn't
4
in by exynos4210_init_board_irqs() with the appropriate qemu_irqs
5
receive interrupts and the user is left wondering why. Report an error
5
for each IRQ the board/SoC can assert
6
to the user if this particular combination is requested.
6
* irq_table is a set of qemu_irqs pointed to from the
7
Exynos4210State struct. It's allocated in exynos4210_init_irq,
8
and the only behaviour these irqs have is that they pass on the
9
level to the equivalent board_irqs[] irq
7
10
8
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
11
The extra indirection through irq_table is unnecessary, so coalesce
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
these into a single irq_table[] array as a direct field in
10
Message-id: 20180201205307.30343-1-christoffer.dall@linaro.org
13
Exynos4210State which exynos4210_init_board_irqs() fills in.
14
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20220404154658.565020-6-peter.maydell@linaro.org
12
---
18
---
13
target/arm/kvm_arm.h | 4 ++++
19
include/hw/arm/exynos4210.h | 8 ++------
14
1 file changed, 4 insertions(+)
20
hw/arm/exynos4210.c | 6 +-----
21
hw/intc/exynos4210_gic.c | 32 ++++++++------------------------
22
3 files changed, 11 insertions(+), 35 deletions(-)
15
23
16
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
24
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
17
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm_arm.h
26
--- a/include/hw/arm/exynos4210.h
19
+++ b/target/arm/kvm_arm.h
27
+++ b/include/hw/arm/exynos4210.h
20
@@ -XXX,XX +XXX,XX @@ static inline const char *gicv3_class_name(void)
28
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210Irq {
21
exit(1);
29
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
22
#endif
30
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
23
} else {
31
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
24
+ if (kvm_enabled()) {
32
- qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
25
+ error_report("Userspace GICv3 is not supported with KVM");
33
} Exynos4210Irq;
26
+ exit(1);
34
27
+ }
35
struct Exynos4210State {
28
return "arm-gicv3";
36
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
37
/*< public >*/
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
39
Exynos4210Irq irqs;
40
- qemu_irq *irq_table;
41
+ qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
42
43
MemoryRegion chipid_mem;
44
MemoryRegion iram_mem;
45
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
46
void exynos4210_write_secondary(ARMCPU *cpu,
47
const struct arm_boot_info *info);
48
49
-/* Initialize exynos4210 IRQ subsystem stub */
50
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);
51
-
52
/* Initialize board IRQs.
53
* These IRQs contain splitted Int/External Combiner and External Gic IRQs */
54
-void exynos4210_init_board_irqs(Exynos4210Irq *s);
55
+void exynos4210_init_board_irqs(Exynos4210State *s);
56
57
/* Get IRQ number from exynos4210 IRQ subsystem stub.
58
* To identify IRQ source use internal combiner group and bit number
59
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/exynos4210.c
62
+++ b/hw/arm/exynos4210.c
63
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
64
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
65
}
66
67
- /*** IRQs ***/
68
-
69
- s->irq_table = exynos4210_init_irq(&s->irqs);
70
-
71
/* IRQ Gate */
72
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
73
DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
74
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
75
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
76
77
/* Initialize board IRQs. */
78
- exynos4210_init_board_irqs(&s->irqs);
79
+ exynos4210_init_board_irqs(s);
80
81
/*** Memory ***/
82
83
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/intc/exynos4210_gic.c
86
+++ b/hw/intc/exynos4210_gic.c
87
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
88
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
89
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
90
91
-static void exynos4210_irq_handler(void *opaque, int irq, int level)
92
-{
93
- Exynos4210Irq *s = (Exynos4210Irq *)opaque;
94
-
95
- /* Bypass */
96
- qemu_set_irq(s->board_irqs[irq], level);
97
-}
98
-
99
-/*
100
- * Initialize exynos4210 IRQ subsystem stub.
101
- */
102
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *s)
103
-{
104
- return qemu_allocate_irqs(exynos4210_irq_handler, s,
105
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ);
106
-}
107
-
108
/*
109
* Initialize board IRQs.
110
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
111
*/
112
-void exynos4210_init_board_irqs(Exynos4210Irq *s)
113
+void exynos4210_init_board_irqs(Exynos4210State *s)
114
{
115
uint32_t grp, bit, irq_id, n;
116
+ Exynos4210Irq *is = &s->irqs;
117
118
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
119
irq_id = 0;
120
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
121
irq_id = EXT_GIC_ID_MCT_G1;
122
}
123
if (irq_id) {
124
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
125
- s->ext_gic_irq[irq_id-32]);
126
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
127
+ is->ext_gic_irq[irq_id - 32]);
128
} else {
129
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
130
- s->ext_combiner_irq[n]);
131
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
132
+ is->ext_combiner_irq[n]);
133
}
134
}
135
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
136
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
137
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
138
139
if (irq_id) {
140
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
141
- s->ext_gic_irq[irq_id-32]);
142
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
143
+ is->ext_gic_irq[irq_id - 32]);
144
}
29
}
145
}
30
}
146
}
31
--
147
--
32
2.16.1
148
2.25.1
33
34
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Fix a missing set of spaces around '-' in the definition of
2
combiner_grp_to_gic_id[]. We're about to move this code, so
3
fix the style issue first to keep checkpatch happy with the
4
code-motion patch.
2
5
3
Convert i.MX6 to use TYPE_IMX_USDHC since that's what real HW comes
4
with.
5
6
Cc: Peter Maydell <peter.maydell@linaro.org>
7
Cc: Jason Wang <jasowang@redhat.com>
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
10
Cc: Michael S. Tsirkin <mst@redhat.com>
11
Cc: qemu-devel@nongnu.org
12
Cc: qemu-arm@nongnu.org
13
Cc: yurovsky@gmail.com
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220404154658.565020-7-peter.maydell@linaro.org
17
---
9
---
18
hw/arm/fsl-imx6.c | 2 +-
10
hw/intc/exynos4210_gic.c | 2 +-
19
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
20
12
21
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
13
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/fsl-imx6.c
15
--- a/hw/intc/exynos4210_gic.c
24
+++ b/hw/arm/fsl-imx6.c
16
+++ b/hw/intc/exynos4210_gic.c
25
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6_init(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ enum ExtInt {
26
}
18
*/
27
19
28
for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) {
20
static const uint32_t
29
- object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_SYSBUS_SDHCI);
21
-combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
30
+ object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_IMX_USDHC);
22
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
31
qdev_set_parent_bus(DEVICE(&s->esdhc[i]), sysbus_get_default());
23
/* int combiner groups 16-19 */
32
snprintf(name, NAME_SIZE, "sdhc%d", i + 1);
24
{ }, { }, { }, { },
33
object_property_add_child(obj, name, OBJECT(&s->esdhc[i]), NULL);
25
/* int combiner group 20 */
34
--
26
--
35
2.16.1
27
2.25.1
36
37
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
The function exynos4210_init_board_irqs() currently lives in
2
exynos4210_gic.c, but it isn't really part of the exynos4210.gic
3
device -- it is a function that implements (some of) the wiring up of
4
interrupts between the SoC's GIC and combiner components. This means
5
it fits better in exynos4210.c, which is the SoC-level code. Move it
6
there. Similarly, exynos4210_git_irq() is used almost only in the
7
SoC-level code, so move it too.
2
8
3
This implements emulation of the new SHA-512 instructions that have
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
been added as an optional extensions to the ARMv8 Crypto Extensions
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
in ARM v8.2.
11
Message-id: 20220404154658.565020-8-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 4 -
14
hw/arm/exynos4210.c | 202 +++++++++++++++++++++++++++++++++++
15
hw/intc/exynos4210_gic.c | 204 ------------------------------------
16
3 files changed, 202 insertions(+), 208 deletions(-)
6
17
7
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
8
Message-id: 20180207111729.15737-2-ard.biesheuvel@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpu.h | 1 +
13
target/arm/helper.h | 5 +++
14
target/arm/crypto_helper.c | 90 ++++++++++++++++++++++++++++++++++++-
15
target/arm/translate-a64.c | 110 +++++++++++++++++++++++++++++++++++++++++++++
16
4 files changed, 205 insertions(+), 1 deletion(-)
17
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
20
--- a/include/hw/arm/exynos4210.h
21
+++ b/target/arm/cpu.h
21
+++ b/include/hw/arm/exynos4210.h
22
@@ -XXX,XX +XXX,XX @@ enum arm_features {
22
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
23
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
23
void exynos4210_write_secondary(ARMCPU *cpu,
24
ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
24
const struct arm_boot_info *info);
25
ARM_FEATURE_SVE, /* has Scalable Vector Extension */
25
26
+ ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
26
-/* Initialize board IRQs.
27
};
27
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
28
28
-void exynos4210_init_board_irqs(Exynos4210State *s);
29
static inline int arm_feature(CPUARMState *env, int feature)
29
-
30
diff --git a/target/arm/helper.h b/target/arm/helper.h
30
/* Get IRQ number from exynos4210 IRQ subsystem stub.
31
* To identify IRQ source use internal combiner group and bit number
32
* grp - group number
33
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
31
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/helper.h
35
--- a/hw/arm/exynos4210.c
33
+++ b/target/arm/helper.h
36
+++ b/hw/arm/exynos4210.c
34
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
35
DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
36
DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
37
38
+DEF_HELPER_FLAGS_3(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
39
+DEF_HELPER_FLAGS_3(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
40
+DEF_HELPER_FLAGS_2(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr)
41
+DEF_HELPER_FLAGS_3(crypto_sha512su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
42
+
43
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
44
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
45
DEF_HELPER_2(dc_zva, void, env, i64)
46
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/crypto_helper.c
49
+++ b/target/arm/crypto_helper.c
50
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
51
/*
38
#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
52
* crypto_helper.c - emulate v8 Crypto Extensions instructions
39
#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
53
*
40
54
- * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
41
+enum ExtGicId {
55
+ * Copyright (C) 2013 - 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
42
+ EXT_GIC_ID_MDMA_LCD0 = 66,
56
*
43
+ EXT_GIC_ID_PDMA0,
57
* This library is free software; you can redistribute it and/or
44
+ EXT_GIC_ID_PDMA1,
58
* modify it under the terms of the GNU Lesser General Public
45
+ EXT_GIC_ID_TIMER0,
59
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
46
+ EXT_GIC_ID_TIMER1,
60
rd[0] = d.l[0];
47
+ EXT_GIC_ID_TIMER2,
61
rd[1] = d.l[1];
48
+ EXT_GIC_ID_TIMER3,
62
}
49
+ EXT_GIC_ID_TIMER4,
50
+ EXT_GIC_ID_MCT_L0,
51
+ EXT_GIC_ID_WDT,
52
+ EXT_GIC_ID_RTC_ALARM,
53
+ EXT_GIC_ID_RTC_TIC,
54
+ EXT_GIC_ID_GPIO_XB,
55
+ EXT_GIC_ID_GPIO_XA,
56
+ EXT_GIC_ID_MCT_L1,
57
+ EXT_GIC_ID_IEM_APC,
58
+ EXT_GIC_ID_IEM_IEC,
59
+ EXT_GIC_ID_NFC,
60
+ EXT_GIC_ID_UART0,
61
+ EXT_GIC_ID_UART1,
62
+ EXT_GIC_ID_UART2,
63
+ EXT_GIC_ID_UART3,
64
+ EXT_GIC_ID_UART4,
65
+ EXT_GIC_ID_MCT_G0,
66
+ EXT_GIC_ID_I2C0,
67
+ EXT_GIC_ID_I2C1,
68
+ EXT_GIC_ID_I2C2,
69
+ EXT_GIC_ID_I2C3,
70
+ EXT_GIC_ID_I2C4,
71
+ EXT_GIC_ID_I2C5,
72
+ EXT_GIC_ID_I2C6,
73
+ EXT_GIC_ID_I2C7,
74
+ EXT_GIC_ID_SPI0,
75
+ EXT_GIC_ID_SPI1,
76
+ EXT_GIC_ID_SPI2,
77
+ EXT_GIC_ID_MCT_G1,
78
+ EXT_GIC_ID_USB_HOST,
79
+ EXT_GIC_ID_USB_DEVICE,
80
+ EXT_GIC_ID_MODEMIF,
81
+ EXT_GIC_ID_HSMMC0,
82
+ EXT_GIC_ID_HSMMC1,
83
+ EXT_GIC_ID_HSMMC2,
84
+ EXT_GIC_ID_HSMMC3,
85
+ EXT_GIC_ID_SDMMC,
86
+ EXT_GIC_ID_MIPI_CSI_4LANE,
87
+ EXT_GIC_ID_MIPI_DSI_4LANE,
88
+ EXT_GIC_ID_MIPI_CSI_2LANE,
89
+ EXT_GIC_ID_MIPI_DSI_2LANE,
90
+ EXT_GIC_ID_ONENAND_AUDI,
91
+ EXT_GIC_ID_ROTATOR,
92
+ EXT_GIC_ID_FIMC0,
93
+ EXT_GIC_ID_FIMC1,
94
+ EXT_GIC_ID_FIMC2,
95
+ EXT_GIC_ID_FIMC3,
96
+ EXT_GIC_ID_JPEG,
97
+ EXT_GIC_ID_2D,
98
+ EXT_GIC_ID_PCIe,
99
+ EXT_GIC_ID_MIXER,
100
+ EXT_GIC_ID_HDMI,
101
+ EXT_GIC_ID_HDMI_I2C,
102
+ EXT_GIC_ID_MFC,
103
+ EXT_GIC_ID_TVENC,
104
+};
105
+
106
+enum ExtInt {
107
+ EXT_GIC_ID_EXTINT0 = 48,
108
+ EXT_GIC_ID_EXTINT1,
109
+ EXT_GIC_ID_EXTINT2,
110
+ EXT_GIC_ID_EXTINT3,
111
+ EXT_GIC_ID_EXTINT4,
112
+ EXT_GIC_ID_EXTINT5,
113
+ EXT_GIC_ID_EXTINT6,
114
+ EXT_GIC_ID_EXTINT7,
115
+ EXT_GIC_ID_EXTINT8,
116
+ EXT_GIC_ID_EXTINT9,
117
+ EXT_GIC_ID_EXTINT10,
118
+ EXT_GIC_ID_EXTINT11,
119
+ EXT_GIC_ID_EXTINT12,
120
+ EXT_GIC_ID_EXTINT13,
121
+ EXT_GIC_ID_EXTINT14,
122
+ EXT_GIC_ID_EXTINT15
123
+};
63
+
124
+
64
+/*
125
+/*
65
+ * The SHA-512 logical functions (same as above but using 64-bit operands)
126
+ * External GIC sources which are not from External Interrupt Combiner or
127
+ * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
128
+ * which is INTG16 in Internal Interrupt Combiner.
66
+ */
129
+ */
67
+
130
+
68
+static uint64_t cho512(uint64_t x, uint64_t y, uint64_t z)
131
+static const uint32_t
132
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
133
+ /* int combiner groups 16-19 */
134
+ { }, { }, { }, { },
135
+ /* int combiner group 20 */
136
+ { 0, EXT_GIC_ID_MDMA_LCD0 },
137
+ /* int combiner group 21 */
138
+ { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
139
+ /* int combiner group 22 */
140
+ { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
141
+ EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
142
+ /* int combiner group 23 */
143
+ { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
144
+ /* int combiner group 24 */
145
+ { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
146
+ /* int combiner group 25 */
147
+ { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
148
+ /* int combiner group 26 */
149
+ { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
150
+ EXT_GIC_ID_UART4 },
151
+ /* int combiner group 27 */
152
+ { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
153
+ EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
154
+ EXT_GIC_ID_I2C7 },
155
+ /* int combiner group 28 */
156
+ { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
157
+ /* int combiner group 29 */
158
+ { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
159
+ EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
160
+ /* int combiner group 30 */
161
+ { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
162
+ /* int combiner group 31 */
163
+ { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
164
+ /* int combiner group 32 */
165
+ { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
166
+ /* int combiner group 33 */
167
+ { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
168
+ /* int combiner group 34 */
169
+ { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
170
+ /* int combiner group 35 */
171
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
172
+ /* int combiner group 36 */
173
+ { EXT_GIC_ID_MIXER },
174
+ /* int combiner group 37 */
175
+ { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
176
+ EXT_GIC_ID_EXTINT7 },
177
+ /* groups 38-50 */
178
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
179
+ /* int combiner group 51 */
180
+ { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
181
+ /* group 52 */
182
+ { },
183
+ /* int combiner group 53 */
184
+ { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
185
+ /* groups 54-63 */
186
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
187
+};
188
+
189
+/*
190
+ * Initialize board IRQs.
191
+ * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
192
+ */
193
+static void exynos4210_init_board_irqs(Exynos4210State *s)
69
+{
194
+{
70
+ return (x & (y ^ z)) ^ z;
195
+ uint32_t grp, bit, irq_id, n;
71
+}
196
+ Exynos4210Irq *is = &s->irqs;
72
+
197
+
73
+static uint64_t maj512(uint64_t x, uint64_t y, uint64_t z)
198
+ for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
74
+{
199
+ irq_id = 0;
75
+ return (x & y) | ((x | y) & z);
200
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
76
+}
201
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
77
+
202
+ /* MCT_G0 is passed to External GIC */
78
+static uint64_t S0_512(uint64_t x)
203
+ irq_id = EXT_GIC_ID_MCT_G0;
79
+{
80
+ return ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39);
81
+}
82
+
83
+static uint64_t S1_512(uint64_t x)
84
+{
85
+ return ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41);
86
+}
87
+
88
+static uint64_t s0_512(uint64_t x)
89
+{
90
+ return ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7);
91
+}
92
+
93
+static uint64_t s1_512(uint64_t x)
94
+{
95
+ return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6);
96
+}
97
+
98
+void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm)
99
+{
100
+ uint64_t *rd = vd;
101
+ uint64_t *rn = vn;
102
+ uint64_t *rm = vm;
103
+ uint64_t d0 = rd[0];
104
+ uint64_t d1 = rd[1];
105
+
106
+ d1 += S1_512(rm[1]) + cho512(rm[1], rn[0], rn[1]);
107
+ d0 += S1_512(d1 + rm[0]) + cho512(d1 + rm[0], rm[1], rn[0]);
108
+
109
+ rd[0] = d0;
110
+ rd[1] = d1;
111
+}
112
+
113
+void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm)
114
+{
115
+ uint64_t *rd = vd;
116
+ uint64_t *rn = vn;
117
+ uint64_t *rm = vm;
118
+ uint64_t d0 = rd[0];
119
+ uint64_t d1 = rd[1];
120
+
121
+ d1 += S0_512(rm[0]) + maj512(rn[0], rm[1], rm[0]);
122
+ d0 += S0_512(d1) + maj512(d1, rm[0], rm[1]);
123
+
124
+ rd[0] = d0;
125
+ rd[1] = d1;
126
+}
127
+
128
+void HELPER(crypto_sha512su0)(void *vd, void *vn)
129
+{
130
+ uint64_t *rd = vd;
131
+ uint64_t *rn = vn;
132
+ uint64_t d0 = rd[0];
133
+ uint64_t d1 = rd[1];
134
+
135
+ d0 += s0_512(rd[1]);
136
+ d1 += s0_512(rn[0]);
137
+
138
+ rd[0] = d0;
139
+ rd[1] = d1;
140
+}
141
+
142
+void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm)
143
+{
144
+ uint64_t *rd = vd;
145
+ uint64_t *rn = vn;
146
+ uint64_t *rm = vm;
147
+
148
+ rd[0] += s1_512(rn[0]) + rm[0];
149
+ rd[1] += s1_512(rn[1]) + rm[1];
150
+}
151
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/target/arm/translate-a64.c
154
+++ b/target/arm/translate-a64.c
155
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
156
tcg_temp_free_ptr(tcg_rn_ptr);
157
}
158
159
+/* Crypto three-reg SHA512
160
+ * 31 21 20 16 15 14 13 12 11 10 9 5 4 0
161
+ * +-----------------------+------+---+---+-----+--------+------+------+
162
+ * | 1 1 0 0 1 1 1 0 0 1 1 | Rm | 1 | O | 0 0 | opcode | Rn | Rd |
163
+ * +-----------------------+------+---+---+-----+--------+------+------+
164
+ */
165
+static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
166
+{
167
+ int opcode = extract32(insn, 10, 2);
168
+ int o = extract32(insn, 14, 1);
169
+ int rm = extract32(insn, 16, 5);
170
+ int rn = extract32(insn, 5, 5);
171
+ int rd = extract32(insn, 0, 5);
172
+ int feature;
173
+ CryptoThreeOpFn *genfn;
174
+
175
+ if (o == 0) {
176
+ switch (opcode) {
177
+ case 0: /* SHA512H */
178
+ feature = ARM_FEATURE_V8_SHA512;
179
+ genfn = gen_helper_crypto_sha512h;
180
+ break;
181
+ case 1: /* SHA512H2 */
182
+ feature = ARM_FEATURE_V8_SHA512;
183
+ genfn = gen_helper_crypto_sha512h2;
184
+ break;
185
+ case 2: /* SHA512SU1 */
186
+ feature = ARM_FEATURE_V8_SHA512;
187
+ genfn = gen_helper_crypto_sha512su1;
188
+ break;
189
+ default:
190
+ unallocated_encoding(s);
191
+ return;
192
+ }
204
+ }
193
+ } else {
205
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
194
+ unallocated_encoding(s);
206
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
195
+ return;
207
+ /* MCT_G1 is passed to External and GIC */
208
+ irq_id = EXT_GIC_ID_MCT_G1;
209
+ }
210
+ if (irq_id) {
211
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
212
+ is->ext_gic_irq[irq_id - 32]);
213
+ } else {
214
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
215
+ is->ext_combiner_irq[n]);
216
+ }
196
+ }
217
+ }
197
+
218
+ for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
198
+ if (!arm_dc_feature(s, feature)) {
219
+ /* these IDs are passed to Internal Combiner and External GIC */
199
+ unallocated_encoding(s);
220
+ grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
200
+ return;
221
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
201
+ }
222
+ irq_id = combiner_grp_to_gic_id[grp -
202
+
223
+ EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
203
+ if (!fp_access_check(s)) {
224
+
204
+ return;
225
+ if (irq_id) {
205
+ }
226
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
206
+
227
+ is->ext_gic_irq[irq_id - 32]);
207
+ if (genfn) {
228
+ }
208
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
209
+
210
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
211
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
212
+ tcg_rm_ptr = vec_full_reg_ptr(s, rm);
213
+
214
+ genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
215
+
216
+ tcg_temp_free_ptr(tcg_rd_ptr);
217
+ tcg_temp_free_ptr(tcg_rn_ptr);
218
+ tcg_temp_free_ptr(tcg_rm_ptr);
219
+ } else {
220
+ g_assert_not_reached();
221
+ }
229
+ }
222
+}
230
+}
223
+
231
+
224
+/* Crypto two-reg SHA512
232
+/*
225
+ * 31 12 11 10 9 5 4 0
233
+ * Get IRQ number from exynos4210 IRQ subsystem stub.
226
+ * +-----------------------------------------+--------+------+------+
234
+ * To identify IRQ source use internal combiner group and bit number
227
+ * | 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 | opcode | Rn | Rd |
235
+ * grp - group number
228
+ * +-----------------------------------------+--------+------+------+
236
+ * bit - bit number inside group
229
+ */
237
+ */
230
+static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
238
+uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
231
+{
239
+{
232
+ int opcode = extract32(insn, 10, 2);
240
+ return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
233
+ int rn = extract32(insn, 5, 5);
234
+ int rd = extract32(insn, 0, 5);
235
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
236
+ int feature;
237
+ CryptoTwoOpFn *genfn;
238
+
239
+ switch (opcode) {
240
+ case 0: /* SHA512SU0 */
241
+ feature = ARM_FEATURE_V8_SHA512;
242
+ genfn = gen_helper_crypto_sha512su0;
243
+ break;
244
+ default:
245
+ unallocated_encoding(s);
246
+ return;
247
+ }
248
+
249
+ if (!arm_dc_feature(s, feature)) {
250
+ unallocated_encoding(s);
251
+ return;
252
+ }
253
+
254
+ if (!fp_access_check(s)) {
255
+ return;
256
+ }
257
+
258
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
259
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
260
+
261
+ genfn(tcg_rd_ptr, tcg_rn_ptr);
262
+
263
+ tcg_temp_free_ptr(tcg_rd_ptr);
264
+ tcg_temp_free_ptr(tcg_rn_ptr);
265
+}
241
+}
266
+
242
+
267
/* C3.6 Data processing - SIMD, inc Crypto
243
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
268
*
244
0x09, 0x00, 0x00, 0x00 };
269
* As the decode gets a little complex we are using a table based
245
270
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
246
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
271
{ 0x4e280800, 0xff3e0c00, disas_crypto_aes },
247
index XXXXXXX..XXXXXXX 100644
272
{ 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
248
--- a/hw/intc/exynos4210_gic.c
273
{ 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
249
+++ b/hw/intc/exynos4210_gic.c
274
+ { 0xce608000, 0xffe0b000, disas_crypto_three_reg_sha512 },
250
@@ -XXX,XX +XXX,XX @@
275
+ { 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
251
#include "hw/arm/exynos4210.h"
276
{ 0x00000000, 0x00000000, NULL }
252
#include "qom/object.h"
277
};
253
254
-enum ExtGicId {
255
- EXT_GIC_ID_MDMA_LCD0 = 66,
256
- EXT_GIC_ID_PDMA0,
257
- EXT_GIC_ID_PDMA1,
258
- EXT_GIC_ID_TIMER0,
259
- EXT_GIC_ID_TIMER1,
260
- EXT_GIC_ID_TIMER2,
261
- EXT_GIC_ID_TIMER3,
262
- EXT_GIC_ID_TIMER4,
263
- EXT_GIC_ID_MCT_L0,
264
- EXT_GIC_ID_WDT,
265
- EXT_GIC_ID_RTC_ALARM,
266
- EXT_GIC_ID_RTC_TIC,
267
- EXT_GIC_ID_GPIO_XB,
268
- EXT_GIC_ID_GPIO_XA,
269
- EXT_GIC_ID_MCT_L1,
270
- EXT_GIC_ID_IEM_APC,
271
- EXT_GIC_ID_IEM_IEC,
272
- EXT_GIC_ID_NFC,
273
- EXT_GIC_ID_UART0,
274
- EXT_GIC_ID_UART1,
275
- EXT_GIC_ID_UART2,
276
- EXT_GIC_ID_UART3,
277
- EXT_GIC_ID_UART4,
278
- EXT_GIC_ID_MCT_G0,
279
- EXT_GIC_ID_I2C0,
280
- EXT_GIC_ID_I2C1,
281
- EXT_GIC_ID_I2C2,
282
- EXT_GIC_ID_I2C3,
283
- EXT_GIC_ID_I2C4,
284
- EXT_GIC_ID_I2C5,
285
- EXT_GIC_ID_I2C6,
286
- EXT_GIC_ID_I2C7,
287
- EXT_GIC_ID_SPI0,
288
- EXT_GIC_ID_SPI1,
289
- EXT_GIC_ID_SPI2,
290
- EXT_GIC_ID_MCT_G1,
291
- EXT_GIC_ID_USB_HOST,
292
- EXT_GIC_ID_USB_DEVICE,
293
- EXT_GIC_ID_MODEMIF,
294
- EXT_GIC_ID_HSMMC0,
295
- EXT_GIC_ID_HSMMC1,
296
- EXT_GIC_ID_HSMMC2,
297
- EXT_GIC_ID_HSMMC3,
298
- EXT_GIC_ID_SDMMC,
299
- EXT_GIC_ID_MIPI_CSI_4LANE,
300
- EXT_GIC_ID_MIPI_DSI_4LANE,
301
- EXT_GIC_ID_MIPI_CSI_2LANE,
302
- EXT_GIC_ID_MIPI_DSI_2LANE,
303
- EXT_GIC_ID_ONENAND_AUDI,
304
- EXT_GIC_ID_ROTATOR,
305
- EXT_GIC_ID_FIMC0,
306
- EXT_GIC_ID_FIMC1,
307
- EXT_GIC_ID_FIMC2,
308
- EXT_GIC_ID_FIMC3,
309
- EXT_GIC_ID_JPEG,
310
- EXT_GIC_ID_2D,
311
- EXT_GIC_ID_PCIe,
312
- EXT_GIC_ID_MIXER,
313
- EXT_GIC_ID_HDMI,
314
- EXT_GIC_ID_HDMI_I2C,
315
- EXT_GIC_ID_MFC,
316
- EXT_GIC_ID_TVENC,
317
-};
318
-
319
-enum ExtInt {
320
- EXT_GIC_ID_EXTINT0 = 48,
321
- EXT_GIC_ID_EXTINT1,
322
- EXT_GIC_ID_EXTINT2,
323
- EXT_GIC_ID_EXTINT3,
324
- EXT_GIC_ID_EXTINT4,
325
- EXT_GIC_ID_EXTINT5,
326
- EXT_GIC_ID_EXTINT6,
327
- EXT_GIC_ID_EXTINT7,
328
- EXT_GIC_ID_EXTINT8,
329
- EXT_GIC_ID_EXTINT9,
330
- EXT_GIC_ID_EXTINT10,
331
- EXT_GIC_ID_EXTINT11,
332
- EXT_GIC_ID_EXTINT12,
333
- EXT_GIC_ID_EXTINT13,
334
- EXT_GIC_ID_EXTINT14,
335
- EXT_GIC_ID_EXTINT15
336
-};
337
-
338
-/*
339
- * External GIC sources which are not from External Interrupt Combiner or
340
- * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
341
- * which is INTG16 in Internal Interrupt Combiner.
342
- */
343
-
344
-static const uint32_t
345
-combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
346
- /* int combiner groups 16-19 */
347
- { }, { }, { }, { },
348
- /* int combiner group 20 */
349
- { 0, EXT_GIC_ID_MDMA_LCD0 },
350
- /* int combiner group 21 */
351
- { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
352
- /* int combiner group 22 */
353
- { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
354
- EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
355
- /* int combiner group 23 */
356
- { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
357
- /* int combiner group 24 */
358
- { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
359
- /* int combiner group 25 */
360
- { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
361
- /* int combiner group 26 */
362
- { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
363
- EXT_GIC_ID_UART4 },
364
- /* int combiner group 27 */
365
- { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
366
- EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
367
- EXT_GIC_ID_I2C7 },
368
- /* int combiner group 28 */
369
- { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
370
- /* int combiner group 29 */
371
- { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
372
- EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
373
- /* int combiner group 30 */
374
- { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
375
- /* int combiner group 31 */
376
- { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
377
- /* int combiner group 32 */
378
- { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
379
- /* int combiner group 33 */
380
- { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
381
- /* int combiner group 34 */
382
- { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
383
- /* int combiner group 35 */
384
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
385
- /* int combiner group 36 */
386
- { EXT_GIC_ID_MIXER },
387
- /* int combiner group 37 */
388
- { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
389
- EXT_GIC_ID_EXTINT7 },
390
- /* groups 38-50 */
391
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
392
- /* int combiner group 51 */
393
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
394
- /* group 52 */
395
- { },
396
- /* int combiner group 53 */
397
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
398
- /* groups 54-63 */
399
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
400
-};
401
-
402
#define EXYNOS4210_GIC_NIRQ 160
403
404
#define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000
405
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
406
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
407
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
408
409
-/*
410
- * Initialize board IRQs.
411
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
412
- */
413
-void exynos4210_init_board_irqs(Exynos4210State *s)
414
-{
415
- uint32_t grp, bit, irq_id, n;
416
- Exynos4210Irq *is = &s->irqs;
417
-
418
- for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
419
- irq_id = 0;
420
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
421
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
422
- /* MCT_G0 is passed to External GIC */
423
- irq_id = EXT_GIC_ID_MCT_G0;
424
- }
425
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
426
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
427
- /* MCT_G1 is passed to External and GIC */
428
- irq_id = EXT_GIC_ID_MCT_G1;
429
- }
430
- if (irq_id) {
431
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
432
- is->ext_gic_irq[irq_id - 32]);
433
- } else {
434
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
435
- is->ext_combiner_irq[n]);
436
- }
437
- }
438
- for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
439
- /* these IDs are passed to Internal Combiner and External GIC */
440
- grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
441
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
442
- irq_id = combiner_grp_to_gic_id[grp -
443
- EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
444
-
445
- if (irq_id) {
446
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
447
- is->ext_gic_irq[irq_id - 32]);
448
- }
449
- }
450
-}
451
-
452
-/*
453
- * Get IRQ number from exynos4210 IRQ subsystem stub.
454
- * To identify IRQ source use internal combiner group and bit number
455
- * grp - group number
456
- * bit - bit number inside group
457
- */
458
-uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
459
-{
460
- return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
461
-}
462
-
463
-/********* GIC part *********/
464
-
465
#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
466
OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
278
467
279
--
468
--
280
2.16.1
469
2.25.1
281
282
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Switch the creation of the external GIC to the new-style "embedded in
2
state struct" approach, so we can easily refer to the object
3
elsewhere during realize.
2
4
3
Add minimal code needed to allow upstream Linux guest to boot.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-9-peter.maydell@linaro.org
8
---
9
include/hw/arm/exynos4210.h | 2 ++
10
include/hw/intc/exynos4210_gic.h | 43 ++++++++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 10 ++++----
12
hw/intc/exynos4210_gic.c | 17 ++-----------
13
MAINTAINERS | 2 +-
14
5 files changed, 53 insertions(+), 21 deletions(-)
15
create mode 100644 include/hw/intc/exynos4210_gic.h
4
16
5
Cc: Peter Maydell <peter.maydell@linaro.org>
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
6
Cc: Jason Wang <jasowang@redhat.com>
7
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
9
Cc: Michael S. Tsirkin <mst@redhat.com>
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/misc/Makefile.objs | 1 +
19
include/hw/misc/imx7_gpr.h | 28 ++++++++++
20
hw/misc/imx7_gpr.c | 124 +++++++++++++++++++++++++++++++++++++++++++++
21
hw/misc/trace-events | 4 ++
22
4 files changed, 157 insertions(+)
23
create mode 100644 include/hw/misc/imx7_gpr.h
24
create mode 100644 hw/misc/imx7_gpr.c
25
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/Makefile.objs
19
--- a/include/hw/arm/exynos4210.h
29
+++ b/hw/misc/Makefile.objs
20
+++ b/include/hw/arm/exynos4210.h
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx6_src.o
21
@@ -XXX,XX +XXX,XX @@
31
obj-$(CONFIG_IMX) += imx7_ccm.o
22
#include "hw/or-irq.h"
32
obj-$(CONFIG_IMX) += imx2_wdt.o
23
#include "hw/sysbus.h"
33
obj-$(CONFIG_IMX) += imx7_snvs.o
24
#include "hw/cpu/a9mpcore.h"
34
+obj-$(CONFIG_IMX) += imx7_gpr.o
25
+#include "hw/intc/exynos4210_gic.h"
35
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
26
#include "target/arm/cpu-qom.h"
36
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
27
#include "qom/object.h"
37
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
28
38
diff --git a/include/hw/misc/imx7_gpr.h b/include/hw/misc/imx7_gpr.h
29
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
30
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
31
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
32
A9MPPrivState a9mpcore;
33
+ Exynos4210GicState ext_gic;
34
};
35
36
#define TYPE_EXYNOS4210_SOC "exynos4210"
37
diff --git a/include/hw/intc/exynos4210_gic.h b/include/hw/intc/exynos4210_gic.h
39
new file mode 100644
38
new file mode 100644
40
index XXXXXXX..XXXXXXX
39
index XXXXXXX..XXXXXXX
41
--- /dev/null
40
--- /dev/null
42
+++ b/include/hw/misc/imx7_gpr.h
41
+++ b/include/hw/intc/exynos4210_gic.h
43
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
44
+/*
43
+/*
45
+ * Copyright (c) 2017, Impinj, Inc.
44
+ * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c
46
+ *
45
+ *
47
+ * i.MX7 GPR IP block emulation code
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
48
+ *
49
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
50
+ *
50
+ *
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * See the COPYING file in the top-level directory.
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
53
+ */
63
+ */
64
+#ifndef HW_INTC_EXYNOS4210_GIC_H
65
+#define HW_INTC_EXYNOS4210_GIC_H
54
+
66
+
55
+#ifndef IMX7_GPR_H
56
+#define IMX7_GPR_H
57
+
58
+#include "qemu/bitops.h"
59
+#include "hw/sysbus.h"
67
+#include "hw/sysbus.h"
60
+
68
+
61
+#define TYPE_IMX7_GPR "imx7.gpr"
69
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
62
+#define IMX7_GPR(obj) OBJECT_CHECK(IMX7GPRState, (obj), TYPE_IMX7_GPR)
70
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
63
+
71
+
64
+typedef struct IMX7GPRState {
72
+#define EXYNOS4210_GIC_NCPUS 2
65
+ /* <private> */
73
+
74
+struct Exynos4210GicState {
66
+ SysBusDevice parent_obj;
75
+ SysBusDevice parent_obj;
67
+
76
+
68
+ MemoryRegion mmio;
77
+ MemoryRegion cpu_container;
69
+} IMX7GPRState;
78
+ MemoryRegion dist_container;
70
+
79
+ MemoryRegion cpu_alias[EXYNOS4210_GIC_NCPUS];
71
+#endif /* IMX7_GPR_H */
80
+ MemoryRegion dist_alias[EXYNOS4210_GIC_NCPUS];
72
diff --git a/hw/misc/imx7_gpr.c b/hw/misc/imx7_gpr.c
81
+ uint32_t num_cpu;
73
new file mode 100644
82
+ DeviceState *gic;
74
index XXXXXXX..XXXXXXX
75
--- /dev/null
76
+++ b/hw/misc/imx7_gpr.c
77
@@ -XXX,XX +XXX,XX @@
78
+/*
79
+ * Copyright (c) 2018, Impinj, Inc.
80
+ *
81
+ * i.MX7 GPR IP block emulation code
82
+ *
83
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
84
+ *
85
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
86
+ * See the COPYING file in the top-level directory.
87
+ *
88
+ * Bare minimum emulation code needed to support being able to shut
89
+ * down linux guest gracefully.
90
+ */
91
+
92
+#include "qemu/osdep.h"
93
+#include "hw/misc/imx7_gpr.h"
94
+#include "qemu/log.h"
95
+#include "sysemu/sysemu.h"
96
+
97
+#include "trace.h"
98
+
99
+enum IMX7GPRRegisters {
100
+ IOMUXC_GPR0 = 0x00,
101
+ IOMUXC_GPR1 = 0x04,
102
+ IOMUXC_GPR2 = 0x08,
103
+ IOMUXC_GPR3 = 0x0c,
104
+ IOMUXC_GPR4 = 0x10,
105
+ IOMUXC_GPR5 = 0x14,
106
+ IOMUXC_GPR6 = 0x18,
107
+ IOMUXC_GPR7 = 0x1c,
108
+ IOMUXC_GPR8 = 0x20,
109
+ IOMUXC_GPR9 = 0x24,
110
+ IOMUXC_GPR10 = 0x28,
111
+ IOMUXC_GPR11 = 0x2c,
112
+ IOMUXC_GPR12 = 0x30,
113
+ IOMUXC_GPR13 = 0x34,
114
+ IOMUXC_GPR14 = 0x38,
115
+ IOMUXC_GPR15 = 0x3c,
116
+ IOMUXC_GPR16 = 0x40,
117
+ IOMUXC_GPR17 = 0x44,
118
+ IOMUXC_GPR18 = 0x48,
119
+ IOMUXC_GPR19 = 0x4c,
120
+ IOMUXC_GPR20 = 0x50,
121
+ IOMUXC_GPR21 = 0x54,
122
+ IOMUXC_GPR22 = 0x58,
123
+};
83
+};
124
+
84
+
125
+#define IMX7D_GPR1_IRQ_MASK BIT(12)
85
+#endif
126
+#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK BIT(13)
86
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
127
+#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK BIT(14)
128
+#define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK (0x3 << 13)
129
+#define IMX7D_GPR1_ENET1_CLK_DIR_MASK BIT(17)
130
+#define IMX7D_GPR1_ENET2_CLK_DIR_MASK BIT(18)
131
+#define IMX7D_GPR1_ENET_CLK_DIR_MASK (0x3 << 17)
132
+
133
+#define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI BIT(4)
134
+#define IMX7D_GPR12_PCIE_PHY_REFCLK_SEL BIT(5)
135
+#define IMX7D_GPR22_PCIE_PHY_PLL_LOCKED BIT(31)
136
+
137
+
138
+static uint64_t imx7_gpr_read(void *opaque, hwaddr offset, unsigned size)
139
+{
140
+ trace_imx7_gpr_read(offset);
141
+
142
+ if (offset == IOMUXC_GPR22) {
143
+ return IMX7D_GPR22_PCIE_PHY_PLL_LOCKED;
144
+ }
145
+
146
+ return 0;
147
+}
148
+
149
+static void imx7_gpr_write(void *opaque, hwaddr offset,
150
+ uint64_t v, unsigned size)
151
+{
152
+ trace_imx7_gpr_write(offset, v);
153
+}
154
+
155
+static const struct MemoryRegionOps imx7_gpr_ops = {
156
+ .read = imx7_gpr_read,
157
+ .write = imx7_gpr_write,
158
+ .endianness = DEVICE_NATIVE_ENDIAN,
159
+ .impl = {
160
+ /*
161
+ * Our device would not work correctly if the guest was doing
162
+ * unaligned access. This might not be a limitation on the
163
+ * real device but in practice there is no reason for a guest
164
+ * to access this device unaligned.
165
+ */
166
+ .min_access_size = 4,
167
+ .max_access_size = 4,
168
+ .unaligned = false,
169
+ },
170
+};
171
+
172
+static void imx7_gpr_init(Object *obj)
173
+{
174
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
175
+ IMX7GPRState *s = IMX7_GPR(obj);
176
+
177
+ memory_region_init_io(&s->mmio, obj, &imx7_gpr_ops, s,
178
+ TYPE_IMX7_GPR, 64 * 1024);
179
+ sysbus_init_mmio(sd, &s->mmio);
180
+}
181
+
182
+static void imx7_gpr_class_init(ObjectClass *klass, void *data)
183
+{
184
+ DeviceClass *dc = DEVICE_CLASS(klass);
185
+
186
+ dc->desc = "i.MX7 General Purpose Registers Module";
187
+}
188
+
189
+static const TypeInfo imx7_gpr_info = {
190
+ .name = TYPE_IMX7_GPR,
191
+ .parent = TYPE_SYS_BUS_DEVICE,
192
+ .instance_size = sizeof(IMX7GPRState),
193
+ .instance_init = imx7_gpr_init,
194
+ .class_init = imx7_gpr_class_init,
195
+};
196
+
197
+static void imx7_gpr_register_type(void)
198
+{
199
+ type_register_static(&imx7_gpr_info);
200
+}
201
+type_init(imx7_gpr_register_type)
202
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
203
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
204
--- a/hw/misc/trace-events
88
--- a/hw/arm/exynos4210.c
205
+++ b/hw/misc/trace-events
89
+++ b/hw/arm/exynos4210.c
206
@@ -XXX,XX +XXX,XX @@ mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC
90
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
207
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
91
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
208
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
92
209
msf2_sysreg_write_pll_status(void) "Invalid write to read only PLL status register"
93
/* External GIC */
210
+
94
- dev = qdev_new("exynos4210.gic");
211
+#hw/misc/imx7_gpr.c
95
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
212
+imx7_gpr_read(uint64_t offset) "addr 0x%08" HWADDR_PRIx
96
- busdev = SYS_BUS_DEVICE(dev);
213
+imx7_gpr_write(uint64_t offset, uint64_t value) "addr 0x%08" HWADDR_PRIx "value 0x%08" HWADDR_PRIx
97
- sysbus_realize_and_unref(busdev, &error_fatal);
98
+ qdev_prop_set_uint32(DEVICE(&s->ext_gic), "num-cpu", EXYNOS4210_NCPUS);
99
+ busdev = SYS_BUS_DEVICE(&s->ext_gic);
100
+ sysbus_realize(busdev, &error_fatal);
101
/* Map CPU interface */
102
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
103
/* Map Distributer interface */
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
105
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
106
}
107
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
108
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
109
+ s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
110
}
111
112
/* Internal Interrupt Combiner */
113
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
114
}
115
116
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
117
+ object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
118
}
119
120
static void exynos4210_class_init(ObjectClass *klass, void *data)
121
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/intc/exynos4210_gic.c
124
+++ b/hw/intc/exynos4210_gic.c
125
@@ -XXX,XX +XXX,XX @@
126
#include "qemu/module.h"
127
#include "hw/irq.h"
128
#include "hw/qdev-properties.h"
129
+#include "hw/intc/exynos4210_gic.h"
130
#include "hw/arm/exynos4210.h"
131
#include "qom/object.h"
132
133
@@ -XXX,XX +XXX,XX @@
134
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
135
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
136
137
-#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
138
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
139
-
140
-struct Exynos4210GicState {
141
- SysBusDevice parent_obj;
142
-
143
- MemoryRegion cpu_container;
144
- MemoryRegion dist_container;
145
- MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
146
- MemoryRegion dist_alias[EXYNOS4210_NCPUS];
147
- uint32_t num_cpu;
148
- DeviceState *gic;
149
-};
150
-
151
static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
152
{
153
Exynos4210GicState *s = (Exynos4210GicState *)opaque;
154
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp)
155
* enough room for the cpu numbers. gcc 9.2.1 on 32-bit x86
156
* doesn't figure this out, otherwise and gives spurious warnings.
157
*/
158
- assert(n <= EXYNOS4210_NCPUS);
159
+ assert(n <= EXYNOS4210_GIC_NCPUS);
160
for (i = 0; i < n; i++) {
161
/* Map CPU interface per SMP Core */
162
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
163
diff --git a/MAINTAINERS b/MAINTAINERS
164
index XXXXXXX..XXXXXXX 100644
165
--- a/MAINTAINERS
166
+++ b/MAINTAINERS
167
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
168
L: qemu-arm@nongnu.org
169
S: Odd Fixes
170
F: hw/*/exynos*
171
-F: include/hw/arm/exynos4210.h
172
+F: include/hw/*/exynos*
173
174
Calxeda Highbank
175
M: Rob Herring <robh@kernel.org>
214
--
176
--
215
2.16.1
177
2.25.1
216
217
diff view generated by jsdifflib
1
Make the load of the exception vector from the vector table honour
1
The only time we use the ext_gic_irq[] array in the Exynos4210Irq
2
the SAU and any bus error on the load (possibly provoking a derived
2
struct is during realize of the SoC -- we initialize it with the
3
exception), rather than simply aborting if the load fails.
3
input IRQs of the external GIC device, and then connect those to
4
outputs of other devices further on in realize (including in the
5
exynos4210_init_board_irqs() function). Now that the ext_gic object
6
is easily accessible as s->ext_gic we can make the connections
7
directly from one device to the other without going via this array.
4
8
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 1517324542-6607-7-git-send-email-peter.maydell@linaro.org
11
Message-id: 20220404154658.565020-10-peter.maydell@linaro.org
8
---
12
---
9
target/arm/helper.c | 71 +++++++++++++++++++++++++++++++++++++++++------------
13
include/hw/arm/exynos4210.h | 1 -
10
1 file changed, 55 insertions(+), 16 deletions(-)
14
hw/arm/exynos4210.c | 12 ++++++------
15
2 files changed, 6 insertions(+), 7 deletions(-)
11
16
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
19
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/helper.c
20
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
21
@@ -XXX,XX +XXX,XX @@
22
typedef struct Exynos4210Irq {
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
25
- qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
26
} Exynos4210Irq;
27
28
struct Exynos4210State {
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
34
{
35
uint32_t grp, bit, irq_id, n;
36
Exynos4210Irq *is = &s->irqs;
37
+ DeviceState *extgicdev = DEVICE(&s->ext_gic);
38
39
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
40
irq_id = 0;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
42
}
43
if (irq_id) {
44
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
45
- is->ext_gic_irq[irq_id - 32]);
46
+ qdev_get_gpio_in(extgicdev,
47
+ irq_id - 32));
48
} else {
49
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
50
is->ext_combiner_irq[n]);
51
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
52
53
if (irq_id) {
54
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
55
- is->ext_gic_irq[irq_id - 32]);
56
+ qdev_get_gpio_in(extgicdev,
57
+ irq_id - 32));
58
}
17
}
59
}
18
}
60
}
19
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
20
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
62
sysbus_connect_irq(busdev, n,
21
+static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
63
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
22
+ uint32_t *pvec)
23
{
24
CPUState *cs = CPU(cpu);
25
CPUARMState *env = &cpu->env;
26
MemTxResult result;
27
- hwaddr vec = env->v7m.vecbase[targets_secure] + exc * 4;
28
- uint32_t addr;
29
+ uint32_t addr = env->v7m.vecbase[targets_secure] + exc * 4;
30
+ uint32_t vector_entry;
31
+ MemTxAttrs attrs = {};
32
+ ARMMMUIdx mmu_idx;
33
+ bool exc_secure;
34
+
35
+ mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, targets_secure, true);
36
37
- addr = address_space_ldl(cs->as, vec,
38
- MEMTXATTRS_UNSPECIFIED, &result);
39
+ /* We don't do a get_phys_addr() here because the rules for vector
40
+ * loads are special: they always use the default memory map, and
41
+ * the default memory map permits reads from all addresses.
42
+ * Since there's no easy way to pass through to pmsav8_mpu_lookup()
43
+ * that we want this special case which would always say "yes",
44
+ * we just do the SAU lookup here followed by a direct physical load.
45
+ */
46
+ attrs.secure = targets_secure;
47
+ attrs.user = false;
48
+
49
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
50
+ V8M_SAttributes sattrs = {};
51
+
52
+ v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, &sattrs);
53
+ if (sattrs.ns) {
54
+ attrs.secure = false;
55
+ } else if (!targets_secure) {
56
+ /* NS access to S memory */
57
+ goto load_fail;
58
+ }
59
+ }
60
+
61
+ vector_entry = address_space_ldl(arm_addressspace(cs, attrs), addr,
62
+ attrs, &result);
63
if (result != MEMTX_OK) {
64
- /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
65
- * which would then be immediately followed by our failing to load
66
- * the entry vector for that HardFault, which is a Lockup case.
67
- * Since we don't model Lockup, we just report this guest error
68
- * via cpu_abort().
69
- */
70
- cpu_abort(cs, "Failed to read from %s exception vector table "
71
- "entry %08x\n", targets_secure ? "secure" : "nonsecure",
72
- (unsigned)vec);
73
+ goto load_fail;
74
}
64
}
75
- return addr;
65
- for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
76
+ *pvec = vector_entry;
66
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
77
+ return true;
67
- }
78
+
68
79
+load_fail:
69
/* Internal Interrupt Combiner */
80
+ /* All vector table fetch fails are reported as HardFault, with
70
dev = qdev_new("exynos4210.combiner");
81
+ * HFSR.VECTTBL and .FORCED set. (FORCED is set because
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
82
+ * technically the underlying exception is a MemManage or BusFault
72
busdev = SYS_BUS_DEVICE(dev);
83
+ * that is escalated to HardFault.) This is a terminal exception,
73
sysbus_realize_and_unref(busdev, &error_fatal);
84
+ * so we will either take the HardFault immediately or else enter
74
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
85
+ * lockup (the latter case is handled in armv7m_nvic_set_pending_derived()).
75
- sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
86
+ */
76
+ sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
87
+ exc_secure = targets_secure ||
88
+ !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK);
89
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
90
+ armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
91
+ return false;
92
}
93
94
static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
95
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
96
return;
97
}
77
}
98
78
exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
99
- addr = arm_v7m_load_vector(cpu, exc, targets_secure);
79
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
100
+ if (!arm_v7m_load_vector(cpu, exc, targets_secure, &addr)) {
101
+ /* Vector load failed: derived exception */
102
+ v7m_exception_taken(cpu, lr, true, true);
103
+ return;
104
+ }
105
106
/* Now we've done everything that might cause a derived exception
107
* we can go ahead and activate whichever exception we're going to
108
--
80
--
109
2.16.1
81
2.25.1
110
111
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
The function exynos4210_combiner_get_gpioin() currently lives in
2
exynos4210_combiner.c, but it isn't really part of the combiner
3
device itself -- it is a function that implements the wiring up of
4
some interrupt sources to multiple combiner inputs. Move it to live
5
with the other SoC-level code in exynos4210.c, along with a few
6
macros previously defined in exynos4210.h which are now used only
7
in exynos4210.c.
2
8
3
IP block found on several generations of i.MX family does not use
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
vanilla SDHCI implementation and it comes with a number of quirks.
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-11-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 11 -----
14
hw/arm/exynos4210.c | 82 +++++++++++++++++++++++++++++++++++
15
hw/intc/exynos4210_combiner.c | 77 --------------------------------
16
3 files changed, 82 insertions(+), 88 deletions(-)
5
17
6
Introduce i.MX SDHCI subtype of SDHCI block to add code necessary to
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
7
support unmodified Linux guest driver.
8
9
Cc: Peter Maydell <peter.maydell@linaro.org>
10
Cc: Jason Wang <jasowang@redhat.com>
11
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
13
Cc: Michael S. Tsirkin <mst@redhat.com>
14
Cc: qemu-devel@nongnu.org
15
Cc: qemu-arm@nongnu.org
16
Cc: yurovsky@gmail.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
[PMM: define and use ESDHC_UNDOCUMENTED_REG27]
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/sd/sdhci-internal.h | 23 +++++
24
include/hw/sd/sdhci.h | 13 +++
25
hw/sd/sdhci.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++-
26
3 files changed, 265 insertions(+), 1 deletion(-)
27
28
diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
29
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/sd/sdhci-internal.h
20
--- a/include/hw/arm/exynos4210.h
31
+++ b/hw/sd/sdhci-internal.h
21
+++ b/include/hw/arm/exynos4210.h
32
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
33
23
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
34
/* R/W Host control Register 0x0 */
24
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
35
#define SDHC_HOSTCTL 0x28
25
36
+#define SDHC_CTRL_LED 0x01
26
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
37
#define SDHC_CTRL_DMA_CHECK_MASK 0x18
27
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
38
#define SDHC_CTRL_SDMA 0x00
28
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
39
#define SDHC_CTRL_ADMA1_32 0x08
29
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
40
#define SDHC_CTRL_ADMA2_32 0x10
30
-
41
#define SDHC_CTRL_ADMA2_64 0x18
31
/* IRQs number for external and internal GIC */
42
#define SDHC_DMA_TYPE(x) ((x) & SDHC_CTRL_DMA_CHECK_MASK)
32
#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
43
+#define SDHC_CTRL_4BITBUS 0x02
33
#define EXYNOS4210_INT_GIC_NIRQ 64
44
+#define SDHC_CTRL_8BITBUS 0x20
34
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
45
+#define SDHC_CTRL_CDTEST_INS 0x40
35
* bit - bit number inside group */
46
+#define SDHC_CTRL_CDTEST_EN 0x80
36
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
47
+
37
48
38
-/*
49
/* R/W Power Control Register 0x0 */
39
- * Get Combiner input GPIO into irqs structure
50
#define SDHC_PWRCON 0x29
40
- */
51
@@ -XXX,XX +XXX,XX @@ enum {
41
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
52
sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */
42
- int ext);
43
-
44
/*
45
* exynos4210 UART
46
*/
47
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/exynos4210.c
50
+++ b/hw/arm/exynos4210.c
51
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
52
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
53
};
53
};
54
54
55
+extern const VMStateDescription sdhci_vmstate;
55
+#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp) * 8 + (bit))
56
+
56
+#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
57
+
57
+#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
58
+#define ESDHC_MIX_CTRL 0x48
58
+ ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
59
+#define ESDHC_VENDOR_SPEC 0xc0
59
+
60
+#define ESDHC_DLL_CTRL 0x60
60
/*
61
+
61
* Initialize board IRQs.
62
+#define ESDHC_TUNING_CTRL 0xcc
62
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
63
+#define ESDHC_TUNE_CTRL_STATUS 0x68
63
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
64
+#define ESDHC_WTMK_LVL 0x44
64
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
65
+
65
}
66
+/* Undocumented register used by guests working around erratum ERR004536 */
67
+#define ESDHC_UNDOCUMENTED_REG27 0x6c
68
+
69
+#define ESDHC_CTRL_4BITBUS (0x1 << 1)
70
+#define ESDHC_CTRL_8BITBUS (0x2 << 1)
71
+
72
#endif
73
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
74
index XXXXXXX..XXXXXXX 100644
75
--- a/include/hw/sd/sdhci.h
76
+++ b/include/hw/sd/sdhci.h
77
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
78
AddressSpace sysbus_dma_as;
79
AddressSpace *dma_as;
80
MemoryRegion *dma_mr;
81
+ const MemoryRegionOps *io_ops;
82
83
QEMUTimer *insert_timer; /* timer for 'changing' sd card. */
84
QEMUTimer *transfer_timer;
85
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
86
87
/* Configurable properties */
88
bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
89
+ uint32_t quirks;
90
} SDHCIState;
91
66
92
+/*
67
+/*
93
+ * Controller does not provide transfer-complete interrupt when not
68
+ * Get Combiner input GPIO into irqs structure
94
+ * busy.
95
+ *
96
+ * NOTE: This definition is taken out of Linux kernel and so the
97
+ * original bit number is preserved
98
+ */
69
+ */
99
+#define SDHCI_QUIRK_NO_BUSY_IRQ BIT(14)
70
+static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
100
+
71
+ DeviceState *dev, int ext)
101
#define TYPE_PCI_SDHCI "sdhci-pci"
102
#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI)
103
104
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
105
#define SYSBUS_SDHCI(obj) \
106
OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI)
107
108
+#define TYPE_IMX_USDHC "imx-usdhc"
109
+
110
#endif /* SDHCI_H */
111
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/hw/sd/sdhci.c
114
+++ b/hw/sd/sdhci.c
115
@@ -XXX,XX +XXX,XX @@ static void sdhci_send_command(SDHCIState *s)
116
}
117
}
118
119
- if ((s->norintstsen & SDHC_NISEN_TRSCMP) &&
120
+ if (!(s->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
121
+ (s->norintstsen & SDHC_NISEN_TRSCMP) &&
122
(s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
123
s->norintsts |= SDHC_NIS_TRSCMP;
124
}
125
@@ -XXX,XX +XXX,XX @@ static void sdhci_initfn(SDHCIState *s)
126
127
s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
128
s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s);
129
+
130
+ s->io_ops = &sdhci_mmio_ops;
131
}
132
133
static void sdhci_uninitfn(SDHCIState *s)
134
@@ -XXX,XX +XXX,XX @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
135
}
136
137
sysbus_init_irq(sbd, &s->irq);
138
+
139
+ memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
140
+ SDHC_REGISTERS_MAP_SIZE);
141
+
142
sysbus_init_mmio(sbd, &s->iomem);
143
}
144
145
@@ -XXX,XX +XXX,XX @@ static const TypeInfo sdhci_bus_info = {
146
.class_init = sdhci_bus_class_init,
147
};
148
149
+static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
150
+{
72
+{
151
+ SDHCIState *s = SYSBUS_SDHCI(opaque);
73
+ int n;
152
+ uint32_t ret;
74
+ int bit;
153
+ uint16_t hostctl;
75
+ int max;
154
+
76
+ qemu_irq *irq;
155
+ switch (offset) {
77
+
156
+ default:
78
+ max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
157
+ return sdhci_read(opaque, offset, size);
79
+ EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
158
+
80
+ irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
159
+ case SDHC_HOSTCTL:
81
+
160
+ /*
82
+ /*
161
+ * For a detailed explanation on the following bit
83
+ * Some IRQs of Int/External Combiner are going to two Combiners groups,
162
+ * manipulation code see comments in a similar part of
84
+ * so let split them.
163
+ * usdhc_write()
85
+ */
164
+ */
86
+ for (n = 0; n < max; n++) {
165
+ hostctl = SDHC_DMA_TYPE(s->hostctl) << (8 - 3);
87
+
166
+
88
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
167
+ if (s->hostctl & SDHC_CTRL_8BITBUS) {
89
+
168
+ hostctl |= ESDHC_CTRL_8BITBUS;
90
+ switch (n) {
91
+ /* MDNIE_LCD1 INTG1 */
92
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
93
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
94
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
95
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
96
+ continue;
97
+
98
+ /* TMU INTG3 */
99
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
100
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
101
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
102
+ continue;
103
+
104
+ /* LCD1 INTG12 */
105
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
106
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
107
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
108
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
109
+ continue;
110
+
111
+ /* Multi-Core Timer INTG12 */
112
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
113
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
114
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
115
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
116
+ continue;
117
+
118
+ /* Multi-Core Timer INTG35 */
119
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
120
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
121
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
122
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
123
+ continue;
124
+
125
+ /* Multi-Core Timer INTG51 */
126
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
127
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
128
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
129
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
130
+ continue;
131
+
132
+ /* Multi-Core Timer INTG53 */
133
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
134
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
135
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
136
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
137
+ continue;
169
+ }
138
+ }
170
+
139
+
171
+ if (s->hostctl & SDHC_CTRL_4BITBUS) {
140
+ irq[n] = qdev_get_gpio_in(dev, n);
172
+ hostctl |= ESDHC_CTRL_4BITBUS;
173
+ }
174
+
175
+ ret = hostctl;
176
+ ret |= (uint32_t)s->blkgap << 16;
177
+ ret |= (uint32_t)s->wakcon << 24;
178
+
179
+ break;
180
+
181
+ case ESDHC_DLL_CTRL:
182
+ case ESDHC_TUNE_CTRL_STATUS:
183
+ case ESDHC_UNDOCUMENTED_REG27:
184
+ case ESDHC_TUNING_CTRL:
185
+ case ESDHC_VENDOR_SPEC:
186
+ case ESDHC_MIX_CTRL:
187
+ case ESDHC_WTMK_LVL:
188
+ ret = 0;
189
+ break;
190
+ }
191
+
192
+ return ret;
193
+}
194
+
195
+static void
196
+usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
197
+{
198
+ SDHCIState *s = SYSBUS_SDHCI(opaque);
199
+ uint8_t hostctl;
200
+ uint32_t value = (uint32_t)val;
201
+
202
+ switch (offset) {
203
+ case ESDHC_DLL_CTRL:
204
+ case ESDHC_TUNE_CTRL_STATUS:
205
+ case ESDHC_UNDOCUMENTED_REG27:
206
+ case ESDHC_TUNING_CTRL:
207
+ case ESDHC_WTMK_LVL:
208
+ case ESDHC_VENDOR_SPEC:
209
+ break;
210
+
211
+ case SDHC_HOSTCTL:
212
+ /*
213
+ * Here's What ESDHCI has at offset 0x28 (SDHC_HOSTCTL)
214
+ *
215
+ * 7 6 5 4 3 2 1 0
216
+ * |-----------+--------+--------+-----------+----------+---------|
217
+ * | Card | Card | Endian | DATA3 | Data | Led |
218
+ * | Detect | Detect | Mode | as Card | Transfer | Control |
219
+ * | Signal | Test | | Detection | Width | |
220
+ * | Selection | Level | | Pin | | |
221
+ * |-----------+--------+--------+-----------+----------+---------|
222
+ *
223
+ * and 0x29
224
+ *
225
+ * 15 10 9 8
226
+ * |----------+------|
227
+ * | Reserved | DMA |
228
+ * | | Sel. |
229
+ * | | |
230
+ * |----------+------|
231
+ *
232
+ * and here's what SDCHI spec expects those offsets to be:
233
+ *
234
+ * 0x28 (Host Control Register)
235
+ *
236
+ * 7 6 5 4 3 2 1 0
237
+ * |--------+--------+----------+------+--------+----------+---------|
238
+ * | Card | Card | Extended | DMA | High | Data | LED |
239
+ * | Detect | Detect | Data | Sel. | Speed | Transfer | Control |
240
+ * | Signal | Test | Transfer | | Enable | Width | |
241
+ * | Sel. | Level | Width | | | | |
242
+ * |--------+--------+----------+------+--------+----------+---------|
243
+ *
244
+ * and 0x29 (Power Control Register)
245
+ *
246
+ * |----------------------------------|
247
+ * | Power Control Register |
248
+ * | |
249
+ * | Description omitted, |
250
+ * | since it has no analog in ESDHCI |
251
+ * | |
252
+ * |----------------------------------|
253
+ *
254
+ * Since offsets 0x2A and 0x2B should be compatible between
255
+ * both IP specs we only need to reconcile least 16-bit of the
256
+ * word we've been given.
257
+ */
258
+
259
+ /*
260
+ * First, save bits 7 6 and 0 since they are identical
261
+ */
262
+ hostctl = value & (SDHC_CTRL_LED |
263
+ SDHC_CTRL_CDTEST_INS |
264
+ SDHC_CTRL_CDTEST_EN);
265
+ /*
266
+ * Second, split "Data Transfer Width" from bits 2 and 1 in to
267
+ * bits 5 and 1
268
+ */
269
+ if (value & ESDHC_CTRL_8BITBUS) {
270
+ hostctl |= SDHC_CTRL_8BITBUS;
271
+ }
272
+
273
+ if (value & ESDHC_CTRL_4BITBUS) {
274
+ hostctl |= ESDHC_CTRL_4BITBUS;
275
+ }
276
+
277
+ /*
278
+ * Third, move DMA select from bits 9 and 8 to bits 4 and 3
279
+ */
280
+ hostctl |= SDHC_DMA_TYPE(value >> (8 - 3));
281
+
282
+ /*
283
+ * Now place the corrected value into low 16-bit of the value
284
+ * we are going to give standard SDHCI write function
285
+ *
286
+ * NOTE: This transformation should be the inverse of what can
287
+ * be found in drivers/mmc/host/sdhci-esdhc-imx.c in Linux
288
+ * kernel
289
+ */
290
+ value &= ~UINT16_MAX;
291
+ value |= hostctl;
292
+ value |= (uint16_t)s->pwrcon << 8;
293
+
294
+ sdhci_write(opaque, offset, value, size);
295
+ break;
296
+
297
+ case ESDHC_MIX_CTRL:
298
+ /*
299
+ * So, when SD/MMC stack in Linux tries to write to "Transfer
300
+ * Mode Register", ESDHC i.MX quirk code will translate it
301
+ * into a write to ESDHC_MIX_CTRL, so we do the opposite in
302
+ * order to get where we started
303
+ *
304
+ * Note that Auto CMD23 Enable bit is located in a wrong place
305
+ * on i.MX, but since it is not used by QEMU we do not care.
306
+ *
307
+ * We don't want to call sdhci_write(.., SDHC_TRNMOD, ...)
308
+ * here becuase it will result in a call to
309
+ * sdhci_send_command(s) which we don't want.
310
+ *
311
+ */
312
+ s->trnmod = value & UINT16_MAX;
313
+ break;
314
+ case SDHC_TRNMOD:
315
+ /*
316
+ * Similar to above, but this time a write to "Command
317
+ * Register" will be translated into a 4-byte write to
318
+ * "Transfer Mode register" where lower 16-bit of value would
319
+ * be set to zero. So what we do is fill those bits with
320
+ * cached value from s->trnmod and let the SDHCI
321
+ * infrastructure handle the rest
322
+ */
323
+ sdhci_write(opaque, offset, val | s->trnmod, size);
324
+ break;
325
+ case SDHC_BLKSIZE:
326
+ /*
327
+ * ESDHCI does not implement "Host SDMA Buffer Boundary", and
328
+ * Linux driver will try to zero this field out which will
329
+ * break the rest of SDHCI emulation.
330
+ *
331
+ * Linux defaults to maximum possible setting (512K boundary)
332
+ * and it seems to be the only option that i.MX IP implements,
333
+ * so we artificially set it to that value.
334
+ */
335
+ val |= 0x7 << 12;
336
+ /* FALLTHROUGH */
337
+ default:
338
+ sdhci_write(opaque, offset, val, size);
339
+ break;
340
+ }
141
+ }
341
+}
142
+}
342
+
143
+
343
+
144
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
344
+static const MemoryRegionOps usdhc_mmio_ops = {
145
0x09, 0x00, 0x00, 0x00 };
345
+ .read = usdhc_read,
146
346
+ .write = usdhc_write,
147
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
347
+ .valid = {
148
index XXXXXXX..XXXXXXX 100644
348
+ .min_access_size = 1,
149
--- a/hw/intc/exynos4210_combiner.c
349
+ .max_access_size = 4,
150
+++ b/hw/intc/exynos4210_combiner.c
350
+ .unaligned = false
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_combiner = {
351
+ },
152
}
352
+ .endianness = DEVICE_LITTLE_ENDIAN,
153
};
353
+};
154
354
+
155
-/*
355
+static void imx_usdhc_init(Object *obj)
156
- * Get Combiner input GPIO into irqs structure
356
+{
157
- */
357
+ SDHCIState *s = SYSBUS_SDHCI(obj);
158
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
358
+
159
- int ext)
359
+ s->io_ops = &usdhc_mmio_ops;
160
-{
360
+ s->quirks = SDHCI_QUIRK_NO_BUSY_IRQ;
161
- int n;
361
+}
162
- int bit;
362
+
163
- int max;
363
+static const TypeInfo imx_usdhc_info = {
164
- qemu_irq *irq;
364
+ .name = TYPE_IMX_USDHC,
165
-
365
+ .parent = TYPE_SYSBUS_SDHCI,
166
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
366
+ .instance_init = imx_usdhc_init,
167
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
367
+};
168
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
368
+
169
-
369
static void sdhci_register_types(void)
170
- /*
171
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
172
- * so let split them.
173
- */
174
- for (n = 0; n < max; n++) {
175
-
176
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
177
-
178
- switch (n) {
179
- /* MDNIE_LCD1 INTG1 */
180
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
181
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
182
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
183
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
184
- continue;
185
-
186
- /* TMU INTG3 */
187
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
188
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
189
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
190
- continue;
191
-
192
- /* LCD1 INTG12 */
193
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
194
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
195
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
196
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
197
- continue;
198
-
199
- /* Multi-Core Timer INTG12 */
200
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
201
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
202
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
203
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
204
- continue;
205
-
206
- /* Multi-Core Timer INTG35 */
207
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
208
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
209
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
210
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
211
- continue;
212
-
213
- /* Multi-Core Timer INTG51 */
214
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
215
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
216
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
217
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
218
- continue;
219
-
220
- /* Multi-Core Timer INTG53 */
221
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
222
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
223
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
224
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
225
- continue;
226
- }
227
-
228
- irq[n] = qdev_get_gpio_in(dev, n);
229
- }
230
-}
231
-
232
static uint64_t
233
exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size)
370
{
234
{
371
type_register_static(&sdhci_pci_info);
372
type_register_static(&sdhci_sysbus_info);
373
type_register_static(&sdhci_bus_info);
374
+ type_register_static(&imx_usdhc_info);
375
}
376
377
type_init(sdhci_register_types)
378
--
235
--
379
2.16.1
236
2.25.1
380
381
diff view generated by jsdifflib
1
The code where we added the TT instruction was accidentally
1
Delete a couple of #defines which are never used.
2
missing a 'break', which meant that after generating the code
3
to execute the TT we would fall through to 'goto illegal_op'
4
and generate code to take an UNDEF insn.
5
2
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180206103941.13985-1-peter.maydell@linaro.org
5
Message-id: 20220404154658.565020-12-peter.maydell@linaro.org
9
---
6
---
10
target/arm/translate.c | 1 +
7
include/hw/arm/exynos4210.h | 4 ----
11
1 file changed, 1 insertion(+)
8
1 file changed, 4 deletions(-)
12
9
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
10
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
12
--- a/include/hw/arm/exynos4210.h
16
+++ b/target/arm/translate.c
13
+++ b/include/hw/arm/exynos4210.h
17
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
14
@@ -XXX,XX +XXX,XX @@
18
tcg_temp_free_i32(addr);
15
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
19
tcg_temp_free_i32(op);
16
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
20
store_reg(s, rd, ttresp);
17
21
+ break;
18
-/* IRQs number for external and internal GIC */
22
}
19
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
23
goto illegal_op;
20
-#define EXYNOS4210_INT_GIC_NIRQ 64
24
}
21
-
22
#define EXYNOS4210_I2C_NUMBER 9
23
24
#define EXYNOS4210_NUM_DMA 3
25
--
25
--
26
2.16.1
26
2.25.1
27
28
diff view generated by jsdifflib
1
Currently armv7m_nvic_acknowledge_irq() does three things:
1
In exynos4210_init_board_irqs(), use the TYPE_SPLIT_IRQ device
2
* make the current highest priority pending interrupt active
2
instead of qemu_irq_split().
3
* return a bool indicating whether that interrupt is targeting
4
Secure or NonSecure state
5
* implicitly tell the caller which is the highest priority
6
pending interrupt by setting env->v7m.exception
7
8
We need to split these jobs, because v7m_exception_taken()
9
needs to know whether the pending interrupt targets Secure so
10
it can choose to stack callee-saves registers or not, but it
11
must not make the interrupt active until after it has done
12
that stacking, in case the stacking causes a derived exception.
13
Similarly, it needs to know the number of the pending interrupt
14
so it can read the correct vector table entry before the
15
interrupt is made active, because vector table reads might
16
also cause a derived exception.
17
18
Create a new armv7m_nvic_get_pending_irq_info() function which simply
19
returns information about the highest priority pending interrupt, and
20
use it to rearrange the v7m_exception_taken() code so we don't
21
acknowledge the exception until we've done all the things which could
22
possibly cause a derived exception.
23
3
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20220404154658.565020-13-peter.maydell@linaro.org
27
Message-id: 1517324542-6607-3-git-send-email-peter.maydell@linaro.org
28
---
7
---
29
target/arm/cpu.h | 19 ++++++++++++++++---
8
include/hw/arm/exynos4210.h | 9 ++++++++
30
hw/intc/armv7m_nvic.c | 30 +++++++++++++++++++++++-------
9
hw/arm/exynos4210.c | 41 +++++++++++++++++++++++++++++--------
31
target/arm/helper.c | 16 ++++++++++++----
10
2 files changed, 42 insertions(+), 8 deletions(-)
32
hw/intc/trace-events | 3 ++-
33
4 files changed, 53 insertions(+), 15 deletions(-)
34
11
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
36
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
14
--- a/include/hw/arm/exynos4210.h
38
+++ b/target/arm/cpu.h
15
+++ b/include/hw/arm/exynos4210.h
39
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
16
@@ -XXX,XX +XXX,XX @@
40
* a different exception).
17
#include "hw/sysbus.h"
41
*/
18
#include "hw/cpu/a9mpcore.h"
42
void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
19
#include "hw/intc/exynos4210_gic.h"
43
+/**
20
+#include "hw/core/split-irq.h"
44
+ * armv7m_nvic_get_pending_irq_info: return highest priority pending
21
#include "target/arm/cpu-qom.h"
45
+ * exception, and whether it targets Secure state
22
#include "qom/object.h"
46
+ * @opaque: the NVIC
23
47
+ * @pirq: set to pending exception number
24
@@ -XXX,XX +XXX,XX @@
48
+ * @ptargets_secure: set to whether pending exception targets Secure
25
49
+ *
26
#define EXYNOS4210_NUM_DMA 3
50
+ * This function writes the number of the highest priority pending
27
51
+ * exception (the one which would be made active by
28
+/*
52
+ * armv7m_nvic_acknowledge_irq()) to @pirq, and sets @ptargets_secure
29
+ * We need one splitter for every external combiner input, plus
53
+ * to true if the current highest priority pending exception should
30
+ * one for every non-zero entry in combiner_grp_to_gic_id[].
54
+ * be taken to Secure state, false for NS.
31
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
55
+ */
32
+ */
56
+void armv7m_nvic_get_pending_irq_info(void *opaque, int *pirq,
33
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
57
+ bool *ptargets_secure);
34
+
58
/**
35
typedef struct Exynos4210Irq {
59
* armv7m_nvic_acknowledge_irq: make highest priority pending exception active
36
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
60
* @opaque: the NVIC
37
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
61
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
38
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
62
* Move the current highest priority pending exception from the pending
39
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
63
* state to the active state, and update v7m.exception to indicate that
40
A9MPPrivState a9mpcore;
64
* it is the exception currently being handled.
41
Exynos4210GicState ext_gic;
65
- *
42
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
66
- * Returns: true if exception should be taken to Secure state, false for NS
43
};
67
*/
44
68
-bool armv7m_nvic_acknowledge_irq(void *opaque);
45
#define TYPE_EXYNOS4210_SOC "exynos4210"
69
+void armv7m_nvic_acknowledge_irq(void *opaque);
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
70
/**
71
* armv7m_nvic_complete_irq: complete specified interrupt or exception
72
* @opaque: the NVIC
73
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
74
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/intc/armv7m_nvic.c
48
--- a/hw/arm/exynos4210.c
76
+++ b/hw/intc/armv7m_nvic.c
49
+++ b/hw/arm/exynos4210.c
77
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
50
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
51
uint32_t grp, bit, irq_id, n;
52
Exynos4210Irq *is = &s->irqs;
53
DeviceState *extgicdev = DEVICE(&s->ext_gic);
54
+ int splitcount = 0;
55
+ DeviceState *splitter;
56
57
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
58
irq_id = 0;
59
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
60
/* MCT_G1 is passed to External and GIC */
61
irq_id = EXT_GIC_ID_MCT_G1;
62
}
63
+
64
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
65
+ splitter = DEVICE(&s->splitter[splitcount]);
66
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
67
+ qdev_realize(splitter, NULL, &error_abort);
68
+ splitcount++;
69
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
70
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
71
if (irq_id) {
72
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
73
- qdev_get_gpio_in(extgicdev,
74
- irq_id - 32));
75
+ qdev_connect_gpio_out(splitter, 1,
76
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
77
} else {
78
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
79
- is->ext_combiner_irq[n]);
80
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
81
}
82
}
83
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
84
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
85
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
86
87
if (irq_id) {
88
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
89
- qdev_get_gpio_in(extgicdev,
90
- irq_id - 32));
91
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
92
+ splitter = DEVICE(&s->splitter[splitcount]);
93
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
94
+ qdev_realize(splitter, NULL, &error_abort);
95
+ splitcount++;
96
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
97
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
98
+ qdev_connect_gpio_out(splitter, 1,
99
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
100
}
101
}
102
+ /*
103
+ * We check this here to avoid a more obscure assert later when
104
+ * qdev_assert_realized_properly() checks that we realized every
105
+ * child object we initialized.
106
+ */
107
+ assert(splitcount == EXYNOS4210_NUM_SPLITTERS);
78
}
108
}
79
109
80
/* Make pending IRQ active. */
110
/*
81
-bool armv7m_nvic_acknowledge_irq(void *opaque)
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
82
+void armv7m_nvic_acknowledge_irq(void *opaque)
112
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
83
{
84
NVICState *s = (NVICState *)opaque;
85
CPUARMState *env = &s->cpu->env;
86
const int pending = s->vectpending;
87
const int running = nvic_exec_prio(s);
88
VecInfo *vec;
89
- bool targets_secure;
90
91
assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
92
93
if (s->vectpending_is_s_banked) {
94
vec = &s->sec_vectors[pending];
95
- targets_secure = true;
96
} else {
97
vec = &s->vectors[pending];
98
- targets_secure = !exc_is_banked(s->vectpending) &&
99
- exc_targets_secure(s, s->vectpending);
100
}
113
}
101
114
102
assert(vec->enabled);
115
+ for (i = 0; i < ARRAY_SIZE(s->splitter); i++) {
103
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
116
+ g_autofree char *name = g_strdup_printf("irq-splitter%d", i);
104
117
+ object_initialize_child(obj, name, &s->splitter[i], TYPE_SPLIT_IRQ);
105
assert(s->vectpending_prio < running);
106
107
- trace_nvic_acknowledge_irq(pending, s->vectpending_prio, targets_secure);
108
+ trace_nvic_acknowledge_irq(pending, s->vectpending_prio);
109
110
vec->active = 1;
111
vec->pending = 0;
112
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
113
write_v7m_exception(env, s->vectpending);
114
115
nvic_irq_update(s);
116
+}
117
+
118
+void armv7m_nvic_get_pending_irq_info(void *opaque,
119
+ int *pirq, bool *ptargets_secure)
120
+{
121
+ NVICState *s = (NVICState *)opaque;
122
+ const int pending = s->vectpending;
123
+ bool targets_secure;
124
+
125
+ assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
126
+
127
+ if (s->vectpending_is_s_banked) {
128
+ targets_secure = true;
129
+ } else {
130
+ targets_secure = !exc_is_banked(pending) &&
131
+ exc_targets_secure(s, pending);
132
+ }
118
+ }
133
+
119
+
134
+ trace_nvic_get_pending_irq_info(pending, targets_secure);
120
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
135
121
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
136
- return targets_secure;
137
+ *ptargets_secure = targets_secure;
138
+ *pirq = pending;
139
}
122
}
140
141
int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
142
diff --git a/target/arm/helper.c b/target/arm/helper.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/target/arm/helper.c
145
+++ b/target/arm/helper.c
146
@@ -XXX,XX +XXX,XX @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
147
}
148
}
149
150
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu, bool targets_secure)
151
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
152
{
153
CPUState *cs = CPU(cpu);
154
CPUARMState *env = &cpu->env;
155
MemTxResult result;
156
- hwaddr vec = env->v7m.vecbase[targets_secure] + env->v7m.exception * 4;
157
+ hwaddr vec = env->v7m.vecbase[targets_secure] + exc * 4;
158
uint32_t addr;
159
160
addr = address_space_ldl(cs->as, vec,
161
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
162
CPUARMState *env = &cpu->env;
163
uint32_t addr;
164
bool targets_secure;
165
+ int exc;
166
167
- targets_secure = armv7m_nvic_acknowledge_irq(env->nvic);
168
+ armv7m_nvic_get_pending_irq_info(env->nvic, &exc, &targets_secure);
169
170
if (arm_feature(env, ARM_FEATURE_V8)) {
171
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
172
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
173
}
174
}
175
176
+ addr = arm_v7m_load_vector(cpu, exc, targets_secure);
177
+
178
+ /* Now we've done everything that might cause a derived exception
179
+ * we can go ahead and activate whichever exception we're going to
180
+ * take (which might now be the derived exception).
181
+ */
182
+ armv7m_nvic_acknowledge_irq(env->nvic);
183
+
184
/* Switch to target security state -- must do this before writing SPSEL */
185
switch_v7m_security_state(env, targets_secure);
186
write_v7m_control_spsel(env, 0);
187
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
188
/* Clear IT bits */
189
env->condexec_bits = 0;
190
env->regs[14] = lr;
191
- addr = arm_v7m_load_vector(cpu, targets_secure);
192
env->regs[15] = addr & 0xfffffffe;
193
env->thumb = addr & 1;
194
}
195
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
196
index XXXXXXX..XXXXXXX 100644
197
--- a/hw/intc/trace-events
198
+++ b/hw/intc/trace-events
199
@@ -XXX,XX +XXX,XX @@ nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
200
nvic_set_pending(int irq, bool secure, bool derived, int en, int prio) "NVIC set pending irq %d secure-bank %d derived %d (enabled: %d priority %d)"
201
nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear pending irq %d secure-bank %d (enabled: %d priority %d)"
202
nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
203
-nvic_acknowledge_irq(int irq, int prio, bool targets_secure) "NVIC acknowledge IRQ: %d now active (prio %d targets_secure %d)"
204
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
205
+nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
206
nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
207
nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
208
nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
209
--
123
--
210
2.16.1
124
2.25.1
211
212
diff view generated by jsdifflib
1
Make v7m_push_callee_stack() honour the MPU by using the
1
In exynos4210_init_board_irqs(), the loop that handles IRQ lines that
2
new v7m_stack_write() function. We return a flag to indicate
2
are in a range that applies to the internal combiner only creates a
3
whether the pushes failed, which we can then use in
3
splitter for those interrupts which go to both the internal combiner
4
v7m_exception_taken() to cause us to handle the derived
4
and to the external GIC, but it does nothing at all for the
5
exception correctly.
5
interrupts which don't go to the external GIC, leaving the
6
irq_table[] array element empty for those. (This will result in
7
those interrupts simply being lost, not in a QEMU crash.)
8
9
I don't have a reliable datasheet for this SoC, but since we do wire
10
up one interrupt line in this category (the HDMI I2C device on
11
interrupt 16,1), this seems like it must be a bug in the existing
12
QEMU code. Fill in the irq_table[] entries where we're not splitting
13
the IRQ to both the internal combiner and the external GIC with the
14
IRQ line of the internal combiner. (That is, these IRQ lines go to
15
just one device, not multiple.)
16
17
This bug didn't have any visible guest effects because the only
18
implemented device that was affected was the HDMI I2C controller,
19
and we never connect any I2C devices to that bus.
6
20
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Message-id: 20220404154658.565020-14-peter.maydell@linaro.org
10
Message-id: 1517324542-6607-6-git-send-email-peter.maydell@linaro.org
11
---
24
---
12
target/arm/helper.c | 64 ++++++++++++++++++++++++++++++++++++++++-------------
25
hw/arm/exynos4210.c | 2 ++
13
1 file changed, 49 insertions(+), 15 deletions(-)
26
1 file changed, 2 insertions(+)
14
27
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
16
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
30
--- a/hw/arm/exynos4210.c
18
+++ b/target/arm/helper.c
31
+++ b/hw/arm/exynos4210.c
19
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
32
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
20
return addr;
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
21
}
34
qdev_connect_gpio_out(splitter, 1,
22
35
qdev_get_gpio_in(extgicdev, irq_id - 32));
23
-static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
36
+ } else {
24
+static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
37
+ s->irq_table[n] = is->int_combiner_irq[n];
25
bool ignore_faults)
26
{
27
/* For v8M, push the callee-saves register part of the stack frame.
28
@@ -XXX,XX +XXX,XX @@ static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
29
* In the tailchaining case this may not be the current stack.
30
*/
31
CPUARMState *env = &cpu->env;
32
- CPUState *cs = CPU(cpu);
33
uint32_t *frame_sp_p;
34
uint32_t frameptr;
35
+ ARMMMUIdx mmu_idx;
36
+ bool stacked_ok;
37
38
if (dotailchain) {
39
- frame_sp_p = get_v7m_sp_ptr(env, true,
40
- lr & R_V7M_EXCRET_MODE_MASK,
41
+ bool mode = lr & R_V7M_EXCRET_MODE_MASK;
42
+ bool priv = !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_NPRIV_MASK) ||
43
+ !mode;
44
+
45
+ mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, M_REG_S, priv);
46
+ frame_sp_p = get_v7m_sp_ptr(env, M_REG_S, mode,
47
lr & R_V7M_EXCRET_SPSEL_MASK);
48
} else {
49
+ mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
50
frame_sp_p = &env->regs[13];
51
}
52
53
frameptr = *frame_sp_p - 0x28;
54
55
- stl_phys(cs->as, frameptr, 0xfefa125b);
56
- stl_phys(cs->as, frameptr + 0x8, env->regs[4]);
57
- stl_phys(cs->as, frameptr + 0xc, env->regs[5]);
58
- stl_phys(cs->as, frameptr + 0x10, env->regs[6]);
59
- stl_phys(cs->as, frameptr + 0x14, env->regs[7]);
60
- stl_phys(cs->as, frameptr + 0x18, env->regs[8]);
61
- stl_phys(cs->as, frameptr + 0x1c, env->regs[9]);
62
- stl_phys(cs->as, frameptr + 0x20, env->regs[10]);
63
- stl_phys(cs->as, frameptr + 0x24, env->regs[11]);
64
+ /* Write as much of the stack frame as we can. A write failure may
65
+ * cause us to pend a derived exception.
66
+ */
67
+ stacked_ok =
68
+ v7m_stack_write(cpu, frameptr, 0xfefa125b, mmu_idx, ignore_faults) &&
69
+ v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
70
+ ignore_faults) &&
71
+ v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
72
+ ignore_faults) &&
73
+ v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx,
74
+ ignore_faults) &&
75
+ v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx,
76
+ ignore_faults) &&
77
+ v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx,
78
+ ignore_faults) &&
79
+ v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx,
80
+ ignore_faults) &&
81
+ v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx,
82
+ ignore_faults) &&
83
+ v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx,
84
+ ignore_faults);
85
86
+ /* Update SP regardless of whether any of the stack accesses failed.
87
+ * When we implement v8M stack limit checking then this attempt to
88
+ * update SP might also fail and result in a derived exception.
89
+ */
90
*frame_sp_p = frameptr;
91
+
92
+ return !stacked_ok;
93
}
94
95
static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
96
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
97
uint32_t addr;
98
bool targets_secure;
99
int exc;
100
+ bool push_failed = false;
101
102
armv7m_nvic_get_pending_irq_info(env->nvic, &exc, &targets_secure);
103
104
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
105
*/
106
if (lr & R_V7M_EXCRET_DCRS_MASK &&
107
!(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) {
108
- v7m_push_callee_stack(cpu, lr, dotailchain,
109
- ignore_stackfaults);
110
+ push_failed = v7m_push_callee_stack(cpu, lr, dotailchain,
111
+ ignore_stackfaults);
112
}
113
lr |= R_V7M_EXCRET_DCRS_MASK;
114
}
115
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
116
}
38
}
117
}
39
}
118
40
/*
119
+ if (push_failed && !ignore_stackfaults) {
120
+ /* Derived exception on callee-saves register stacking:
121
+ * we might now want to take a different exception which
122
+ * targets a different security state, so try again from the top.
123
+ */
124
+ v7m_exception_taken(cpu, lr, true, true);
125
+ return;
126
+ }
127
+
128
addr = arm_v7m_load_vector(cpu, exc, targets_secure);
129
130
/* Now we've done everything that might cause a derived exception
131
--
41
--
132
2.16.1
42
2.25.1
133
134
diff view generated by jsdifflib
1
The memory writes done to push registers on the stack
1
Currently for the interrupts MCT_G0 and MCT_G1 which are
2
on exception entry in M profile CPUs are supposed to
2
the only ones in the input range of the external combiner
3
go via MPU permissions checks, which may cause us to
3
and which are also wired to the external GIC, we connect
4
take a derived exception instead of the original one of
4
them only to the internal combiner and the external GIC.
5
the MPU lookup fails. We were implementing these as
5
This seems likely to be a bug, as all other interrupts
6
always-succeeds direct writes to physical memory.
6
which are in the input range of both combiners are
7
Rewrite v7m_push_stack() to do the necessary checks.
7
connected to both combiners. (The fact that the code in
8
exynos4210_combiner_get_gpioin() is also trying to wire
9
up these inputs on both combiners also suggests this.)
10
11
Wire these interrupts up to both combiners, like the rest.
8
12
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 1517324542-6607-5-git-send-email-peter.maydell@linaro.org
15
Message-id: 20220404154658.565020-15-peter.maydell@linaro.org
12
---
16
---
13
target/arm/helper.c | 103 ++++++++++++++++++++++++++++++++++++++++++++--------
17
hw/arm/exynos4210.c | 7 +++----
14
1 file changed, 87 insertions(+), 16 deletions(-)
18
1 file changed, 3 insertions(+), 4 deletions(-)
15
19
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
22
--- a/hw/arm/exynos4210.c
19
+++ b/target/arm/helper.c
23
+++ b/hw/arm/exynos4210.c
20
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
24
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
21
return target_el;
25
22
}
26
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
23
27
splitter = DEVICE(&s->splitter[splitcount]);
24
-static void v7m_push(CPUARMState *env, uint32_t val)
28
- qdev_prop_set_uint16(splitter, "num-lines", 2);
25
+static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
29
+ qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
26
+ ARMMMUIdx mmu_idx, bool ignfault)
30
qdev_realize(splitter, NULL, &error_abort);
27
{
31
splitcount++;
28
- CPUState *cs = CPU(arm_env_get_cpu(env));
32
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
29
+ CPUState *cs = CPU(cpu);
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
30
+ CPUARMState *env = &cpu->env;
34
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
31
+ MemTxAttrs attrs = {};
35
if (irq_id) {
32
+ MemTxResult txres;
36
- qdev_connect_gpio_out(splitter, 1,
33
+ target_ulong page_size;
37
+ qdev_connect_gpio_out(splitter, 2,
34
+ hwaddr physaddr;
38
qdev_get_gpio_in(extgicdev, irq_id - 32));
35
+ int prot;
39
- } else {
36
+ ARMMMUFaultInfo fi;
40
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
37
+ bool secure = mmu_idx & ARM_MMU_IDX_M_S;
41
}
38
+ int exc;
39
+ bool exc_secure;
40
41
- env->regs[13] -= 4;
42
- stl_phys(cs->as, env->regs[13], val);
43
+ if (get_phys_addr(env, addr, MMU_DATA_STORE, mmu_idx, &physaddr,
44
+ &attrs, &prot, &page_size, &fi, NULL)) {
45
+ /* MPU/SAU lookup failed */
46
+ if (fi.type == ARMFault_QEMU_SFault) {
47
+ qemu_log_mask(CPU_LOG_INT,
48
+ "...SecureFault with SFSR.AUVIOL during stacking\n");
49
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
50
+ env->v7m.sfar = addr;
51
+ exc = ARMV7M_EXCP_SECURE;
52
+ exc_secure = false;
53
+ } else {
54
+ qemu_log_mask(CPU_LOG_INT, "...MemManageFault with CFSR.MSTKERR\n");
55
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
56
+ exc = ARMV7M_EXCP_MEM;
57
+ exc_secure = secure;
58
+ }
59
+ goto pend_fault;
60
+ }
61
+ address_space_stl_le(arm_addressspace(cs, attrs), physaddr, value,
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to write the data */
65
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
66
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
67
+ exc = ARMV7M_EXCP_BUS;
68
+ exc_secure = false;
69
+ goto pend_fault;
70
+ }
71
+ return true;
72
+
73
+pend_fault:
74
+ /* By pending the exception at this point we are making
75
+ * the IMPDEF choice "overridden exceptions pended" (see the
76
+ * MergeExcInfo() pseudocode). The other choice would be to not
77
+ * pend them now and then make a choice about which to throw away
78
+ * later if we have two derived exceptions.
79
+ * The only case when we must not pend the exception but instead
80
+ * throw it away is if we are doing the push of the callee registers
81
+ * and we've already generated a derived exception. Even in this
82
+ * case we will still update the fault status registers.
83
+ */
84
+ if (!ignfault) {
85
+ armv7m_nvic_set_pending_derived(env->nvic, exc, exc_secure);
86
+ }
87
+ return false;
88
}
89
90
/* Return true if we're using the process stack pointer (not the MSP) */
91
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
92
* should ignore further stack faults trying to process
93
* that derived exception.)
94
*/
95
+ bool stacked_ok;
96
CPUARMState *env = &cpu->env;
97
uint32_t xpsr = xpsr_read(env);
98
+ uint32_t frameptr = env->regs[13];
99
+ ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
100
101
/* Align stack pointer if the guest wants that */
102
- if ((env->regs[13] & 4) &&
103
+ if ((frameptr & 4) &&
104
(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKALIGN_MASK)) {
105
- env->regs[13] -= 4;
106
+ frameptr -= 4;
107
xpsr |= XPSR_SPREALIGN;
108
}
42
}
109
- /* Switch to the handler mode. */
43
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
110
- v7m_push(env, xpsr);
111
- v7m_push(env, env->regs[15]);
112
- v7m_push(env, env->regs[14]);
113
- v7m_push(env, env->regs[12]);
114
- v7m_push(env, env->regs[3]);
115
- v7m_push(env, env->regs[2]);
116
- v7m_push(env, env->regs[1]);
117
- v7m_push(env, env->regs[0]);
118
119
- return false;
120
+ frameptr -= 0x20;
121
+
122
+ /* Write as much of the stack frame as we can. If we fail a stack
123
+ * write this will result in a derived exception being pended
124
+ * (which may be taken in preference to the one we started with
125
+ * if it has higher priority).
126
+ */
127
+ stacked_ok =
128
+ v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
129
+ v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
130
+ v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
131
+ v7m_stack_write(cpu, frameptr + 12, env->regs[3], mmu_idx, false) &&
132
+ v7m_stack_write(cpu, frameptr + 16, env->regs[12], mmu_idx, false) &&
133
+ v7m_stack_write(cpu, frameptr + 20, env->regs[14], mmu_idx, false) &&
134
+ v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
135
+ v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
136
+
137
+ /* Update SP regardless of whether any of the stack accesses failed.
138
+ * When we implement v8M stack limit checking then this attempt to
139
+ * update SP might also fail and result in a derived exception.
140
+ */
141
+ env->regs[13] = frameptr;
142
+
143
+ return !stacked_ok;
144
}
145
146
static void do_v7m_exception_exit(ARMCPU *cpu)
147
--
44
--
148
2.16.1
45
2.25.1
149
150
diff view generated by jsdifflib
1
In the v8M architecture, if the process of taking an exception
1
The combiner_grp_to_gic_id[] array includes the EXT_GIC_ID_MCT_G0
2
results in a further exception this is called a derived exception
2
and EXT_GIC_ID_MCT_G1 multiple times. This means that we will
3
(for example, an MPU exception when writing the exception frame to
3
connect multiple IRQs up to the same external GIC input, which
4
memory). If the derived exception happens while pushing the initial
4
is not permitted. We do the same thing in the code in
5
stack frame, we must ignore any subsequent possible exception
5
exynos4210_init_board_irqs() because the conditionals selecting
6
pushing the callee-saves registers.
6
an irq_id in the first loop match multiple interrupt IDs.
7
7
8
In preparation for making the stack writes check for exceptions,
8
Overall we do this for interrupt IDs
9
add a return value from v7m_push_stack() and a new parameter to
9
(1, 4), (12, 4), (35, 4), (51, 4), (53, 4) for EXT_GIC_ID_MCT_G0
10
v7m_exception_taken(), so that the former can tell the latter that
10
and
11
it needs to ignore failures to write to the stack. We also plumb
11
(1, 5), (12, 5), (35, 5), (51, 5), (53, 5) for EXT_GIC_ID_MCT_G1
12
the argument through to v7m_push_callee_stack(), which is where
13
the code to ignore the failures will be.
14
12
15
(Note that the v8M ARM pseudocode structures this slightly differently:
13
These correspond to the cases for the multi-core timer that we are
16
derived exceptions cause the attempt to process the original
14
wiring up to multiple inputs on the combiner in
17
exception to be abandoned; then at the top level it calls
15
exynos4210_combiner_get_gpioin(). That code already deals with all
18
DerivedLateArrival to prioritize the derived exception and call
16
these interrupt IDs being the same input source, so we don't need to
19
TakeException from there. We choose to let the NVIC do the prioritization
17
connect the external GIC interrupt for any of them except the first
20
and continue forward with a call to TakeException which will then
18
(1, 4) and (1, 5). Remove the array entries and conditionals which
21
take either the original or the derived exception. The effect is
19
were incorrectly causing us to wire up extra lines.
22
the same, but this structure works better for QEMU because we don't
20
23
have a convenient top level place to do the abandon-and-retry logic.)
21
This bug didn't cause any visible effects, because we only connect
22
up a device to the "primary" ID values (1, 4) and (1, 5), so the
23
extra lines would never be set to a level.
24
24
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 1517324542-6607-4-git-send-email-peter.maydell@linaro.org
27
Message-id: 20220404154658.565020-16-peter.maydell@linaro.org
28
---
28
---
29
target/arm/helper.c | 35 +++++++++++++++++++++++------------
29
include/hw/arm/exynos4210.h | 2 +-
30
1 file changed, 23 insertions(+), 12 deletions(-)
30
hw/arm/exynos4210.c | 12 +++++-------
31
2 files changed, 6 insertions(+), 8 deletions(-)
31
32
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
33
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
35
--- a/include/hw/arm/exynos4210.h
35
+++ b/target/arm/helper.c
36
+++ b/include/hw/arm/exynos4210.h
36
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
37
@@ -XXX,XX +XXX,XX @@
37
return addr;
38
* one for every non-zero entry in combiner_grp_to_gic_id[].
38
}
39
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
39
40
*/
40
-static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain)
41
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
41
+static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
42
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
42
+ bool ignore_faults)
43
43
{
44
typedef struct Exynos4210Irq {
44
/* For v8M, push the callee-saves register part of the stack frame.
45
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
45
* Compare the v8M pseudocode PushCalleeStack().
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
46
@@ -XXX,XX +XXX,XX @@ static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain)
47
index XXXXXXX..XXXXXXX 100644
47
*frame_sp_p = frameptr;
48
--- a/hw/arm/exynos4210.c
48
}
49
+++ b/hw/arm/exynos4210.c
49
50
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
50
-static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
51
/* int combiner group 34 */
51
+static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
52
{ EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
52
+ bool ignore_stackfaults)
53
/* int combiner group 35 */
53
{
54
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
54
/* Do the "take the exception" parts of exception entry,
55
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1 },
55
* but not the pushing of state to the stack. This is
56
/* int combiner group 36 */
56
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
57
{ EXT_GIC_ID_MIXER },
57
*/
58
/* int combiner group 37 */
58
if (lr & R_V7M_EXCRET_DCRS_MASK &&
59
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
59
!(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) {
60
/* groups 38-50 */
60
- v7m_push_callee_stack(cpu, lr, dotailchain);
61
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
61
+ v7m_push_callee_stack(cpu, lr, dotailchain,
62
/* int combiner group 51 */
62
+ ignore_stackfaults);
63
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
63
}
64
+ { EXT_GIC_ID_MCT_L0 },
64
lr |= R_V7M_EXCRET_DCRS_MASK;
65
/* group 52 */
65
}
66
{ },
66
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
67
/* int combiner group 53 */
67
env->thumb = addr & 1;
68
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
68
}
69
+ { EXT_GIC_ID_WDT },
69
70
/* groups 54-63 */
70
-static void v7m_push_stack(ARMCPU *cpu)
71
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
71
+static bool v7m_push_stack(ARMCPU *cpu)
72
};
72
{
73
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
73
/* Do the "set up stack frame" part of exception entry,
74
74
* similar to pseudocode PushStack().
75
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
75
+ * Return true if we generate a derived exception (and so
76
irq_id = 0;
76
+ * should ignore further stack faults trying to process
77
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
77
+ * that derived exception.)
78
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
78
*/
79
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4)) {
79
CPUARMState *env = &cpu->env;
80
/* MCT_G0 is passed to External GIC */
80
uint32_t xpsr = xpsr_read(env);
81
irq_id = EXT_GIC_ID_MCT_G0;
81
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
82
}
82
v7m_push(env, env->regs[2]);
83
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
83
v7m_push(env, env->regs[1]);
84
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
84
v7m_push(env, env->regs[0]);
85
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5)) {
85
+
86
/* MCT_G1 is passed to External and GIC */
86
+ return false;
87
irq_id = EXT_GIC_ID_MCT_G1;
87
}
88
}
88
89
static void do_v7m_exception_exit(ARMCPU *cpu)
90
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
91
if (sfault) {
92
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
93
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
94
- v7m_exception_taken(cpu, excret, true);
95
+ v7m_exception_taken(cpu, excret, true, false);
96
qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
97
"stackframe: failed EXC_RETURN.ES validity check\n");
98
return;
99
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
100
*/
101
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
102
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
103
- v7m_exception_taken(cpu, excret, true);
104
+ v7m_exception_taken(cpu, excret, true, false);
105
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
106
"stackframe: failed exception return integrity check\n");
107
return;
108
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
109
/* Take a SecureFault on the current stack */
110
env->v7m.sfsr |= R_V7M_SFSR_INVIS_MASK;
111
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
112
- v7m_exception_taken(cpu, excret, true);
113
+ v7m_exception_taken(cpu, excret, true, false);
114
qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
115
"stackframe: failed exception return integrity "
116
"signature check\n");
117
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
118
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
119
env->v7m.secure);
120
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
121
- v7m_exception_taken(cpu, excret, true);
122
+ v7m_exception_taken(cpu, excret, true, false);
123
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
124
"stackframe: failed exception return integrity "
125
"check\n");
126
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
127
/* Take an INVPC UsageFault by pushing the stack again;
128
* we know we're v7M so this is never a Secure UsageFault.
129
*/
130
+ bool ignore_stackfaults;
131
+
132
assert(!arm_feature(env, ARM_FEATURE_V8));
133
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, false);
134
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
135
- v7m_push_stack(cpu);
136
- v7m_exception_taken(cpu, excret, false);
137
+ ignore_stackfaults = v7m_push_stack(cpu);
138
+ v7m_exception_taken(cpu, excret, false, ignore_stackfaults);
139
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
140
"failed exception return integrity check\n");
141
return;
142
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
143
ARMCPU *cpu = ARM_CPU(cs);
144
CPUARMState *env = &cpu->env;
145
uint32_t lr;
146
+ bool ignore_stackfaults;
147
148
arm_log_exception(cs->exception_index);
149
150
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
151
lr |= R_V7M_EXCRET_MODE_MASK;
152
}
153
154
- v7m_push_stack(cpu);
155
- v7m_exception_taken(cpu, lr, false);
156
+ ignore_stackfaults = v7m_push_stack(cpu);
157
+ v7m_exception_taken(cpu, lr, false, ignore_stackfaults);
158
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
159
}
160
161
--
89
--
162
2.16.1
90
2.25.1
163
164
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
At this point, the function exynos4210_init_board_irqs() splits input
2
2
IRQ lines to connect them to the input combiner, output combiner and
3
Add minimal code needed to allow upstream Linux guest to boot.
3
external GIC. The function exynos4210_combiner_get_gpioin() splits
4
4
some of the combiner input lines further to connect them to multiple
5
Cc: Peter Maydell <peter.maydell@linaro.org>
5
different inputs on the combiner.
6
Cc: Jason Wang <jasowang@redhat.com>
6
7
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Because (unlike qemu_irq_split()) the TYPE_SPLIT_IRQ device has a
8
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
8
configurable number of outputs, we can do all this in one place, by
9
Cc: Michael S. Tsirkin <mst@redhat.com>
9
making exynos4210_init_board_irqs() add extra outputs to the splitter
10
Cc: qemu-devel@nongnu.org
10
device when it must be connected to more than one input on each
11
Cc: qemu-arm@nongnu.org
11
combiner.
12
Cc: yurovsky@gmail.com
12
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
We do this with a new data structure, the combinermap, which is an
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
14
array each of whose elements is a list of the interrupt IDs on the
15
combiner which must be tied together. As we loop through each
16
interrupt ID, if we find that it is the first one in one of these
17
lists, we configure the splitter device with eonugh extra outputs and
18
wire them up to the other interrupt IDs in the list.
19
20
Conveniently, for all the cases where this is necessary, the
21
lowest-numbered interrupt ID in each group is in the range of the
22
external combiner, so we only need to code for this in the first of
23
the two loops in exynos4210_init_board_irqs().
24
25
The old code in exynos4210_combiner_get_gpioin() which is being
26
deleted here had several problems which don't exist in the new code
27
in its handling of the multi-core timer interrupts:
28
(1) the case labels specified bits 4 ... 8, but bit '8' doesn't
29
exist; these should have been 4 ... 7
30
(2) it used the input irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]
31
multiple times as the input of several different splitters,
32
which isn't allowed
33
(3) in an apparent cut-and-paste error, the cases for all the
34
multi-core timer inputs used "bit + 4" even though the
35
bit range for the case was (intended to be) 4 ... 7, which
36
meant it was looking at non-existent bits 8 ... 11.
37
None of these exist in the new code.
38
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
41
Message-id: 20220404154658.565020-17-peter.maydell@linaro.org
16
---
42
---
17
hw/misc/Makefile.objs | 1 +
43
include/hw/arm/exynos4210.h | 6 +-
18
include/hw/misc/imx7_ccm.h | 139 +++++++++++++++++++++++
44
hw/arm/exynos4210.c | 178 +++++++++++++++++++++++-------------
19
hw/misc/imx7_ccm.c | 277 +++++++++++++++++++++++++++++++++++++++++++++
45
2 files changed, 119 insertions(+), 65 deletions(-)
20
3 files changed, 417 insertions(+)
46
21
create mode 100644 include/hw/misc/imx7_ccm.h
47
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
22
create mode 100644 hw/misc/imx7_ccm.c
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/Makefile.objs
49
--- a/include/hw/arm/exynos4210.h
27
+++ b/hw/misc/Makefile.objs
50
+++ b/include/hw/arm/exynos4210.h
28
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx31_ccm.o
29
obj-$(CONFIG_IMX) += imx25_ccm.o
30
obj-$(CONFIG_IMX) += imx6_ccm.o
31
obj-$(CONFIG_IMX) += imx6_src.o
32
+obj-$(CONFIG_IMX) += imx7_ccm.o
33
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
34
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
35
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
36
diff --git a/include/hw/misc/imx7_ccm.h b/include/hw/misc/imx7_ccm.h
37
new file mode 100644
38
index XXXXXXX..XXXXXXX
39
--- /dev/null
40
+++ b/include/hw/misc/imx7_ccm.h
41
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@
52
53
/*
54
* We need one splitter for every external combiner input, plus
55
- * one for every non-zero entry in combiner_grp_to_gic_id[].
56
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
57
+ * minus one for every external combiner ID in second or later
58
+ * places in a combinermap[] line.
59
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
60
*/
61
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
62
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
63
64
typedef struct Exynos4210Irq {
65
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
66
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/exynos4210.c
69
+++ b/hw/arm/exynos4210.c
70
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
71
#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
72
((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
73
42
+/*
74
+/*
43
+ * Copyright (c) 2017, Impinj, Inc.
75
+ * Some interrupt lines go to multiple combiner inputs.
44
+ *
76
+ * This data structure defines those: each array element is
45
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
77
+ * a list of combiner inputs which are connected together;
46
+ *
78
+ * the one with the smallest interrupt ID value must be first.
47
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
79
+ * As with combiner_grp_to_gic_id[], we rely on (0, 0) not being
48
+ *
80
+ * wired to anything so we can use 0 as a terminator.
49
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
50
+ * See the COPYING file in the top-level directory.
51
+ */
81
+ */
52
+
82
+#define IRQNO(G, B) EXYNOS4210_COMBINER_GET_IRQ_NUM(G, B)
53
+#ifndef IMX7_CCM_H
83
+#define IRQNONE 0
54
+#define IMX7_CCM_H
84
+
55
+
85
+#define COMBINERMAP_SIZE 16
56
+#include "hw/misc/imx_ccm.h"
86
+
57
+#include "qemu/bitops.h"
87
+static const int combinermap[COMBINERMAP_SIZE][6] = {
58
+
88
+ /* MDNIE_LCD1 */
59
+enum IMX7AnalogRegisters {
89
+ { IRQNO(0, 4), IRQNO(1, 0), IRQNONE },
60
+ ANALOG_PLL_ARM,
90
+ { IRQNO(0, 5), IRQNO(1, 1), IRQNONE },
61
+ ANALOG_PLL_ARM_SET,
91
+ { IRQNO(0, 6), IRQNO(1, 2), IRQNONE },
62
+ ANALOG_PLL_ARM_CLR,
92
+ { IRQNO(0, 7), IRQNO(1, 3), IRQNONE },
63
+ ANALOG_PLL_ARM_TOG,
93
+ /* TMU */
64
+ ANALOG_PLL_DDR,
94
+ { IRQNO(2, 4), IRQNO(3, 4), IRQNONE },
65
+ ANALOG_PLL_DDR_SET,
95
+ { IRQNO(2, 5), IRQNO(3, 5), IRQNONE },
66
+ ANALOG_PLL_DDR_CLR,
96
+ { IRQNO(2, 6), IRQNO(3, 6), IRQNONE },
67
+ ANALOG_PLL_DDR_TOG,
97
+ { IRQNO(2, 7), IRQNO(3, 7), IRQNONE },
68
+ ANALOG_PLL_DDR_SS,
98
+ /* LCD1 */
69
+ ANALOG_PLL_DDR_SS_SET,
99
+ { IRQNO(11, 4), IRQNO(12, 0), IRQNONE },
70
+ ANALOG_PLL_DDR_SS_CLR,
100
+ { IRQNO(11, 5), IRQNO(12, 1), IRQNONE },
71
+ ANALOG_PLL_DDR_SS_TOG,
101
+ { IRQNO(11, 6), IRQNO(12, 2), IRQNONE },
72
+ ANALOG_PLL_DDR_NUM,
102
+ { IRQNO(11, 7), IRQNO(12, 3), IRQNONE },
73
+ ANALOG_PLL_DDR_NUM_SET,
103
+ /* Multi-core timer */
74
+ ANALOG_PLL_DDR_NUM_CLR,
104
+ { IRQNO(1, 4), IRQNO(12, 4), IRQNO(35, 4), IRQNO(51, 4), IRQNO(53, 4), IRQNONE },
75
+ ANALOG_PLL_DDR_NUM_TOG,
105
+ { IRQNO(1, 5), IRQNO(12, 5), IRQNO(35, 5), IRQNO(51, 5), IRQNO(53, 5), IRQNONE },
76
+ ANALOG_PLL_DDR_DENOM,
106
+ { IRQNO(1, 6), IRQNO(12, 6), IRQNO(35, 6), IRQNO(51, 6), IRQNO(53, 6), IRQNONE },
77
+ ANALOG_PLL_DDR_DENOM_SET,
107
+ { IRQNO(1, 7), IRQNO(12, 7), IRQNO(35, 7), IRQNO(51, 7), IRQNO(53, 7), IRQNONE },
78
+ ANALOG_PLL_DDR_DENOM_CLR,
79
+ ANALOG_PLL_DDR_DENOM_TOG,
80
+ ANALOG_PLL_480,
81
+ ANALOG_PLL_480_SET,
82
+ ANALOG_PLL_480_CLR,
83
+ ANALOG_PLL_480_TOG,
84
+ ANALOG_PLL_480A,
85
+ ANALOG_PLL_480A_SET,
86
+ ANALOG_PLL_480A_CLR,
87
+ ANALOG_PLL_480A_TOG,
88
+ ANALOG_PLL_480B,
89
+ ANALOG_PLL_480B_SET,
90
+ ANALOG_PLL_480B_CLR,
91
+ ANALOG_PLL_480B_TOG,
92
+ ANALOG_PLL_ENET,
93
+ ANALOG_PLL_ENET_SET,
94
+ ANALOG_PLL_ENET_CLR,
95
+ ANALOG_PLL_ENET_TOG,
96
+ ANALOG_PLL_AUDIO,
97
+ ANALOG_PLL_AUDIO_SET,
98
+ ANALOG_PLL_AUDIO_CLR,
99
+ ANALOG_PLL_AUDIO_TOG,
100
+ ANALOG_PLL_AUDIO_SS,
101
+ ANALOG_PLL_AUDIO_SS_SET,
102
+ ANALOG_PLL_AUDIO_SS_CLR,
103
+ ANALOG_PLL_AUDIO_SS_TOG,
104
+ ANALOG_PLL_AUDIO_NUM,
105
+ ANALOG_PLL_AUDIO_NUM_SET,
106
+ ANALOG_PLL_AUDIO_NUM_CLR,
107
+ ANALOG_PLL_AUDIO_NUM_TOG,
108
+ ANALOG_PLL_AUDIO_DENOM,
109
+ ANALOG_PLL_AUDIO_DENOM_SET,
110
+ ANALOG_PLL_AUDIO_DENOM_CLR,
111
+ ANALOG_PLL_AUDIO_DENOM_TOG,
112
+ ANALOG_PLL_VIDEO,
113
+ ANALOG_PLL_VIDEO_SET,
114
+ ANALOG_PLL_VIDEO_CLR,
115
+ ANALOG_PLL_VIDEO_TOG,
116
+ ANALOG_PLL_VIDEO_SS,
117
+ ANALOG_PLL_VIDEO_SS_SET,
118
+ ANALOG_PLL_VIDEO_SS_CLR,
119
+ ANALOG_PLL_VIDEO_SS_TOG,
120
+ ANALOG_PLL_VIDEO_NUM,
121
+ ANALOG_PLL_VIDEO_NUM_SET,
122
+ ANALOG_PLL_VIDEO_NUM_CLR,
123
+ ANALOG_PLL_VIDEO_NUM_TOG,
124
+ ANALOG_PLL_VIDEO_DENOM,
125
+ ANALOG_PLL_VIDEO_DENOM_SET,
126
+ ANALOG_PLL_VIDEO_DENOM_CLR,
127
+ ANALOG_PLL_VIDEO_DENOM_TOG,
128
+ ANALOG_PLL_MISC0,
129
+ ANALOG_PLL_MISC0_SET,
130
+ ANALOG_PLL_MISC0_CLR,
131
+ ANALOG_PLL_MISC0_TOG,
132
+
133
+ ANALOG_DIGPROG = 0x800 / sizeof(uint32_t),
134
+ ANALOG_MAX,
135
+
136
+ ANALOG_PLL_LOCK = BIT(31)
137
+};
108
+};
138
+
109
+
139
+enum IMX7CCMRegisters {
110
+#undef IRQNO
140
+ CCM_MAX = 0xBE00 / sizeof(uint32_t) + 1,
111
+
141
+};
112
+static const int *combinermap_entry(int irq)
142
+
143
+enum IMX7PMURegisters {
144
+ PMU_MAX = 0x140 / sizeof(uint32_t),
145
+};
146
+
147
+#define TYPE_IMX7_CCM "imx7.ccm"
148
+#define IMX7_CCM(obj) OBJECT_CHECK(IMX7CCMState, (obj), TYPE_IMX7_CCM)
149
+
150
+typedef struct IMX7CCMState {
151
+ /* <private> */
152
+ IMXCCMState parent_obj;
153
+
154
+ /* <public> */
155
+ MemoryRegion iomem;
156
+
157
+ uint32_t ccm[CCM_MAX];
158
+} IMX7CCMState;
159
+
160
+
161
+#define TYPE_IMX7_ANALOG "imx7.analog"
162
+#define IMX7_ANALOG(obj) OBJECT_CHECK(IMX7AnalogState, (obj), TYPE_IMX7_ANALOG)
163
+
164
+typedef struct IMX7AnalogState {
165
+ /* <private> */
166
+ IMXCCMState parent_obj;
167
+
168
+ /* <public> */
169
+ struct {
170
+ MemoryRegion container;
171
+ MemoryRegion analog;
172
+ MemoryRegion digprog;
173
+ MemoryRegion pmu;
174
+ } mmio;
175
+
176
+ uint32_t analog[ANALOG_MAX];
177
+ uint32_t pmu[PMU_MAX];
178
+} IMX7AnalogState;
179
+
180
+#endif /* IMX7_CCM_H */
181
diff --git a/hw/misc/imx7_ccm.c b/hw/misc/imx7_ccm.c
182
new file mode 100644
183
index XXXXXXX..XXXXXXX
184
--- /dev/null
185
+++ b/hw/misc/imx7_ccm.c
186
@@ -XXX,XX +XXX,XX @@
187
+/*
188
+ * Copyright (c) 2018, Impinj, Inc.
189
+ *
190
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
191
+ *
192
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
193
+ *
194
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
195
+ * See the COPYING file in the top-level directory.
196
+ */
197
+
198
+#include "qemu/osdep.h"
199
+#include "qemu/log.h"
200
+
201
+#include "hw/misc/imx7_ccm.h"
202
+
203
+static void imx7_analog_reset(DeviceState *dev)
204
+{
205
+ IMX7AnalogState *s = IMX7_ANALOG(dev);
206
+
207
+ memset(s->pmu, 0, sizeof(s->pmu));
208
+ memset(s->analog, 0, sizeof(s->analog));
209
+
210
+ s->analog[ANALOG_PLL_ARM] = 0x00002042;
211
+ s->analog[ANALOG_PLL_DDR] = 0x0060302c;
212
+ s->analog[ANALOG_PLL_DDR_SS] = 0x00000000;
213
+ s->analog[ANALOG_PLL_DDR_NUM] = 0x06aaac4d;
214
+ s->analog[ANALOG_PLL_DDR_DENOM] = 0x100003ec;
215
+ s->analog[ANALOG_PLL_480] = 0x00002000;
216
+ s->analog[ANALOG_PLL_480A] = 0x52605a56;
217
+ s->analog[ANALOG_PLL_480B] = 0x52525216;
218
+ s->analog[ANALOG_PLL_ENET] = 0x00001fc0;
219
+ s->analog[ANALOG_PLL_AUDIO] = 0x0001301b;
220
+ s->analog[ANALOG_PLL_AUDIO_SS] = 0x00000000;
221
+ s->analog[ANALOG_PLL_AUDIO_NUM] = 0x05f5e100;
222
+ s->analog[ANALOG_PLL_AUDIO_DENOM] = 0x2964619c;
223
+ s->analog[ANALOG_PLL_VIDEO] = 0x0008201b;
224
+ s->analog[ANALOG_PLL_VIDEO_SS] = 0x00000000;
225
+ s->analog[ANALOG_PLL_VIDEO_NUM] = 0x0000f699;
226
+ s->analog[ANALOG_PLL_VIDEO_DENOM] = 0x000f4240;
227
+ s->analog[ANALOG_PLL_MISC0] = 0x00000000;
228
+
229
+ /* all PLLs need to be locked */
230
+ s->analog[ANALOG_PLL_ARM] |= ANALOG_PLL_LOCK;
231
+ s->analog[ANALOG_PLL_DDR] |= ANALOG_PLL_LOCK;
232
+ s->analog[ANALOG_PLL_480] |= ANALOG_PLL_LOCK;
233
+ s->analog[ANALOG_PLL_480A] |= ANALOG_PLL_LOCK;
234
+ s->analog[ANALOG_PLL_480B] |= ANALOG_PLL_LOCK;
235
+ s->analog[ANALOG_PLL_ENET] |= ANALOG_PLL_LOCK;
236
+ s->analog[ANALOG_PLL_AUDIO] |= ANALOG_PLL_LOCK;
237
+ s->analog[ANALOG_PLL_VIDEO] |= ANALOG_PLL_LOCK;
238
+ s->analog[ANALOG_PLL_MISC0] |= ANALOG_PLL_LOCK;
239
+
240
+ /*
241
+ * Since I couldn't find any info about this in the reference
242
+ * manual the value of this register is based strictly on matching
243
+ * what Linux kernel expects it to be.
244
+ */
245
+ s->analog[ANALOG_DIGPROG] = 0x720000;
246
+ /*
247
+ * Set revision to be 1.0 (Arbitrary choice, no particular
248
+ * reason).
249
+ */
250
+ s->analog[ANALOG_DIGPROG] |= 0x000010;
251
+}
252
+
253
+static void imx7_ccm_reset(DeviceState *dev)
254
+{
255
+ IMX7CCMState *s = IMX7_CCM(dev);
256
+
257
+ memset(s->ccm, 0, sizeof(s->ccm));
258
+}
259
+
260
+#define CCM_INDEX(offset) (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
261
+#define CCM_BITOP(offset) ((offset) & (hwaddr)0xF)
262
+
263
+enum {
264
+ CCM_BITOP_NONE = 0x00,
265
+ CCM_BITOP_SET = 0x04,
266
+ CCM_BITOP_CLR = 0x08,
267
+ CCM_BITOP_TOG = 0x0C,
268
+};
269
+
270
+static uint64_t imx7_set_clr_tog_read(void *opaque, hwaddr offset,
271
+ unsigned size)
272
+{
273
+ const uint32_t *mmio = opaque;
274
+
275
+ return mmio[CCM_INDEX(offset)];
276
+}
277
+
278
+static void imx7_set_clr_tog_write(void *opaque, hwaddr offset,
279
+ uint64_t value, unsigned size)
280
+{
281
+ const uint8_t bitop = CCM_BITOP(offset);
282
+ const uint32_t index = CCM_INDEX(offset);
283
+ uint32_t *mmio = opaque;
284
+
285
+ switch (bitop) {
286
+ case CCM_BITOP_NONE:
287
+ mmio[index] = value;
288
+ break;
289
+ case CCM_BITOP_SET:
290
+ mmio[index] |= value;
291
+ break;
292
+ case CCM_BITOP_CLR:
293
+ mmio[index] &= ~value;
294
+ break;
295
+ case CCM_BITOP_TOG:
296
+ mmio[index] ^= value;
297
+ break;
298
+ };
299
+}
300
+
301
+static const struct MemoryRegionOps imx7_set_clr_tog_ops = {
302
+ .read = imx7_set_clr_tog_read,
303
+ .write = imx7_set_clr_tog_write,
304
+ .endianness = DEVICE_NATIVE_ENDIAN,
305
+ .impl = {
306
+ /*
307
+ * Our device would not work correctly if the guest was doing
308
+ * unaligned access. This might not be a limitation on the real
309
+ * device but in practice there is no reason for a guest to access
310
+ * this device unaligned.
311
+ */
312
+ .min_access_size = 4,
313
+ .max_access_size = 4,
314
+ .unaligned = false,
315
+ },
316
+};
317
+
318
+static const struct MemoryRegionOps imx7_digprog_ops = {
319
+ .read = imx7_set_clr_tog_read,
320
+ .endianness = DEVICE_NATIVE_ENDIAN,
321
+ .impl = {
322
+ .min_access_size = 4,
323
+ .max_access_size = 4,
324
+ .unaligned = false,
325
+ },
326
+};
327
+
328
+static void imx7_ccm_init(Object *obj)
329
+{
330
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
331
+ IMX7CCMState *s = IMX7_CCM(obj);
332
+
333
+ memory_region_init_io(&s->iomem,
334
+ obj,
335
+ &imx7_set_clr_tog_ops,
336
+ s->ccm,
337
+ TYPE_IMX7_CCM ".ccm",
338
+ sizeof(s->ccm));
339
+
340
+ sysbus_init_mmio(sd, &s->iomem);
341
+}
342
+
343
+static void imx7_analog_init(Object *obj)
344
+{
345
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
346
+ IMX7AnalogState *s = IMX7_ANALOG(obj);
347
+
348
+ memory_region_init(&s->mmio.container, obj, TYPE_IMX7_ANALOG,
349
+ 0x10000);
350
+
351
+ memory_region_init_io(&s->mmio.analog,
352
+ obj,
353
+ &imx7_set_clr_tog_ops,
354
+ s->analog,
355
+ TYPE_IMX7_ANALOG,
356
+ sizeof(s->analog));
357
+
358
+ memory_region_add_subregion(&s->mmio.container,
359
+ 0x60, &s->mmio.analog);
360
+
361
+ memory_region_init_io(&s->mmio.pmu,
362
+ obj,
363
+ &imx7_set_clr_tog_ops,
364
+ s->pmu,
365
+ TYPE_IMX7_ANALOG ".pmu",
366
+ sizeof(s->pmu));
367
+
368
+ memory_region_add_subregion(&s->mmio.container,
369
+ 0x200, &s->mmio.pmu);
370
+
371
+ memory_region_init_io(&s->mmio.digprog,
372
+ obj,
373
+ &imx7_digprog_ops,
374
+ &s->analog[ANALOG_DIGPROG],
375
+ TYPE_IMX7_ANALOG ".digprog",
376
+ sizeof(uint32_t));
377
+
378
+ memory_region_add_subregion_overlap(&s->mmio.container,
379
+ 0x800, &s->mmio.digprog, 10);
380
+
381
+
382
+ sysbus_init_mmio(sd, &s->mmio.container);
383
+}
384
+
385
+static const VMStateDescription vmstate_imx7_ccm = {
386
+ .name = TYPE_IMX7_CCM,
387
+ .version_id = 1,
388
+ .minimum_version_id = 1,
389
+ .fields = (VMStateField[]) {
390
+ VMSTATE_UINT32_ARRAY(ccm, IMX7CCMState, CCM_MAX),
391
+ VMSTATE_END_OF_LIST()
392
+ },
393
+};
394
+
395
+static uint32_t imx7_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
396
+{
113
+{
397
+ /*
114
+ /*
398
+ * This function is "consumed" by GPT emulation code, however on
115
+ * If the interrupt number passed in is the first entry in some
399
+ * i.MX7 each GPT block can have their own clock root. This means
116
+ * line of the combinermap, return a pointer to that line;
400
+ * that this functions needs somehow to know requester's identity
117
+ * otherwise return NULL.
401
+ * and the way to pass it: be it via additional IMXClk constants
402
+ * or by adding another argument to this method needs to be
403
+ * figured out
404
+ */
118
+ */
405
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Not implemented\n",
119
+ int i;
406
+ TYPE_IMX7_CCM, __func__);
120
+ for (i = 0; i < COMBINERMAP_SIZE; i++) {
407
+ return 0;
121
+ if (combinermap[i][0] == irq) {
122
+ return combinermap[i];
123
+ }
124
+ }
125
+ return NULL;
408
+}
126
+}
409
+
127
+
410
+static void imx7_ccm_class_init(ObjectClass *klass, void *data)
128
+static int mapline_size(const int *mapline)
411
+{
129
+{
412
+ DeviceClass *dc = DEVICE_CLASS(klass);
130
+ /* Return number of entries in this mapline in total */
413
+ IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
131
+ int i = 0;
414
+
132
+
415
+ dc->reset = imx7_ccm_reset;
133
+ if (!mapline) {
416
+ dc->vmsd = &vmstate_imx7_ccm;
134
+ /* Not in the map? IRQ goes to exactly one combiner input */
417
+ dc->desc = "i.MX7 Clock Control Module";
135
+ return 1;
418
+
136
+ }
419
+ ccm->get_clock_frequency = imx7_ccm_get_clock_frequency;
137
+ while (*mapline != IRQNONE) {
138
+ mapline++;
139
+ i++;
140
+ }
141
+ return i;
420
+}
142
+}
421
+
143
+
422
+static const TypeInfo imx7_ccm_info = {
144
/*
423
+ .name = TYPE_IMX7_CCM,
145
* Initialize board IRQs.
424
+ .parent = TYPE_IMX_CCM,
146
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
425
+ .instance_size = sizeof(IMX7CCMState),
147
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
426
+ .instance_init = imx7_ccm_init,
148
DeviceState *extgicdev = DEVICE(&s->ext_gic);
427
+ .class_init = imx7_ccm_class_init,
149
int splitcount = 0;
428
+};
150
DeviceState *splitter;
429
+
151
+ const int *mapline;
430
+static const VMStateDescription vmstate_imx7_analog = {
152
+ int numlines, splitin, in;
431
+ .name = TYPE_IMX7_ANALOG,
153
432
+ .version_id = 1,
154
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
433
+ .minimum_version_id = 1,
155
irq_id = 0;
434
+ .fields = (VMStateField[]) {
156
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
435
+ VMSTATE_UINT32_ARRAY(analog, IMX7AnalogState, ANALOG_MAX),
157
irq_id = EXT_GIC_ID_MCT_G1;
436
+ VMSTATE_UINT32_ARRAY(pmu, IMX7AnalogState, PMU_MAX),
158
}
437
+ VMSTATE_END_OF_LIST()
159
438
+ },
160
+ if (s->irq_table[n]) {
439
+};
161
+ /*
440
+
162
+ * This must be some non-first entry in a combinermap line,
441
+static void imx7_analog_class_init(ObjectClass *klass, void *data)
163
+ * and we've already filled it in.
442
+{
164
+ */
443
+ DeviceClass *dc = DEVICE_CLASS(klass);
165
+ continue;
444
+
166
+ }
445
+ dc->reset = imx7_analog_reset;
167
+ mapline = combinermap_entry(n);
446
+ dc->vmsd = &vmstate_imx7_analog;
168
+ /*
447
+ dc->desc = "i.MX7 Analog Module";
169
+ * We need to connect the IRQ to multiple inputs on both combiners
448
+}
170
+ * and possibly also to the external GIC.
449
+
171
+ */
450
+static const TypeInfo imx7_analog_info = {
172
+ numlines = 2 * mapline_size(mapline);
451
+ .name = TYPE_IMX7_ANALOG,
173
+ if (irq_id) {
452
+ .parent = TYPE_SYS_BUS_DEVICE,
174
+ numlines++;
453
+ .instance_size = sizeof(IMX7AnalogState),
175
+ }
454
+ .instance_init = imx7_analog_init,
176
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
455
+ .class_init = imx7_analog_class_init,
177
splitter = DEVICE(&s->splitter[splitcount]);
456
+};
178
- qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
457
+
179
+ qdev_prop_set_uint16(splitter, "num-lines", numlines);
458
+static void imx7_ccm_register_type(void)
180
qdev_realize(splitter, NULL, &error_abort);
459
+{
181
splitcount++;
460
+ type_register_static(&imx7_ccm_info);
182
- s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
461
+ type_register_static(&imx7_analog_info);
183
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
462
+}
184
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
463
+type_init(imx7_ccm_register_type)
185
+
186
+ in = n;
187
+ splitin = 0;
188
+ for (;;) {
189
+ s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
190
+ qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
191
+ qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
192
+ splitin += 2;
193
+ if (!mapline) {
194
+ break;
195
+ }
196
+ mapline++;
197
+ in = *mapline;
198
+ if (in == IRQNONE) {
199
+ break;
200
+ }
201
+ }
202
if (irq_id) {
203
- qdev_connect_gpio_out(splitter, 2,
204
+ qdev_connect_gpio_out(splitter, splitin,
205
qdev_get_gpio_in(extgicdev, irq_id - 32));
206
}
207
}
208
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
209
irq_id = combiner_grp_to_gic_id[grp -
210
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
211
212
+ if (s->irq_table[n]) {
213
+ /*
214
+ * This must be some non-first entry in a combinermap line,
215
+ * and we've already filled it in.
216
+ */
217
+ continue;
218
+ }
219
+
220
if (irq_id) {
221
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
222
splitter = DEVICE(&s->splitter[splitcount]);
223
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
224
DeviceState *dev, int ext)
225
{
226
int n;
227
- int bit;
228
int max;
229
qemu_irq *irq;
230
231
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
232
EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
233
irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
234
235
- /*
236
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
237
- * so let split them.
238
- */
239
for (n = 0; n < max; n++) {
240
-
241
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
242
-
243
- switch (n) {
244
- /* MDNIE_LCD1 INTG1 */
245
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
246
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
247
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
248
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
249
- continue;
250
-
251
- /* TMU INTG3 */
252
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
253
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
254
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
255
- continue;
256
-
257
- /* LCD1 INTG12 */
258
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
259
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
260
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
261
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
262
- continue;
263
-
264
- /* Multi-Core Timer INTG12 */
265
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
266
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
267
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
268
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
269
- continue;
270
-
271
- /* Multi-Core Timer INTG35 */
272
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
273
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
274
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
275
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
276
- continue;
277
-
278
- /* Multi-Core Timer INTG51 */
279
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
280
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
281
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
282
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
283
- continue;
284
-
285
- /* Multi-Core Timer INTG53 */
286
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
287
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
288
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
289
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
290
- continue;
291
- }
292
-
293
irq[n] = qdev_get_gpio_in(dev, n);
294
}
295
}
464
--
296
--
465
2.16.1
297
2.25.1
466
467
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Switch the creation of the combiner devices to the new-style
2
"embedded in state struct" approach, so we can easily refer
3
to the object elsewhere during realize.
2
4
3
Add enough code to emulate i.MX2 watchdog IP block so it would be
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
possible to reboot the machine running Linux Guest.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-18-peter.maydell@linaro.org
8
---
9
include/hw/arm/exynos4210.h | 3 ++
10
include/hw/intc/exynos4210_combiner.h | 57 +++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 20 +++++-----
12
hw/intc/exynos4210_combiner.c | 31 +--------------
13
4 files changed, 72 insertions(+), 39 deletions(-)
14
create mode 100644 include/hw/intc/exynos4210_combiner.h
5
15
6
Cc: Peter Maydell <peter.maydell@linaro.org>
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
7
Cc: Jason Wang <jasowang@redhat.com>
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
10
Cc: Michael S. Tsirkin <mst@redhat.com>
11
Cc: qemu-devel@nongnu.org
12
Cc: qemu-arm@nongnu.org
13
Cc: yurovsky@gmail.com
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/misc/Makefile.objs | 1 +
20
include/hw/misc/imx2_wdt.h | 33 +++++++++++++++++
21
hw/misc/imx2_wdt.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++
22
3 files changed, 123 insertions(+)
23
create mode 100644 include/hw/misc/imx2_wdt.h
24
create mode 100644 hw/misc/imx2_wdt.c
25
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/Makefile.objs
18
--- a/include/hw/arm/exynos4210.h
29
+++ b/hw/misc/Makefile.objs
19
+++ b/include/hw/arm/exynos4210.h
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx25_ccm.o
20
@@ -XXX,XX +XXX,XX @@
31
obj-$(CONFIG_IMX) += imx6_ccm.o
21
#include "hw/sysbus.h"
32
obj-$(CONFIG_IMX) += imx6_src.o
22
#include "hw/cpu/a9mpcore.h"
33
obj-$(CONFIG_IMX) += imx7_ccm.o
23
#include "hw/intc/exynos4210_gic.h"
34
+obj-$(CONFIG_IMX) += imx2_wdt.o
24
+#include "hw/intc/exynos4210_combiner.h"
35
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
25
#include "hw/core/split-irq.h"
36
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
26
#include "target/arm/cpu-qom.h"
37
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
27
#include "qom/object.h"
38
diff --git a/include/hw/misc/imx2_wdt.h b/include/hw/misc/imx2_wdt.h
28
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
29
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
30
A9MPPrivState a9mpcore;
31
Exynos4210GicState ext_gic;
32
+ Exynos4210CombinerState int_combiner;
33
+ Exynos4210CombinerState ext_combiner;
34
SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
35
};
36
37
diff --git a/include/hw/intc/exynos4210_combiner.h b/include/hw/intc/exynos4210_combiner.h
39
new file mode 100644
38
new file mode 100644
40
index XXXXXXX..XXXXXXX
39
index XXXXXXX..XXXXXXX
41
--- /dev/null
40
--- /dev/null
42
+++ b/include/hw/misc/imx2_wdt.h
41
+++ b/include/hw/intc/exynos4210_combiner.h
43
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
44
+/*
43
+/*
45
+ * Copyright (c) 2017, Impinj, Inc.
44
+ * Samsung exynos4210 Interrupt Combiner
46
+ *
45
+ *
47
+ * i.MX2 Watchdog IP block
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
48
+ *
49
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
50
+ *
50
+ *
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * See the COPYING file in the top-level directory.
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
53
+ */
63
+ */
54
+
64
+
55
+#ifndef IMX2_WDT_H
65
+#ifndef HW_INTC_EXYNOS4210_COMBINER
56
+#define IMX2_WDT_H
66
+#define HW_INTC_EXYNOS4210_COMBINER
57
+
67
+
58
+#include "hw/sysbus.h"
68
+#include "hw/sysbus.h"
59
+
69
+
60
+#define TYPE_IMX2_WDT "imx2.wdt"
70
+/*
61
+#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
71
+ * State for each output signal of internal combiner
72
+ */
73
+typedef struct CombinerGroupState {
74
+ uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
75
+ uint8_t src_pending; /* Pending source interrupts before masking */
76
+} CombinerGroupState;
62
+
77
+
63
+enum IMX2WdtRegisters {
78
+#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
64
+ IMX2_WDT_WCR = 0x0000,
79
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
65
+ IMX2_WDT_REG_NUM = 0x0008 / sizeof(uint16_t) + 1,
80
+
81
+/* Number of groups and total number of interrupts for the internal combiner */
82
+#define IIC_NGRP 64
83
+#define IIC_NIRQ (IIC_NGRP * 8)
84
+#define IIC_REGSET_SIZE 0x41
85
+
86
+struct Exynos4210CombinerState {
87
+ SysBusDevice parent_obj;
88
+
89
+ MemoryRegion iomem;
90
+
91
+ struct CombinerGroupState group[IIC_NGRP];
92
+ uint32_t reg_set[IIC_REGSET_SIZE];
93
+ uint32_t icipsr[2];
94
+ uint32_t external; /* 1 means that this combiner is external */
95
+
96
+ qemu_irq output_irq[IIC_NGRP];
66
+};
97
+};
67
+
98
+
68
+
99
+#endif
69
+typedef struct IMX2WdtState {
100
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
70
+ /* <private> */
101
index XXXXXXX..XXXXXXX 100644
71
+ SysBusDevice parent_obj;
102
--- a/hw/arm/exynos4210.c
72
+
103
+++ b/hw/arm/exynos4210.c
73
+ MemoryRegion mmio;
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
74
+} IMX2WdtState;
105
}
75
+
106
76
+#endif /* IMX7_SNVS_H */
107
/* Internal Interrupt Combiner */
77
diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
108
- dev = qdev_new("exynos4210.combiner");
78
new file mode 100644
109
- busdev = SYS_BUS_DEVICE(dev);
79
index XXXXXXX..XXXXXXX
110
- sysbus_realize_and_unref(busdev, &error_fatal);
80
--- /dev/null
111
+ busdev = SYS_BUS_DEVICE(&s->int_combiner);
81
+++ b/hw/misc/imx2_wdt.c
112
+ sysbus_realize(busdev, &error_fatal);
113
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
114
sysbus_connect_irq(busdev, n,
115
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
116
}
117
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
118
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
119
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
120
121
/* External Interrupt Combiner */
122
- dev = qdev_new("exynos4210.combiner");
123
- qdev_prop_set_uint32(dev, "external", 1);
124
- busdev = SYS_BUS_DEVICE(dev);
125
- sysbus_realize_and_unref(busdev, &error_fatal);
126
+ qdev_prop_set_uint32(DEVICE(&s->ext_combiner), "external", 1);
127
+ busdev = SYS_BUS_DEVICE(&s->ext_combiner);
128
+ sysbus_realize(busdev, &error_fatal);
129
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
130
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
131
}
132
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
133
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
134
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
135
136
/* Initialize board IRQs. */
137
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
138
139
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
140
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
141
+ object_initialize_child(obj, "int-combiner", &s->int_combiner,
142
+ TYPE_EXYNOS4210_COMBINER);
143
+ object_initialize_child(obj, "ext-combiner", &s->ext_combiner,
144
+ TYPE_EXYNOS4210_COMBINER);
145
}
146
147
static void exynos4210_class_init(ObjectClass *klass, void *data)
148
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/hw/intc/exynos4210_combiner.c
151
+++ b/hw/intc/exynos4210_combiner.c
82
@@ -XXX,XX +XXX,XX @@
152
@@ -XXX,XX +XXX,XX @@
83
+/*
153
#include "hw/sysbus.h"
84
+ * Copyright (c) 2018, Impinj, Inc.
154
#include "migration/vmstate.h"
85
+ *
155
#include "qemu/module.h"
86
+ * i.MX2 Watchdog IP block
156
-
87
+ *
157
+#include "hw/intc/exynos4210_combiner.h"
88
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
158
#include "hw/arm/exynos4210.h"
89
+ *
159
#include "hw/hw.h"
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
160
#include "hw/irq.h"
91
+ * See the COPYING file in the top-level directory.
161
@@ -XXX,XX +XXX,XX @@
92
+ */
162
#define DPRINTF(fmt, ...) do {} while (0)
93
+
163
#endif
94
+#include "qemu/osdep.h"
164
95
+#include "qemu/bitops.h"
165
-#define IIC_NGRP 64 /* Internal Interrupt Combiner
96
+#include "sysemu/watchdog.h"
166
- Groups number */
97
+
167
-#define IIC_NIRQ (IIC_NGRP * 8)/* Internal Interrupt Combiner
98
+#include "hw/misc/imx2_wdt.h"
168
- Interrupts number */
99
+
169
#define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */
100
+#define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */
170
-#define IIC_REGSET_SIZE 0x41
101
+#define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */
171
-
102
+
172
-/*
103
+static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
173
- * State for each output signal of internal combiner
104
+ unsigned int size)
174
- */
105
+{
175
-typedef struct CombinerGroupState {
106
+ return 0;
176
- uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
107
+}
177
- uint8_t src_pending; /* Pending source interrupts before masking */
108
+
178
-} CombinerGroupState;
109
+static void imx2_wdt_write(void *opaque, hwaddr addr,
179
-
110
+ uint64_t value, unsigned int size)
180
-#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
111
+{
181
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
112
+ if (addr == IMX2_WDT_WCR &&
182
-
113
+ (value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
183
-struct Exynos4210CombinerState {
114
+ watchdog_perform_action();
184
- SysBusDevice parent_obj;
115
+ }
185
-
116
+}
186
- MemoryRegion iomem;
117
+
187
-
118
+static const MemoryRegionOps imx2_wdt_ops = {
188
- struct CombinerGroupState group[IIC_NGRP];
119
+ .read = imx2_wdt_read,
189
- uint32_t reg_set[IIC_REGSET_SIZE];
120
+ .write = imx2_wdt_write,
190
- uint32_t icipsr[2];
121
+ .endianness = DEVICE_NATIVE_ENDIAN,
191
- uint32_t external; /* 1 means that this combiner is external */
122
+ .impl = {
192
-
123
+ /*
193
- qemu_irq output_irq[IIC_NGRP];
124
+ * Our device would not work correctly if the guest was doing
194
-};
125
+ * unaligned access. This might not be a limitation on the
195
126
+ * real device but in practice there is no reason for a guest
196
static const VMStateDescription vmstate_exynos4210_combiner_group_state = {
127
+ * to access this device unaligned.
197
.name = "exynos4210.combiner.groupstate",
128
+ */
129
+ .min_access_size = 4,
130
+ .max_access_size = 4,
131
+ .unaligned = false,
132
+ },
133
+};
134
+
135
+static void imx2_wdt_realize(DeviceState *dev, Error **errp)
136
+{
137
+ IMX2WdtState *s = IMX2_WDT(dev);
138
+
139
+ memory_region_init_io(&s->mmio, OBJECT(dev),
140
+ &imx2_wdt_ops, s,
141
+ TYPE_IMX2_WDT".mmio",
142
+ IMX2_WDT_REG_NUM * sizeof(uint16_t));
143
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
144
+}
145
+
146
+static void imx2_wdt_class_init(ObjectClass *klass, void *data)
147
+{
148
+ DeviceClass *dc = DEVICE_CLASS(klass);
149
+
150
+ dc->realize = imx2_wdt_realize;
151
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
152
+}
153
+
154
+static const TypeInfo imx2_wdt_info = {
155
+ .name = TYPE_IMX2_WDT,
156
+ .parent = TYPE_SYS_BUS_DEVICE,
157
+ .instance_size = sizeof(IMX2WdtState),
158
+ .class_init = imx2_wdt_class_init,
159
+};
160
+
161
+static WatchdogTimerModel model = {
162
+ .wdt_name = "imx2-watchdog",
163
+ .wdt_description = "i.MX2 Watchdog",
164
+};
165
+
166
+static void imx2_wdt_register_type(void)
167
+{
168
+ watchdog_add_model(&model);
169
+ type_register_static(&imx2_wdt_info);
170
+}
171
+type_init(imx2_wdt_register_type)
172
--
198
--
173
2.16.1
199
2.25.1
174
175
diff view generated by jsdifflib
1
In order to support derived exceptions (exceptions generated in
1
The only time we use the int_combiner_irq[] and ext_combiner_irq[]
2
the course of trying to take an exception), we need to be able
2
arrays in the Exynos4210Irq struct is during realize of the SoC -- we
3
to handle prioritizing whether to take the original exception
3
initialize them with the input IRQs of the combiner devices, and then
4
or the derived exception.
4
connect those to outputs of other devices in
5
exynos4210_init_board_irqs(). Now that the combiner objects are
6
easily accessible as s->int_combiner and s->ext_combiner we can make
7
the connections directly from one device to the other without going
8
via these arrays.
5
9
6
We do this by introducing a new function
10
Since these are the only two remaining elements of Exynos4210Irq,
7
armv7m_nvic_set_pending_derived() which the exception-taking code in
11
we can remove that struct entirely.
8
helper.c will call when a derived exception occurs. Derived
9
exceptions are dealt with mostly like normal pending exceptions, so
10
we share the implementation with the armv7m_nvic_set_pending()
11
function.
12
13
Note that the way we structure this is significantly different
14
from the v8M Arm ARM pseudocode: that does all the prioritization
15
logic in the DerivedLateArrival() function, whereas we choose to
16
let the existing "identify highest priority exception" logic
17
do the prioritization for us. The effect is the same, though.
18
12
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 1517324542-6607-2-git-send-email-peter.maydell@linaro.org
15
Message-id: 20220404154658.565020-19-peter.maydell@linaro.org
22
---
16
---
23
target/arm/cpu.h | 13 ++++++++++
17
include/hw/arm/exynos4210.h | 6 ------
24
hw/intc/armv7m_nvic.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--
18
hw/arm/exynos4210.c | 34 ++++++++--------------------------
25
hw/intc/trace-events | 2 +-
19
2 files changed, 8 insertions(+), 32 deletions(-)
26
3 files changed, 80 insertions(+), 3 deletions(-)
27
20
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
29
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
23
--- a/include/hw/arm/exynos4210.h
31
+++ b/target/arm/cpu.h
24
+++ b/include/hw/arm/exynos4210.h
32
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
25
@@ -XXX,XX +XXX,XX @@
33
* of architecturally banked exceptions.
34
*/
26
*/
35
void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
27
#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
36
+/**
28
37
+ * armv7m_nvic_set_pending_derived: mark this derived exception as pending
29
-typedef struct Exynos4210Irq {
38
+ * @opaque: the NVIC
30
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
39
+ * @irq: the exception number to mark pending
31
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
40
+ * @secure: false for non-banked exceptions or for the nonsecure
32
-} Exynos4210Irq;
41
+ * version of a banked exception, true for the secure version of a banked
33
-
42
+ * exception.
34
struct Exynos4210State {
43
+ *
35
/*< private >*/
44
+ * Similar to armv7m_nvic_set_pending(), but specifically for derived
36
SysBusDevice parent_obj;
45
+ * exceptions (exceptions generated in the course of trying to take
37
/*< public >*/
46
+ * a different exception).
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
47
+ */
39
- Exynos4210Irq irqs;
48
+void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
40
qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
49
/**
41
50
* armv7m_nvic_acknowledge_irq: make highest priority pending exception active
42
MemoryRegion chipid_mem;
51
* @opaque: the NVIC
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
52
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
53
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/intc/armv7m_nvic.c
45
--- a/hw/arm/exynos4210.c
55
+++ b/hw/intc/armv7m_nvic.c
46
+++ b/hw/arm/exynos4210.c
56
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_clear_pending(void *opaque, int irq, bool secure)
47
@@ -XXX,XX +XXX,XX @@ static int mapline_size(const int *mapline)
48
static void exynos4210_init_board_irqs(Exynos4210State *s)
49
{
50
uint32_t grp, bit, irq_id, n;
51
- Exynos4210Irq *is = &s->irqs;
52
DeviceState *extgicdev = DEVICE(&s->ext_gic);
53
+ DeviceState *intcdev = DEVICE(&s->int_combiner);
54
+ DeviceState *extcdev = DEVICE(&s->ext_combiner);
55
int splitcount = 0;
56
DeviceState *splitter;
57
const int *mapline;
58
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
59
splitin = 0;
60
for (;;) {
61
s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
62
- qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
63
- qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
64
+ qdev_connect_gpio_out(splitter, splitin,
65
+ qdev_get_gpio_in(intcdev, in));
66
+ qdev_connect_gpio_out(splitter, splitin + 1,
67
+ qdev_get_gpio_in(extcdev, in));
68
splitin += 2;
69
if (!mapline) {
70
break;
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
72
qdev_realize(splitter, NULL, &error_abort);
73
splitcount++;
74
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
75
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
76
+ qdev_connect_gpio_out(splitter, 0, qdev_get_gpio_in(intcdev, n));
77
qdev_connect_gpio_out(splitter, 1,
78
qdev_get_gpio_in(extgicdev, irq_id - 32));
79
} else {
80
- s->irq_table[n] = is->int_combiner_irq[n];
81
+ s->irq_table[n] = qdev_get_gpio_in(intcdev, n);
82
}
57
}
83
}
84
/*
85
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
86
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
58
}
87
}
59
88
60
-void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
89
-/*
61
+static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure,
90
- * Get Combiner input GPIO into irqs structure
62
+ bool derived)
91
- */
63
{
92
-static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
64
+ /* Pend an exception, including possibly escalating it to HardFault.
93
- DeviceState *dev, int ext)
65
+ *
94
-{
66
+ * This function handles both "normal" pending of interrupts and
95
- int n;
67
+ * exceptions, and also derived exceptions (ones which occur as
96
- int max;
68
+ * a result of trying to take some other exception).
97
- qemu_irq *irq;
69
+ *
98
-
70
+ * If derived == true, the caller guarantees that we are part way through
99
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
71
+ * trying to take an exception (but have not yet called
100
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
72
+ * armv7m_nvic_acknowledge_irq() to make it active), and so:
101
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
73
+ * - s->vectpending is the "original exception" we were trying to take
102
-
74
+ * - irq is the "derived exception"
103
- for (n = 0; n < max; n++) {
75
+ * - nvic_exec_prio(s) gives the priority before exception entry
104
- irq[n] = qdev_get_gpio_in(dev, n);
76
+ * Here we handle the prioritization logic which the pseudocode puts
105
- }
77
+ * in the DerivedLateArrival() function.
106
-}
78
+ */
107
-
79
+
108
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
80
NVICState *s = (NVICState *)opaque;
109
0x09, 0x00, 0x00, 0x00 };
81
bool banked = exc_is_banked(irq);
110
82
VecInfo *vec;
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
83
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
112
sysbus_connect_irq(busdev, n,
84
113
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
85
vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
86
87
- trace_nvic_set_pending(irq, secure, vec->enabled, vec->prio);
88
+ trace_nvic_set_pending(irq, secure, derived, vec->enabled, vec->prio);
89
+
90
+ if (derived) {
91
+ /* Derived exceptions are always synchronous. */
92
+ assert(irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV);
93
+
94
+ if (irq == ARMV7M_EXCP_DEBUG &&
95
+ exc_group_prio(s, vec->prio, secure) >= nvic_exec_prio(s)) {
96
+ /* DebugMonitorFault, but its priority is lower than the
97
+ * preempted exception priority: just ignore it.
98
+ */
99
+ return;
100
+ }
101
+
102
+ if (irq == ARMV7M_EXCP_HARD && vec->prio >= s->vectpending_prio) {
103
+ /* If this is a terminal exception (one which means we cannot
104
+ * take the original exception, like a failure to read its
105
+ * vector table entry), then we must take the derived exception.
106
+ * If the derived exception can't take priority over the
107
+ * original exception, then we go into Lockup.
108
+ *
109
+ * For QEMU, we rely on the fact that a derived exception is
110
+ * terminal if and only if it's reported to us as HardFault,
111
+ * which saves having to have an extra argument is_terminal
112
+ * that we'd only use in one place.
113
+ */
114
+ cpu_abort(&s->cpu->parent_obj,
115
+ "Lockup: can't take terminal derived exception "
116
+ "(original exception priority %d)\n",
117
+ s->vectpending_prio);
118
+ }
119
+ /* We now continue with the same code as for a normal pending
120
+ * exception, which will cause us to pend the derived exception.
121
+ * We'll then take either the original or the derived exception
122
+ * based on which is higher priority by the usual mechanism
123
+ * for selecting the highest priority pending interrupt.
124
+ */
125
+ }
126
127
if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
128
/* If a synchronous exception is pending then it may be
129
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
130
}
114
}
131
}
115
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
132
116
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
133
+void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
117
134
+{
118
/* External Interrupt Combiner */
135
+ do_armv7m_nvic_set_pending(opaque, irq, secure, false);
119
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
136
+}
120
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
137
+
121
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
138
+void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
122
}
139
+{
123
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
140
+ do_armv7m_nvic_set_pending(opaque, irq, secure, true);
124
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
141
+}
125
142
+
126
/* Initialize board IRQs. */
143
/* Make pending IRQ active. */
144
bool armv7m_nvic_acknowledge_irq(void *opaque)
145
{
146
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/intc/trace-events
149
+++ b/hw/intc/trace-events
150
@@ -XXX,XX +XXX,XX @@ nvic_set_prio(int irq, bool secure, uint8_t prio) "NVIC set irq %d secure-bank %
151
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"
152
nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
153
nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
154
-nvic_set_pending(int irq, bool secure, int en, int prio) "NVIC set pending irq %d secure-bank %d (enabled: %d priority %d)"
155
+nvic_set_pending(int irq, bool secure, bool derived, int en, int prio) "NVIC set pending irq %d secure-bank %d derived %d (enabled: %d priority %d)"
156
nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear pending irq %d secure-bank %d (enabled: %d priority %d)"
157
nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
158
nvic_acknowledge_irq(int irq, int prio, bool targets_secure) "NVIC acknowledge IRQ: %d now active (prio %d targets_secure %d)"
159
--
127
--
160
2.16.1
128
2.25.1
161
162
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
Save the high parts of the Zregs and all of the Pregs.
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
The ZCR_ELx registers are migrated via the CP mechanism.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20180123035349.24538-4-richard.henderson@linaro.org
5
Message-id: 20220324181557.203805-2-zongyuan.li@smartx.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
7
---
12
target/arm/machine.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
8
hw/arm/realview.c | 33 ++++++++++++++++++++++++---------
13
1 file changed, 53 insertions(+)
9
1 file changed, 24 insertions(+), 9 deletions(-)
14
10
15
diff --git a/target/arm/machine.c b/target/arm/machine.c
11
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/machine.c
13
--- a/hw/arm/realview.c
18
+++ b/target/arm/machine.c
14
+++ b/hw/arm/realview.c
19
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_iwmmxt = {
15
@@ -XXX,XX +XXX,XX @@
20
}
16
#include "hw/sysbus.h"
17
#include "hw/arm/boot.h"
18
#include "hw/arm/primecell.h"
19
+#include "hw/core/split-irq.h"
20
#include "hw/net/lan9118.h"
21
#include "hw/net/smc91c111.h"
22
#include "hw/pci/pci.h"
23
+#include "hw/qdev-core.h"
24
#include "net/net.h"
25
#include "sysemu/sysemu.h"
26
#include "hw/boards.h"
27
@@ -XXX,XX +XXX,XX @@ static const int realview_board_id[] = {
28
0x76d
21
};
29
};
22
30
23
+#ifdef TARGET_AARCH64
31
+static void split_irq_from_named(DeviceState *src, const char* outname,
24
+/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
32
+ qemu_irq out1, qemu_irq out2) {
25
+ * and ARMPredicateReg is actively empty. This triggers errors
33
+ DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
26
+ * in the expansion of the VMSTATE macros.
27
+ */
28
+
34
+
29
+static bool sve_needed(void *opaque)
35
+ qdev_prop_set_uint32(splitter, "num-lines", 2);
30
+{
31
+ ARMCPU *cpu = opaque;
32
+ CPUARMState *env = &cpu->env;
33
+
36
+
34
+ return arm_feature(env, ARM_FEATURE_SVE);
37
+ qdev_realize_and_unref(splitter, NULL, &error_fatal);
38
+
39
+ qdev_connect_gpio_out(splitter, 0, out1);
40
+ qdev_connect_gpio_out(splitter, 1, out2);
41
+ qdev_connect_gpio_out_named(src, outname, 0,
42
+ qdev_get_gpio_in(splitter, 0));
35
+}
43
+}
36
+
44
+
37
+/* The first two words of each Zreg is stored in VFP state. */
45
static void realview_init(MachineState *machine,
38
+static const VMStateDescription vmstate_zreg_hi_reg = {
46
enum realview_board_type board_type)
39
+ .name = "cpu/sve/zreg_hi",
47
{
40
+ .version_id = 1,
48
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
41
+ .minimum_version_id = 1,
49
DeviceState *dev, *sysctl, *gpio2, *pl041;
42
+ .fields = (VMStateField[]) {
50
SysBusDevice *busdev;
43
+ VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
51
qemu_irq pic[64];
44
+ VMSTATE_END_OF_LIST()
52
- qemu_irq mmc_irq[2];
45
+ }
53
PCIBus *pci_bus = NULL;
46
+};
54
NICInfo *nd;
55
DriveInfo *dinfo;
56
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
57
* and the PL061 has them the other way about. Also the card
58
* detect line is inverted.
59
*/
60
- mmc_irq[0] = qemu_irq_split(
61
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
62
- qdev_get_gpio_in(gpio2, 1));
63
- mmc_irq[1] = qemu_irq_split(
64
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
65
- qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
66
- qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
67
- qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
68
+ split_irq_from_named(dev, "card-read-only",
69
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
70
+ qdev_get_gpio_in(gpio2, 1));
47
+
71
+
48
+static const VMStateDescription vmstate_preg_reg = {
72
+ split_irq_from_named(dev, "card-inserted",
49
+ .name = "cpu/sve/preg",
73
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
50
+ .version_id = 1,
74
+ qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
51
+ .minimum_version_id = 1,
52
+ .fields = (VMStateField[]) {
53
+ VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
54
+ VMSTATE_END_OF_LIST()
55
+ }
56
+};
57
+
75
+
58
+static const VMStateDescription vmstate_sve = {
76
dinfo = drive_get(IF_SD, 0, 0);
59
+ .name = "cpu/sve",
77
if (dinfo) {
60
+ .version_id = 1,
78
DeviceState *card;
61
+ .minimum_version_id = 1,
62
+ .needed = sve_needed,
63
+ .fields = (VMStateField[]) {
64
+ VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
65
+ vmstate_zreg_hi_reg, ARMVectorReg),
66
+ VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
67
+ vmstate_preg_reg, ARMPredicateReg),
68
+ VMSTATE_END_OF_LIST()
69
+ }
70
+};
71
+#endif /* AARCH64 */
72
+
73
static bool m_needed(void *opaque)
74
{
75
ARMCPU *cpu = opaque;
76
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_arm_cpu = {
77
&vmstate_pmsav7,
78
&vmstate_pmsav8,
79
&vmstate_m_security,
80
+#ifdef TARGET_AARCH64
81
+ &vmstate_sve,
82
+#endif
83
NULL
84
}
85
};
86
--
79
--
87
2.16.1
80
2.25.1
88
89
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
Add both SVE exception state and vector length.
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180123035349.24538-6-richard.henderson@linaro.org
5
Message-id: 20220324181557.203805-3-zongyuan.li@smartx.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
7
---
10
target/arm/cpu.h | 8 ++++++++
8
hw/arm/stellaris.c | 15 +++++++++++++--
11
target/arm/translate.h | 2 ++
9
1 file changed, 13 insertions(+), 2 deletions(-)
12
target/arm/helper.c | 25 ++++++++++++++++++++++++-
13
target/arm/translate-a64.c | 2 ++
14
4 files changed, 36 insertions(+), 1 deletion(-)
15
10
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
13
--- a/hw/arm/stellaris.c
19
+++ b/target/arm/cpu.h
14
+++ b/hw/arm/stellaris.c
20
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
15
@@ -XXX,XX +XXX,XX @@
21
#define ARM_TBFLAG_TBI0_MASK (0x1ull << ARM_TBFLAG_TBI0_SHIFT)
16
22
#define ARM_TBFLAG_TBI1_SHIFT 1 /* TBI1 for EL0/1 */
17
#include "qemu/osdep.h"
23
#define ARM_TBFLAG_TBI1_MASK (0x1ull << ARM_TBFLAG_TBI1_SHIFT)
18
#include "qapi/error.h"
24
+#define ARM_TBFLAG_SVEEXC_EL_SHIFT 2
19
+#include "hw/core/split-irq.h"
25
+#define ARM_TBFLAG_SVEEXC_EL_MASK (0x3 << ARM_TBFLAG_SVEEXC_EL_SHIFT)
20
#include "hw/sysbus.h"
26
+#define ARM_TBFLAG_ZCR_LEN_SHIFT 4
21
#include "hw/sd/sd.h"
27
+#define ARM_TBFLAG_ZCR_LEN_MASK (0xf << ARM_TBFLAG_ZCR_LEN_SHIFT)
22
#include "hw/ssi/ssi.h"
28
23
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
29
/* some convenience accessor macros */
24
DeviceState *ssddev;
30
#define ARM_TBFLAG_AARCH64_STATE(F) \
25
DriveInfo *dinfo;
31
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
26
DeviceState *carddev;
32
(((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
27
+ DeviceState *gpio_d_splitter;
33
#define ARM_TBFLAG_TBI1(F) \
28
BlockBackend *blk;
34
(((F) & ARM_TBFLAG_TBI1_MASK) >> ARM_TBFLAG_TBI1_SHIFT)
29
35
+#define ARM_TBFLAG_SVEEXC_EL(F) \
30
/*
36
+ (((F) & ARM_TBFLAG_SVEEXC_EL_MASK) >> ARM_TBFLAG_SVEEXC_EL_SHIFT)
31
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
37
+#define ARM_TBFLAG_ZCR_LEN(F) \
32
&error_fatal);
38
+ (((F) & ARM_TBFLAG_ZCR_LEN_MASK) >> ARM_TBFLAG_ZCR_LEN_SHIFT)
33
39
34
ssddev = ssi_create_peripheral(bus, "ssd0323");
40
static inline bool bswap_code(bool sctlr_b)
35
- gpio_out[GPIO_D][0] = qemu_irq_split(
41
{
36
- qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
42
diff --git a/target/arm/translate.h b/target/arm/translate.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/translate.h
45
+++ b/target/arm/translate.h
46
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
47
bool tbi1; /* TBI1 for EL0/1, not used for EL2/3 */
48
bool ns; /* Use non-secure CPREG bank on access */
49
int fp_excp_el; /* FP exception EL or 0 if enabled */
50
+ int sve_excp_el; /* SVE exception EL or 0 if enabled */
51
+ int sve_len; /* SVE vector length in bytes */
52
/* Flag indicating that exceptions from secure mode are routed to EL3. */
53
bool secure_routed_to_el3;
54
bool vfp_enabled; /* FP enabled via FPSCR.EN */
55
diff --git a/target/arm/helper.c b/target/arm/helper.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/helper.c
58
+++ b/target/arm/helper.c
59
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
60
target_ulong *cs_base, uint32_t *pflags)
61
{
62
ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
63
+ int fp_el = fp_exception_el(env);
64
uint32_t flags;
65
66
if (is_a64(env)) {
67
+ int sve_el = sve_exception_el(env);
68
+ uint32_t zcr_len;
69
+
37
+
70
*pc = env->pc;
38
+ gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
71
flags = ARM_TBFLAG_AARCH64_STATE_MASK;
39
+ qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
72
/* Get control bits for tagged addresses */
40
+ qdev_realize_and_unref(gpio_d_splitter, NULL, &error_fatal);
73
flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
41
+ qdev_connect_gpio_out(
74
flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
42
+ gpio_d_splitter, 0,
75
+ flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
43
+ qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0));
44
+ qdev_connect_gpio_out(
45
+ gpio_d_splitter, 1,
46
qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0));
47
+ gpio_out[GPIO_D][0] = qdev_get_gpio_in(gpio_d_splitter, 0);
76
+
48
+
77
+ /* If SVE is disabled, but FP is enabled,
49
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0);
78
+ then the effective len is 0. */
50
79
+ if (sve_el != 0 && fp_el == 0) {
51
/* Make sure the select pin is high. */
80
+ zcr_len = 0;
81
+ } else {
82
+ int current_el = arm_current_el(env);
83
+
84
+ zcr_len = env->vfp.zcr_el[current_el <= 1 ? 1 : current_el];
85
+ zcr_len &= 0xf;
86
+ if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
87
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
88
+ }
89
+ if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
90
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
91
+ }
92
+ }
93
+ flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
94
} else {
95
*pc = env->regs[15];
96
flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
97
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
98
if (arm_cpu_data_is_big_endian(env)) {
99
flags |= ARM_TBFLAG_BE_DATA_MASK;
100
}
101
- flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
102
+ flags |= fp_el << ARM_TBFLAG_FPEXC_EL_SHIFT;
103
104
if (arm_v7m_is_handler_mode(env)) {
105
flags |= ARM_TBFLAG_HANDLER_MASK;
106
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/translate-a64.c
109
+++ b/target/arm/translate-a64.c
110
@@ -XXX,XX +XXX,XX @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
111
dc->user = (dc->current_el == 0);
112
#endif
113
dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
114
+ dc->sve_excp_el = ARM_TBFLAG_SVEEXC_EL(dc->base.tb->flags);
115
+ dc->sve_len = (ARM_TBFLAG_ZCR_LEN(dc->base.tb->flags) + 1) * 16;
116
dc->vec_len = 0;
117
dc->vec_stride = 0;
118
dc->cp_regs = arm_cpu->cp_regs;
119
--
52
--
120
2.16.1
53
2.25.1
121
122
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20180123035349.24538-3-richard.henderson@linaro.org
5
Message-id: 20220324181557.203805-5-zongyuan.li@smartx.com
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/811
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
8
---
9
target/arm/cpu.h | 12 ++++++++++++
9
include/hw/irq.h | 5 -----
10
1 file changed, 12 insertions(+)
10
hw/core/irq.c | 15 ---------------
11
2 files changed, 20 deletions(-)
11
12
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/include/hw/irq.h b/include/hw/irq.h
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.h
15
--- a/include/hw/irq.h
15
+++ b/target/arm/cpu.h
16
+++ b/include/hw/irq.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct ARMVectorReg {
17
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
17
uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
18
/* Returns a new IRQ with opposite polarity. */
18
} ARMVectorReg;
19
qemu_irq qemu_irq_invert(qemu_irq irq);
19
20
20
+/* In AArch32 mode, predicate registers do not exist at all. */
21
-/* Returns a new IRQ which feeds into both the passed IRQs.
21
+#ifdef TARGET_AARCH64
22
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
22
+typedef struct ARMPredicateReg {
23
- */
23
+ uint64_t p[2 * ARM_MAX_VQ / 8] QEMU_ALIGNED(16);
24
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
24
+} ARMPredicateReg;
25
-
25
+#endif
26
/* For internal use in qtest. Similar to qemu_irq_split, but operating
26
+
27
on an existing vector of qemu_irq. */
27
28
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
28
typedef struct CPUARMState {
29
diff --git a/hw/core/irq.c b/hw/core/irq.c
29
/* Regs for current mode. */
30
index XXXXXXX..XXXXXXX 100644
30
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
31
--- a/hw/core/irq.c
31
struct {
32
+++ b/hw/core/irq.c
32
ARMVectorReg zregs[32];
33
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_invert(qemu_irq irq)
33
34
return qemu_allocate_irq(qemu_notirq, irq, 0);
34
+#ifdef TARGET_AARCH64
35
}
35
+ /* Store FFR as pregs[16] to make it easier to treat as any other. */
36
36
+ ARMPredicateReg pregs[17];
37
-static void qemu_splitirq(void *opaque, int line, int level)
37
+#endif
38
-{
38
+
39
- struct IRQState **irq = opaque;
39
uint32_t xregs[16];
40
- irq[0]->handler(irq[0]->opaque, irq[0]->n, level);
40
/* We store these fpcsr fields separately for convenience. */
41
- irq[1]->handler(irq[1]->opaque, irq[1]->n, level);
41
int vec_len;
42
-}
43
-
44
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
45
-{
46
- qemu_irq *s = g_new0(qemu_irq, 2);
47
- s[0] = irq1;
48
- s[1] = irq2;
49
- return qemu_allocate_irq(qemu_splitirq, s, 0);
50
-}
51
-
52
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
53
{
54
int i;
42
--
55
--
43
2.16.1
56
2.25.1
44
45
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2
2
3
Add support for the new ARMv8.2 SHA-3, SM3, SM4 and SHA-512 instructions to
3
Describe that the gic-version influences the maximum number of CPUs.
4
AArch64 user mode emulation.
5
4
6
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
5
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
7
Message-id: 20180207111729.15737-6-ard.biesheuvel@linaro.org
6
Message-id: 20220413231456.35811-1-heinrich.schuchardt@canonical.com
7
[PMM: minor punctuation tweaks]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@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
linux-user/elfload.c | 19 +++++++++++++++++++
11
docs/system/arm/virt.rst | 4 ++--
12
target/arm/cpu64.c | 4 ++++
12
1 file changed, 2 insertions(+), 2 deletions(-)
13
2 files changed, 23 insertions(+)
14
13
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
16
--- a/docs/system/arm/virt.rst
18
+++ b/linux-user/elfload.c
17
+++ b/docs/system/arm/virt.rst
19
@@ -XXX,XX +XXX,XX @@ enum {
18
@@ -XXX,XX +XXX,XX @@ gic-version
20
ARM_HWCAP_A64_SHA1 = 1 << 5,
19
Valid values are:
21
ARM_HWCAP_A64_SHA2 = 1 << 6,
20
22
ARM_HWCAP_A64_CRC32 = 1 << 7,
21
``2``
23
+ ARM_HWCAP_A64_ATOMICS = 1 << 8,
22
- GICv2
24
+ ARM_HWCAP_A64_FPHP = 1 << 9,
23
+ GICv2. Note that this limits the number of CPUs to 8.
25
+ ARM_HWCAP_A64_ASIMDHP = 1 << 10,
24
``3``
26
+ ARM_HWCAP_A64_CPUID = 1 << 11,
25
- GICv3
27
+ ARM_HWCAP_A64_ASIMDRDM = 1 << 12,
26
+ GICv3. This allows up to 512 CPUs.
28
+ ARM_HWCAP_A64_JSCVT = 1 << 13,
27
``host``
29
+ ARM_HWCAP_A64_FCMA = 1 << 14,
28
Use the same GIC version the host provides, when using KVM
30
+ ARM_HWCAP_A64_LRCPC = 1 << 15,
29
``max``
31
+ ARM_HWCAP_A64_DCPOP = 1 << 16,
32
+ ARM_HWCAP_A64_SHA3 = 1 << 17,
33
+ ARM_HWCAP_A64_SM3 = 1 << 18,
34
+ ARM_HWCAP_A64_SM4 = 1 << 19,
35
+ ARM_HWCAP_A64_ASIMDDP = 1 << 20,
36
+ ARM_HWCAP_A64_SHA512 = 1 << 21,
37
+ ARM_HWCAP_A64_SVE = 1 << 22,
38
};
39
40
#define ELF_HWCAP get_elf_hwcap()
41
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
42
GET_FEATURE(ARM_FEATURE_V8_SHA1, ARM_HWCAP_A64_SHA1);
43
GET_FEATURE(ARM_FEATURE_V8_SHA256, ARM_HWCAP_A64_SHA2);
44
GET_FEATURE(ARM_FEATURE_CRC, ARM_HWCAP_A64_CRC32);
45
+ GET_FEATURE(ARM_FEATURE_V8_SHA3, ARM_HWCAP_A64_SHA3);
46
+ GET_FEATURE(ARM_FEATURE_V8_SM3, ARM_HWCAP_A64_SM3);
47
+ GET_FEATURE(ARM_FEATURE_V8_SM4, ARM_HWCAP_A64_SM4);
48
+ GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
49
#undef GET_FEATURE
50
51
return hwcaps;
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_any_initfn(Object *obj)
57
set_feature(&cpu->env, ARM_FEATURE_V8_AES);
58
set_feature(&cpu->env, ARM_FEATURE_V8_SHA1);
59
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
60
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA512);
61
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA3);
62
+ set_feature(&cpu->env, ARM_FEATURE_V8_SM3);
63
+ set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
64
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
65
set_feature(&cpu->env, ARM_FEATURE_CRC);
66
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
67
--
30
--
68
2.16.1
31
2.25.1
69
70
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This implements emulation of the new SM4 instructions that have
3
Similar to the Aspeed code in include/misc/aspeed_scu.h, we define
4
been added as an optional extension to the ARMv8 Crypto Extensions
4
the PWRON STRAP fields in their corresponding module for NPCM7XX.
5
in ARM v8.2.
6
5
7
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Message-id: 20180207111729.15737-5-ard.biesheuvel@linaro.org
7
Reviewed-by: Patrick Venture <venture@google.com>
8
Message-id: 20220411165842.3912945-2-wuhaotsh@google.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/cpu.h | 1 +
12
include/hw/misc/npcm7xx_gcr.h | 30 ++++++++++++++++++++++++++++++
13
target/arm/helper.h | 3 ++
13
1 file changed, 30 insertions(+)
14
target/arm/crypto_helper.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++
15
target/arm/translate-a64.c | 8 ++++
16
4 files changed, 103 insertions(+)
17
14
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
17
--- a/include/hw/misc/npcm7xx_gcr.h
21
+++ b/target/arm/cpu.h
18
+++ b/include/hw/misc/npcm7xx_gcr.h
22
@@ -XXX,XX +XXX,XX @@ enum arm_features {
19
@@ -XXX,XX +XXX,XX @@
23
ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
20
#include "exec/memory.h"
24
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
21
#include "hw/sysbus.h"
25
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
22
26
+ ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
23
+/*
27
};
24
+ * NPCM7XX PWRON STRAP bit fields
28
25
+ * 12: SPI0 powered by VSBV3 at 1.8V
29
static inline int arm_feature(CPUARMState *env, int feature)
26
+ * 11: System flash attached to BMC
30
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
+ * 10: BSP alternative pins.
31
index XXXXXXX..XXXXXXX 100644
28
+ * 9:8: Flash UART command route enabled.
32
--- a/target/arm/helper.h
29
+ * 7: Security enabled.
33
+++ b/target/arm/helper.h
30
+ * 6: HI-Z state control.
34
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
31
+ * 5: ECC disabled.
35
DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
32
+ * 4: Reserved
36
DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
33
+ * 3: JTAG2 enabled.
37
34
+ * 2:0: CPU and DRAM clock frequency.
38
+DEF_HELPER_FLAGS_2(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr)
35
+ */
39
+DEF_HELPER_FLAGS_3(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
36
+#define NPCM7XX_PWRON_STRAP_SPI0F18 BIT(12)
37
+#define NPCM7XX_PWRON_STRAP_SFAB BIT(11)
38
+#define NPCM7XX_PWRON_STRAP_BSPA BIT(10)
39
+#define NPCM7XX_PWRON_STRAP_FUP(x) ((x) << 8)
40
+#define FUP_NORM_UART2 3
41
+#define FUP_PROG_UART3 2
42
+#define FUP_PROG_UART2 1
43
+#define FUP_NORM_UART3 0
44
+#define NPCM7XX_PWRON_STRAP_SECEN BIT(7)
45
+#define NPCM7XX_PWRON_STRAP_HIZ BIT(6)
46
+#define NPCM7XX_PWRON_STRAP_ECC BIT(5)
47
+#define NPCM7XX_PWRON_STRAP_RESERVE1 BIT(4)
48
+#define NPCM7XX_PWRON_STRAP_J2EN BIT(3)
49
+#define NPCM7XX_PWRON_STRAP_CKFRQ(x) (x)
50
+#define CKFRQ_SKIPINIT 0x000
51
+#define CKFRQ_DEFAULT 0x111
40
+
52
+
41
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
53
/*
42
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
54
* Number of registers in our device state structure. Don't change this without
43
DEF_HELPER_2(dc_zva, void, env, i64)
55
* incrementing the version_id in the vmstate.
44
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/crypto_helper.c
47
+++ b/target/arm/crypto_helper.c
48
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
49
rd[0] = d.l[0];
50
rd[1] = d.l[1];
51
}
52
+
53
+static uint8_t const sm4_sbox[] = {
54
+ 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
55
+ 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
56
+ 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
57
+ 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
58
+ 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
59
+ 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
60
+ 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
61
+ 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
62
+ 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
63
+ 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
64
+ 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
65
+ 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
66
+ 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
67
+ 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
68
+ 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
69
+ 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
70
+ 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
71
+ 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
72
+ 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
73
+ 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
74
+ 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
75
+ 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
76
+ 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
77
+ 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
78
+ 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
79
+ 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
80
+ 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
81
+ 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
82
+ 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
83
+ 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
84
+ 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
85
+ 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
86
+};
87
+
88
+void HELPER(crypto_sm4e)(void *vd, void *vn)
89
+{
90
+ uint64_t *rd = vd;
91
+ uint64_t *rn = vn;
92
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
93
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
94
+ uint32_t t, i;
95
+
96
+ for (i = 0; i < 4; i++) {
97
+ t = CR_ST_WORD(d, (i + 1) % 4) ^
98
+ CR_ST_WORD(d, (i + 2) % 4) ^
99
+ CR_ST_WORD(d, (i + 3) % 4) ^
100
+ CR_ST_WORD(n, i);
101
+
102
+ t = sm4_sbox[t & 0xff] |
103
+ sm4_sbox[(t >> 8) & 0xff] << 8 |
104
+ sm4_sbox[(t >> 16) & 0xff] << 16 |
105
+ sm4_sbox[(t >> 24) & 0xff] << 24;
106
+
107
+ CR_ST_WORD(d, i) ^= t ^ rol32(t, 2) ^ rol32(t, 10) ^ rol32(t, 18) ^
108
+ rol32(t, 24);
109
+ }
110
+
111
+ rd[0] = d.l[0];
112
+ rd[1] = d.l[1];
113
+}
114
+
115
+void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm)
116
+{
117
+ uint64_t *rd = vd;
118
+ uint64_t *rn = vn;
119
+ uint64_t *rm = vm;
120
+ union CRYPTO_STATE d;
121
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
122
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
123
+ uint32_t t, i;
124
+
125
+ d = n;
126
+ for (i = 0; i < 4; i++) {
127
+ t = CR_ST_WORD(d, (i + 1) % 4) ^
128
+ CR_ST_WORD(d, (i + 2) % 4) ^
129
+ CR_ST_WORD(d, (i + 3) % 4) ^
130
+ CR_ST_WORD(m, i);
131
+
132
+ t = sm4_sbox[t & 0xff] |
133
+ sm4_sbox[(t >> 8) & 0xff] << 8 |
134
+ sm4_sbox[(t >> 16) & 0xff] << 16 |
135
+ sm4_sbox[(t >> 24) & 0xff] << 24;
136
+
137
+ CR_ST_WORD(d, i) ^= t ^ rol32(t, 13) ^ rol32(t, 23);
138
+ }
139
+
140
+ rd[0] = d.l[0];
141
+ rd[1] = d.l[1];
142
+}
143
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/target/arm/translate-a64.c
146
+++ b/target/arm/translate-a64.c
147
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
148
feature = ARM_FEATURE_V8_SM3;
149
genfn = gen_helper_crypto_sm3partw2;
150
break;
151
+ case 2: /* SM4EKEY */
152
+ feature = ARM_FEATURE_V8_SM4;
153
+ genfn = gen_helper_crypto_sm4ekey;
154
+ break;
155
default:
156
unallocated_encoding(s);
157
return;
158
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
159
feature = ARM_FEATURE_V8_SHA512;
160
genfn = gen_helper_crypto_sha512su0;
161
break;
162
+ case 1: /* SM4E */
163
+ feature = ARM_FEATURE_V8_SM4;
164
+ genfn = gen_helper_crypto_sm4e;
165
+ break;
166
default:
167
unallocated_encoding(s);
168
return;
169
--
56
--
170
2.16.1
57
2.25.1
171
172
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This implements emulation of the new SM3 instructions that have
3
This patch uses the defined fields to describe PWRON STRAPs for
4
been added as an optional extension to the ARMv8 Crypto Extensions
4
better readability.
5
in ARM v8.2.
6
5
7
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Message-id: 20180207111729.15737-4-ard.biesheuvel@linaro.org
7
Reviewed-by: Patrick Venture <venture@google.com>
8
Message-id: 20220411165842.3912945-3-wuhaotsh@google.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/cpu.h | 1 +
12
hw/arm/npcm7xx_boards.c | 24 +++++++++++++++++++-----
13
target/arm/helper.h | 4 ++
13
1 file changed, 19 insertions(+), 5 deletions(-)
14
target/arm/crypto_helper.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++
15
target/arm/translate-a64.c | 88 ++++++++++++++++++++++++++++++++++++++++--
16
4 files changed, 186 insertions(+), 3 deletions(-)
17
14
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
17
--- a/hw/arm/npcm7xx_boards.c
21
+++ b/target/arm/cpu.h
18
+++ b/hw/arm/npcm7xx_boards.c
22
@@ -XXX,XX +XXX,XX @@ enum arm_features {
19
@@ -XXX,XX +XXX,XX @@
23
ARM_FEATURE_SVE, /* has Scalable Vector Extension */
20
#include "sysemu/sysemu.h"
24
ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
21
#include "sysemu/block-backend.h"
25
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
22
26
+ ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
23
-#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
27
};
24
-#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
28
25
-#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
29
static inline int arm_feature(CPUARMState *env, int feature)
26
-#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
30
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
-#define MORI_BMC_POWER_ON_STRAPS 0x00001fff
31
index XXXXXXX..XXXXXXX 100644
28
+#define NPCM7XX_POWER_ON_STRAPS_DEFAULT ( \
32
--- a/target/arm/helper.h
29
+ NPCM7XX_PWRON_STRAP_SPI0F18 | \
33
+++ b/target/arm/helper.h
30
+ NPCM7XX_PWRON_STRAP_SFAB | \
34
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
31
+ NPCM7XX_PWRON_STRAP_BSPA | \
35
DEF_HELPER_FLAGS_2(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr)
32
+ NPCM7XX_PWRON_STRAP_FUP(FUP_NORM_UART2) | \
36
DEF_HELPER_FLAGS_3(crypto_sha512su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
33
+ NPCM7XX_PWRON_STRAP_SECEN | \
37
34
+ NPCM7XX_PWRON_STRAP_HIZ | \
38
+DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
35
+ NPCM7XX_PWRON_STRAP_ECC | \
39
+DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
36
+ NPCM7XX_PWRON_STRAP_RESERVE1 | \
40
+DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
37
+ NPCM7XX_PWRON_STRAP_J2EN | \
38
+ NPCM7XX_PWRON_STRAP_CKFRQ(CKFRQ_DEFAULT))
41
+
39
+
42
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
40
+#define NPCM750_EVB_POWER_ON_STRAPS ( \
43
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
41
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_J2EN)
44
DEF_HELPER_2(dc_zva, void, env, i64)
42
+#define QUANTA_GSJ_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
45
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
43
+#define QUANTA_GBS_POWER_ON_STRAPS ( \
46
index XXXXXXX..XXXXXXX 100644
44
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_SFAB)
47
--- a/target/arm/crypto_helper.c
45
+#define KUDO_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
48
+++ b/target/arm/crypto_helper.c
46
+#define MORI_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
49
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm)
47
50
rd[0] += s1_512(rn[0]) + rm[0];
48
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
51
rd[1] += s1_512(rn[1]) + rm[1];
52
}
53
+
54
+void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm)
55
+{
56
+ uint64_t *rd = vd;
57
+ uint64_t *rn = vn;
58
+ uint64_t *rm = vm;
59
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
60
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
61
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
62
+ uint32_t t;
63
+
64
+ t = CR_ST_WORD(d, 0) ^ CR_ST_WORD(n, 0) ^ ror32(CR_ST_WORD(m, 1), 17);
65
+ CR_ST_WORD(d, 0) = t ^ ror32(t, 17) ^ ror32(t, 9);
66
+
67
+ t = CR_ST_WORD(d, 1) ^ CR_ST_WORD(n, 1) ^ ror32(CR_ST_WORD(m, 2), 17);
68
+ CR_ST_WORD(d, 1) = t ^ ror32(t, 17) ^ ror32(t, 9);
69
+
70
+ t = CR_ST_WORD(d, 2) ^ CR_ST_WORD(n, 2) ^ ror32(CR_ST_WORD(m, 3), 17);
71
+ CR_ST_WORD(d, 2) = t ^ ror32(t, 17) ^ ror32(t, 9);
72
+
73
+ t = CR_ST_WORD(d, 3) ^ CR_ST_WORD(n, 3) ^ ror32(CR_ST_WORD(d, 0), 17);
74
+ CR_ST_WORD(d, 3) = t ^ ror32(t, 17) ^ ror32(t, 9);
75
+
76
+ rd[0] = d.l[0];
77
+ rd[1] = d.l[1];
78
+}
79
+
80
+void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm)
81
+{
82
+ uint64_t *rd = vd;
83
+ uint64_t *rn = vn;
84
+ uint64_t *rm = vm;
85
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
86
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
87
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
88
+ uint32_t t = CR_ST_WORD(n, 0) ^ ror32(CR_ST_WORD(m, 0), 25);
89
+
90
+ CR_ST_WORD(d, 0) ^= t;
91
+ CR_ST_WORD(d, 1) ^= CR_ST_WORD(n, 1) ^ ror32(CR_ST_WORD(m, 1), 25);
92
+ CR_ST_WORD(d, 2) ^= CR_ST_WORD(n, 2) ^ ror32(CR_ST_WORD(m, 2), 25);
93
+ CR_ST_WORD(d, 3) ^= CR_ST_WORD(n, 3) ^ ror32(CR_ST_WORD(m, 3), 25) ^
94
+ ror32(t, 17) ^ ror32(t, 2) ^ ror32(t, 26);
95
+
96
+ rd[0] = d.l[0];
97
+ rd[1] = d.l[1];
98
+}
99
+
100
+void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
101
+ uint32_t opcode)
102
+{
103
+ uint64_t *rd = vd;
104
+ uint64_t *rn = vn;
105
+ uint64_t *rm = vm;
106
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
107
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
108
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
109
+ uint32_t t;
110
+
111
+ assert(imm2 < 4);
112
+
113
+ if (opcode == 0 || opcode == 2) {
114
+ /* SM3TT1A, SM3TT2A */
115
+ t = par(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1));
116
+ } else if (opcode == 1) {
117
+ /* SM3TT1B */
118
+ t = maj(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1));
119
+ } else if (opcode == 3) {
120
+ /* SM3TT2B */
121
+ t = cho(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1));
122
+ } else {
123
+ g_assert_not_reached();
124
+ }
125
+
126
+ t += CR_ST_WORD(d, 0) + CR_ST_WORD(m, imm2);
127
+
128
+ CR_ST_WORD(d, 0) = CR_ST_WORD(d, 1);
129
+
130
+ if (opcode < 2) {
131
+ /* SM3TT1A, SM3TT1B */
132
+ t += CR_ST_WORD(n, 3) ^ ror32(CR_ST_WORD(d, 3), 20);
133
+
134
+ CR_ST_WORD(d, 1) = ror32(CR_ST_WORD(d, 2), 23);
135
+ } else {
136
+ /* SM3TT2A, SM3TT2B */
137
+ t += CR_ST_WORD(n, 3);
138
+ t ^= rol32(t, 9) ^ rol32(t, 17);
139
+
140
+ CR_ST_WORD(d, 1) = ror32(CR_ST_WORD(d, 2), 13);
141
+ }
142
+
143
+ CR_ST_WORD(d, 2) = CR_ST_WORD(d, 3);
144
+ CR_ST_WORD(d, 3) = t;
145
+
146
+ rd[0] = d.l[0];
147
+ rd[1] = d.l[1];
148
+}
149
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/target/arm/translate-a64.c
152
+++ b/target/arm/translate-a64.c
153
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
154
break;
155
}
156
} else {
157
- unallocated_encoding(s);
158
- return;
159
+ switch (opcode) {
160
+ case 0: /* SM3PARTW1 */
161
+ feature = ARM_FEATURE_V8_SM3;
162
+ genfn = gen_helper_crypto_sm3partw1;
163
+ break;
164
+ case 1: /* SM3PARTW2 */
165
+ feature = ARM_FEATURE_V8_SM3;
166
+ genfn = gen_helper_crypto_sm3partw2;
167
+ break;
168
+ default:
169
+ unallocated_encoding(s);
170
+ return;
171
+ }
172
}
173
174
if (!arm_dc_feature(s, feature)) {
175
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
176
case 1: /* BCAX */
177
feature = ARM_FEATURE_V8_SHA3;
178
break;
179
+ case 2: /* SM3SS1 */
180
+ feature = ARM_FEATURE_V8_SM3;
181
+ break;
182
default:
183
unallocated_encoding(s);
184
return;
185
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
186
tcg_temp_free_i64(tcg_res[0]);
187
tcg_temp_free_i64(tcg_res[1]);
188
} else {
189
- g_assert_not_reached();
190
+ TCGv_i32 tcg_op1, tcg_op2, tcg_op3, tcg_res, tcg_zero;
191
+
192
+ tcg_op1 = tcg_temp_new_i32();
193
+ tcg_op2 = tcg_temp_new_i32();
194
+ tcg_op3 = tcg_temp_new_i32();
195
+ tcg_res = tcg_temp_new_i32();
196
+ tcg_zero = tcg_const_i32(0);
197
+
198
+ read_vec_element_i32(s, tcg_op1, rn, 3, MO_32);
199
+ read_vec_element_i32(s, tcg_op2, rm, 3, MO_32);
200
+ read_vec_element_i32(s, tcg_op3, ra, 3, MO_32);
201
+
202
+ tcg_gen_rotri_i32(tcg_res, tcg_op1, 20);
203
+ tcg_gen_add_i32(tcg_res, tcg_res, tcg_op2);
204
+ tcg_gen_add_i32(tcg_res, tcg_res, tcg_op3);
205
+ tcg_gen_rotri_i32(tcg_res, tcg_res, 25);
206
+
207
+ write_vec_element_i32(s, tcg_zero, rd, 0, MO_32);
208
+ write_vec_element_i32(s, tcg_zero, rd, 1, MO_32);
209
+ write_vec_element_i32(s, tcg_zero, rd, 2, MO_32);
210
+ write_vec_element_i32(s, tcg_res, rd, 3, MO_32);
211
+
212
+ tcg_temp_free_i32(tcg_op1);
213
+ tcg_temp_free_i32(tcg_op2);
214
+ tcg_temp_free_i32(tcg_op3);
215
+ tcg_temp_free_i32(tcg_res);
216
+ tcg_temp_free_i32(tcg_zero);
217
}
218
}
219
220
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_xar(DisasContext *s, uint32_t insn)
221
tcg_temp_free_i64(tcg_res[1]);
222
}
223
224
+/* Crypto three-reg imm2
225
+ * 31 21 20 16 15 14 13 12 11 10 9 5 4 0
226
+ * +-----------------------+------+-----+------+--------+------+------+
227
+ * | 1 1 0 0 1 1 1 0 0 1 0 | Rm | 1 0 | imm2 | opcode | Rn | Rd |
228
+ * +-----------------------+------+-----+------+--------+------+------+
229
+ */
230
+static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
231
+{
232
+ int opcode = extract32(insn, 10, 2);
233
+ int imm2 = extract32(insn, 12, 2);
234
+ int rm = extract32(insn, 16, 5);
235
+ int rn = extract32(insn, 5, 5);
236
+ int rd = extract32(insn, 0, 5);
237
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
238
+ TCGv_i32 tcg_imm2, tcg_opcode;
239
+
240
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_SM3)) {
241
+ unallocated_encoding(s);
242
+ return;
243
+ }
244
+
245
+ if (!fp_access_check(s)) {
246
+ return;
247
+ }
248
+
249
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
250
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
251
+ tcg_rm_ptr = vec_full_reg_ptr(s, rm);
252
+ tcg_imm2 = tcg_const_i32(imm2);
253
+ tcg_opcode = tcg_const_i32(opcode);
254
+
255
+ gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2,
256
+ tcg_opcode);
257
+
258
+ tcg_temp_free_ptr(tcg_rd_ptr);
259
+ tcg_temp_free_ptr(tcg_rn_ptr);
260
+ tcg_temp_free_ptr(tcg_rm_ptr);
261
+ tcg_temp_free_i32(tcg_imm2);
262
+ tcg_temp_free_i32(tcg_opcode);
263
+}
264
+
265
/* C3.6 Data processing - SIMD, inc Crypto
266
*
267
* As the decode gets a little complex we are using a table based
268
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
269
{ 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
270
{ 0xce000000, 0xff808000, disas_crypto_four_reg },
271
{ 0xce800000, 0xffe00000, disas_crypto_xar },
272
+ { 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
273
{ 0x00000000, 0x00000000, NULL }
274
};
275
49
276
--
50
--
277
2.16.1
51
2.25.1
278
279
diff view generated by jsdifflib