1
A set of small bugfixes for arm for 3.0; the "migration was
1
Hi; here's the latest arm pullreq...
2
broken" fixes for SMMUv3 and v7M NVIC with security extensions
3
are the most significant.
4
2
5
thanks
6
-- PMM
3
-- PMM
7
4
8
The following changes since commit 6d9dd5fb9d0e9f4a174f53a0e20a39fbe809c71e:
5
The following changes since commit 03a3a62fbd0aa5227e978eef3c67d3978aec9e5f:
9
6
10
Merge remote-tracking branch 'remotes/armbru/tags/pull-qobject-2018-07-27-v2' into staging (2018-07-30 09:55:47 +0100)
7
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2023-09-07 10:29:06 -0400)
11
8
12
are available in the Git repository at:
9
are available in the Git repository at:
13
10
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180730
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230908
15
12
16
for you to fetch changes up to 0261fb805c00a6f97d143235e7b06b0906bdf898:
13
for you to fetch changes up to c8f2eb5d414b788420b938f2ffdde891aa6c3ae8:
17
14
18
target/arm: Remove duplicate 'host' entry in '-cpu ?' output (2018-07-30 15:07:08 +0100)
15
arm/kvm: Enable support for KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE (2023-09-08 16:41:36 +0100)
19
16
20
----------------------------------------------------------------
17
----------------------------------------------------------------
21
target-arm queue:
18
target-arm queue:
22
* arm/smmuv3: Fix broken VM state migration
19
* New CPU type: cortex-a710
23
* armv7m_nvic: Fix broken VM state migration
20
* Implement new architectural features:
24
* hw/arm/sysbus-fdt: Fix assertion in copy_properties_from_host()
21
- FEAT_PACQARMA3
25
* hw/arm/iotkit: Fix IRQ number for timer1
22
- FEAT_EPAC
26
* hw/misc/tz-mpc: Zero the LUT on initialization, not just reset
23
- FEAT_Pauth2
27
* target/arm: Remove duplicate 'host' entry in '-cpu ?' output
24
- FEAT_FPAC
25
- FEAT_FPACCOMBINE
26
- FEAT_TIDCP1
27
* Xilinx Versal: Model the CFU/CFI
28
* Implement RMR_ELx registers
29
* Implement handling of HCR_EL2.TIDCP trap bit
30
* arm/kvm: Enable support for KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE
31
* hw/intc/arm_gicv3_its: Avoid maybe-uninitialized error in get_vte()
32
* target/arm: Do not use gen_mte_checkN in trans_STGP
33
* arm64: Restore trapless ptimer access
28
34
29
----------------------------------------------------------------
35
----------------------------------------------------------------
30
Dr. David Alan Gilbert (1):
36
Aaron Lindsay (6):
31
arm/smmuv3: Fix missing VMSD terminator
37
target/arm: Add ID_AA64ISAR2_EL1
38
target/arm: Add feature detection for FEAT_Pauth2 and extensions
39
target/arm: Implement FEAT_EPAC
40
target/arm: Implement FEAT_Pauth2
41
target/arm: Inform helpers whether a PAC instruction is 'combined'
42
target/arm: Implement FEAT_FPAC and FEAT_FPACCOMBINE
32
43
33
Geert Uytterhoeven (1):
44
Colton Lewis (1):
34
hw/arm/sysbus-fdt: Fix assertion in copy_properties_from_host()
45
arm64: Restore trapless ptimer access
35
46
36
Peter Maydell (3):
47
Francisco Iglesias (8):
37
armv7m_nvic: Fix m-security subsection name
48
hw/misc: Introduce the Xilinx CFI interface
38
hw/arm/iotkit: Fix IRQ number for timer1
49
hw/misc: Introduce a model of Xilinx Versal's CFU_APB
39
hw/misc/tz-mpc: Zero the LUT on initialization, not just reset
50
hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO
51
hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR
52
hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG
53
hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG
54
hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR
55
hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG
40
56
41
Philippe Mathieu-Daudé (1):
57
Philippe Mathieu-Daudé (1):
42
target/arm: Remove duplicate 'host' entry in '-cpu ?' output
58
hw/intc/arm_gicv3_its: Avoid maybe-uninitialized error in get_vte()
43
59
44
hw/arm/iotkit.c | 2 +-
60
Richard Henderson (9):
45
hw/arm/smmuv3.c | 1 +
61
tests/tcg/aarch64: Adjust pauth tests for FEAT_FPAC
46
hw/arm/sysbus-fdt.c | 1 +
62
target/arm: Don't change pauth features when changing algorithm
47
hw/intc/armv7m_nvic.c | 2 +-
63
target/arm: Implement FEAT_PACQARMA3
48
hw/misc/tz-mpc.c | 2 +-
64
target/arm: Do not use gen_mte_checkN in trans_STGP
49
target/arm/helper.c | 6 ------
65
target/arm: Implement RMR_ELx
50
6 files changed, 5 insertions(+), 9 deletions(-)
66
target/arm: Implement cortex-a710
67
target/arm: Implement HCR_EL2.TIDCP
68
target/arm: Implement FEAT_TIDCP1
69
target/arm: Enable SCTLR_EL1.TIDCP for user-only
51
70
71
Shameer Kolothum (1):
72
arm/kvm: Enable support for KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE
73
74
MAINTAINERS | 10 +
75
docs/system/arm/cpu-features.rst | 21 +-
76
docs/system/arm/emulation.rst | 8 +
77
docs/system/arm/virt.rst | 1 +
78
include/hw/arm/xlnx-versal.h | 85 +++
79
include/hw/misc/xlnx-cfi-if.h | 59 +++
80
include/hw/misc/xlnx-versal-cframe-reg.h | 303 +++++++++++
81
include/hw/misc/xlnx-versal-cfu.h | 258 ++++++++++
82
include/sysemu/kvm_int.h | 1 +
83
target/arm/cpu.h | 54 +-
84
target/arm/helper.h | 2 +
85
target/arm/syndrome.h | 7 +
86
target/arm/tcg/helper-a64.h | 4 +
87
tests/tcg/aarch64/pauth.h | 23 +
88
accel/kvm/kvm-all.c | 1 +
89
hw/arm/virt.c | 1 +
90
hw/arm/xlnx-versal.c | 155 +++++-
91
hw/intc/arm_gicv3_its.c | 15 +-
92
hw/misc/xlnx-cfi-if.c | 34 ++
93
hw/misc/xlnx-versal-cframe-reg.c | 858 +++++++++++++++++++++++++++++++
94
hw/misc/xlnx-versal-cfu.c | 563 ++++++++++++++++++++
95
target/arm/arm-qmp-cmds.c | 2 +-
96
target/arm/cpu.c | 4 +
97
target/arm/cpu64.c | 86 +++-
98
target/arm/helper.c | 68 ++-
99
target/arm/hvf/hvf.c | 1 +
100
target/arm/kvm.c | 61 +++
101
target/arm/kvm64.c | 3 +
102
target/arm/tcg/cpu64.c | 215 ++++++++
103
target/arm/tcg/op_helper.c | 33 ++
104
target/arm/tcg/pauth_helper.c | 180 +++++--
105
target/arm/tcg/translate-a64.c | 74 +--
106
target/arm/tcg/translate.c | 33 ++
107
tests/qtest/arm-cpu-features.c | 12 +-
108
tests/tcg/aarch64/pauth-2.c | 54 +-
109
tests/tcg/aarch64/pauth-4.c | 18 +-
110
tests/tcg/aarch64/pauth-5.c | 10 +
111
hw/misc/meson.build | 3 +
112
qemu-options.hx | 15 +
113
tests/tcg/aarch64/Makefile.target | 6 +-
114
40 files changed, 3184 insertions(+), 157 deletions(-)
115
create mode 100644 include/hw/misc/xlnx-cfi-if.h
116
create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h
117
create mode 100644 include/hw/misc/xlnx-versal-cfu.h
118
create mode 100644 tests/tcg/aarch64/pauth.h
119
create mode 100644 hw/misc/xlnx-cfi-if.c
120
create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
121
create mode 100644 hw/misc/xlnx-versal-cfu.c
122
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
With FEAT_FPAC, AUT* instructions that fail authentication
4
do not produce an error value but instead fault.
5
6
For pauth-2, install a signal handler and verify it gets called.
7
8
For pauth-4 and pauth-5, we are explicitly testing the error value,
9
so there's nothing to test with FEAT_FPAC, so exit early.
10
Adjust the makefile to use -cpu neoverse-v1, which has FEAT_EPAC
11
but not FEAT_FPAC.
12
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20230829232335.965414-2-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
tests/tcg/aarch64/pauth.h | 23 +++++++++++++
19
tests/tcg/aarch64/pauth-2.c | 54 ++++++++++++++++++++++++++-----
20
tests/tcg/aarch64/pauth-4.c | 18 ++++++++---
21
tests/tcg/aarch64/pauth-5.c | 10 ++++++
22
tests/tcg/aarch64/Makefile.target | 6 +++-
23
5 files changed, 98 insertions(+), 13 deletions(-)
24
create mode 100644 tests/tcg/aarch64/pauth.h
25
26
diff --git a/tests/tcg/aarch64/pauth.h b/tests/tcg/aarch64/pauth.h
27
new file mode 100644
28
index XXXXXXX..XXXXXXX
29
--- /dev/null
30
+++ b/tests/tcg/aarch64/pauth.h
31
@@ -XXX,XX +XXX,XX @@
32
+/*
33
+ * Helper for pauth test case
34
+ *
35
+ * Copyright (c) 2023 Linaro Ltd
36
+ * SPDX-License-Identifier: GPL-2.0-or-later
37
+ */
38
+
39
+#include <assert.h>
40
+#include <sys/auxv.h>
41
+
42
+static int get_pac_feature(void)
43
+{
44
+ unsigned long isar1, isar2;
45
+
46
+ assert(getauxval(AT_HWCAP) & HWCAP_CPUID);
47
+
48
+ asm("mrs %0, id_aa64isar1_el1" : "=r"(isar1));
49
+ asm("mrs %0, S3_0_C0_C6_2" : "=r"(isar2)); /* id_aa64isar2_el1 */
50
+
51
+ return ((isar1 >> 4) & 0xf) /* APA */
52
+ | ((isar1 >> 8) & 0xf) /* API */
53
+ | ((isar2 >> 12) & 0xf); /* APA3 */
54
+}
55
diff --git a/tests/tcg/aarch64/pauth-2.c b/tests/tcg/aarch64/pauth-2.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/tests/tcg/aarch64/pauth-2.c
58
+++ b/tests/tcg/aarch64/pauth-2.c
59
@@ -XXX,XX +XXX,XX @@
60
#include <stdint.h>
61
+#include <signal.h>
62
+#include <stdlib.h>
63
#include <assert.h>
64
+#include "pauth.h"
65
+
66
+
67
+static void sigill(int sig, siginfo_t *info, void *vuc)
68
+{
69
+ ucontext_t *uc = vuc;
70
+ uint64_t test;
71
+
72
+ /* There is only one insn below that is allowed to fault. */
73
+ asm volatile("adr %0, auth2_insn" : "=r"(test));
74
+ assert(test == uc->uc_mcontext.pc);
75
+ exit(0);
76
+}
77
+
78
+static int pac_feature;
79
80
void do_test(uint64_t value)
81
{
82
@@ -XXX,XX +XXX,XX @@ void do_test(uint64_t value)
83
* An invalid salt usually fails authorization, but again there
84
* is a chance of choosing another salt that works.
85
* Iterate until we find another salt which does fail.
86
+ *
87
+ * With FEAT_FPAC, this will SIGILL instead of producing a result.
88
*/
89
for (salt2 = salt1 + 1; ; salt2++) {
90
- asm volatile("autda %0, %2" : "=r"(decode) : "0"(encode), "r"(salt2));
91
+ asm volatile("auth2_insn: autda %0, %2"
92
+ : "=r"(decode) : "0"(encode), "r"(salt2));
93
if (decode != value) {
94
break;
95
}
96
}
97
98
+ assert(pac_feature < 4); /* No FEAT_FPAC */
99
+
100
/* The VA bits, bit 55, and the TBI bits, should be unchanged. */
101
assert(((decode ^ value) & 0xff80ffffffffffffull) == 0);
102
103
/*
104
- * Bits [54:53] are an error indicator based on the key used;
105
- * the DA key above is keynumber 0, so error == 0b01. Otherwise
106
- * bit 55 of the original is sign-extended into the rest of the auth.
107
+ * Without FEAT_Pauth2, bits [54:53] are an error indicator based on
108
+ * the key used; the DA key above is keynumber 0, so error == 0b01.
109
+ * Otherwise, bit 55 of the original is sign-extended into the rest
110
+ * of the auth.
111
*/
112
- if ((value >> 55) & 1) {
113
- assert(((decode >> 48) & 0xff) == 0b10111111);
114
- } else {
115
- assert(((decode >> 48) & 0xff) == 0b00100000);
116
+ if (pac_feature < 3) {
117
+ if ((value >> 55) & 1) {
118
+ assert(((decode >> 48) & 0xff) == 0b10111111);
119
+ } else {
120
+ assert(((decode >> 48) & 0xff) == 0b00100000);
121
+ }
122
}
123
}
124
125
int main()
126
{
127
+ static const struct sigaction sa = {
128
+ .sa_sigaction = sigill,
129
+ .sa_flags = SA_SIGINFO
130
+ };
131
+
132
+ pac_feature = get_pac_feature();
133
+ assert(pac_feature != 0);
134
+
135
+ if (pac_feature >= 4) {
136
+ /* FEAT_FPAC */
137
+ sigaction(SIGILL, &sa, NULL);
138
+ }
139
+
140
do_test(0);
141
do_test(0xda004acedeadbeefull);
142
return 0;
143
diff --git a/tests/tcg/aarch64/pauth-4.c b/tests/tcg/aarch64/pauth-4.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/tests/tcg/aarch64/pauth-4.c
146
+++ b/tests/tcg/aarch64/pauth-4.c
147
@@ -XXX,XX +XXX,XX @@
148
#include <assert.h>
149
#include <stdio.h>
150
#include <stdlib.h>
151
+#include "pauth.h"
152
153
#define TESTS 1000
154
155
int main()
156
{
157
+ char base[TESTS];
158
int i, count = 0;
159
float perc;
160
- void *base = malloc(TESTS);
161
+ int pac_feature = get_pac_feature();
162
+
163
+ /*
164
+ * Exit if no PAuth or FEAT_FPAC, which will SIGILL on AUTIA failure
165
+ * rather than return an error for us to check below.
166
+ */
167
+ if (pac_feature == 0 || pac_feature >= 4) {
168
+ return 0;
169
+ }
170
171
for (i = 0; i < TESTS; i++) {
172
uintptr_t in, x, y;
173
@@ -XXX,XX +XXX,XX @@ int main()
174
in = i + (uintptr_t) base;
175
176
asm("mov %0, %[in]\n\t"
177
- "pacia %0, sp\n\t" /* sigill if pauth not supported */
178
+ "pacia %0, sp\n\t"
179
"eor %0, %0, #4\n\t" /* corrupt single bit */
180
"mov %1, %0\n\t"
181
"autia %1, sp\n\t" /* validate corrupted pointer */
182
@@ -XXX,XX +XXX,XX @@ int main()
183
if (x != y) {
184
count++;
185
}
186
-
187
}
188
+
189
perc = (float) count / (float) TESTS;
190
- printf("Checks Passed: %0.2f%%", perc * 100.0);
191
+ printf("Checks Passed: %0.2f%%\n", perc * 100.0);
192
assert(perc > 0.95);
193
return 0;
194
}
195
diff --git a/tests/tcg/aarch64/pauth-5.c b/tests/tcg/aarch64/pauth-5.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/tests/tcg/aarch64/pauth-5.c
198
+++ b/tests/tcg/aarch64/pauth-5.c
199
@@ -XXX,XX +XXX,XX @@
200
#include <assert.h>
201
+#include "pauth.h"
202
203
static int x;
204
205
@@ -XXX,XX +XXX,XX @@ int main()
206
{
207
int *p0 = &x, *p1, *p2, *p3;
208
unsigned long salt = 0;
209
+ int pac_feature = get_pac_feature();
210
+
211
+ /*
212
+ * Exit if no PAuth or FEAT_FPAC, which will SIGILL on AUTDA failure
213
+ * rather than return an error for us to check below.
214
+ */
215
+ if (pac_feature == 0 || pac_feature >= 4) {
216
+ return 0;
217
+ }
218
219
/*
220
* With TBI enabled and a 48-bit VA, there are 7 bits of auth, and so
221
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
222
index XXXXXXX..XXXXXXX 100644
223
--- a/tests/tcg/aarch64/Makefile.target
224
+++ b/tests/tcg/aarch64/Makefile.target
225
@@ -XXX,XX +XXX,XX @@ endif
226
ifneq ($(CROSS_CC_HAS_ARMV8_3),)
227
AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5
228
pauth-%: CFLAGS += -march=armv8.3-a
229
-run-pauth-%: QEMU_OPTS += -cpu max
230
+run-pauth-1: QEMU_OPTS += -cpu max
231
+run-pauth-2: QEMU_OPTS += -cpu max
232
+# Choose a cpu with FEAT_Pauth but without FEAT_FPAC for pauth-[45].
233
+run-pauth-4: QEMU_OPTS += -cpu neoverse-v1
234
+run-pauth-5: QEMU_OPTS += -cpu neoverse-v1
235
endif
236
237
# BTI Tests
238
--
239
2.34.1
diff view generated by jsdifflib
1
A cut-and-paste error meant we were incorrectly wiring up the timer1
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
IRQ to IRQ3. IRQ3 is the interrupt for timer0 -- move timer0 to
3
IRQ4 where it belongs.
4
2
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180727113854.20283-3-peter.maydell@linaro.org
8
Message-id: 20230829232335.965414-3-richard.henderson@linaro.org
9
[PMM: drop the HVF part of the patch and just comment that
10
we need to do something when the register appears in that API]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
14
---
9
hw/arm/iotkit.c | 2 +-
15
target/arm/cpu.h | 1 +
10
1 file changed, 1 insertion(+), 1 deletion(-)
16
target/arm/helper.c | 4 ++--
17
target/arm/hvf/hvf.c | 1 +
18
target/arm/kvm64.c | 2 ++
19
4 files changed, 6 insertions(+), 2 deletions(-)
11
20
12
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/iotkit.c
23
--- a/target/arm/cpu.h
15
+++ b/hw/arm/iotkit.c
24
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
25
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
17
return;
26
uint32_t dbgdevid1;
18
}
27
uint64_t id_aa64isar0;
19
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
28
uint64_t id_aa64isar1;
20
- qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
29
+ uint64_t id_aa64isar2;
21
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 4));
30
uint64_t id_aa64pfr0;
22
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
31
uint64_t id_aa64pfr1;
23
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
32
uint64_t id_aa64mmfr0;
24
if (err) {
33
diff --git a/target/arm/helper.c b/target/arm/helper.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/helper.c
36
+++ b/target/arm/helper.c
37
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
38
.access = PL1_R, .type = ARM_CP_CONST,
39
.accessfn = access_aa64_tid3,
40
.resetvalue = cpu->isar.id_aa64isar1 },
41
- { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
42
+ { .name = "ID_AA64ISAR2_EL1", .state = ARM_CP_STATE_AA64,
43
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,
44
.access = PL1_R, .type = ARM_CP_CONST,
45
.accessfn = access_aa64_tid3,
46
- .resetvalue = 0 },
47
+ .resetvalue = cpu->isar.id_aa64isar2 },
48
{ .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
49
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3,
50
.access = PL1_R, .type = ARM_CP_CONST,
51
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/hvf/hvf.c
54
+++ b/target/arm/hvf/hvf.c
55
@@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
56
{ HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 },
57
{ HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 },
58
{ HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 },
59
+ /* Add ID_AA64ISAR2_EL1 here when HVF supports it */
60
{ HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 },
61
{ HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 },
62
{ HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 },
63
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/kvm64.c
66
+++ b/target/arm/kvm64.c
67
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
68
ARM64_SYS_REG(3, 0, 0, 6, 0));
69
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1,
70
ARM64_SYS_REG(3, 0, 0, 6, 1));
71
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2,
72
+ ARM64_SYS_REG(3, 0, 0, 6, 2));
73
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0,
74
ARM64_SYS_REG(3, 0, 0, 7, 0));
75
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
25
--
76
--
26
2.17.1
77
2.34.1
27
78
28
79
diff view generated by jsdifflib
New patch
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
1
2
3
Rename isar_feature_aa64_pauth_arch to isar_feature_aa64_pauth_qarma5
4
to distinguish the other architectural algorithm qarma3.
5
6
Add ARMPauthFeature and isar_feature_pauth_feature to cover the
7
other pauth conditions.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20230829232335.965414-4-richard.henderson@linaro.org
13
Message-Id: <20230609172324.982888-3-aaron@os.amperecomputing.com>
14
[rth: Add ARMPauthFeature and eliminate most other predicates]
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/cpu.h | 47 +++++++++++++++++++++++++++++------
19
target/arm/tcg/pauth_helper.c | 2 +-
20
2 files changed, 40 insertions(+), 9 deletions(-)
21
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
25
+++ b/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
27
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
28
}
29
30
+/*
31
+ * These are the values from APA/API/APA3.
32
+ * In general these must be compared '>=', per the normal Arm ARM
33
+ * treatment of fields in ID registers.
34
+ */
35
+typedef enum {
36
+ PauthFeat_None = 0,
37
+ PauthFeat_1 = 1,
38
+ PauthFeat_EPAC = 2,
39
+ PauthFeat_2 = 3,
40
+ PauthFeat_FPAC = 4,
41
+ PauthFeat_FPACCOMBINED = 5,
42
+} ARMPauthFeature;
43
+
44
+static inline ARMPauthFeature
45
+isar_feature_pauth_feature(const ARMISARegisters *id)
46
+{
47
+ /*
48
+ * Architecturally, only one of {APA,API,APA3} may be active (non-zero)
49
+ * and the other two must be zero. Thus we may avoid conditionals.
50
+ */
51
+ return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) |
52
+ FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, API) |
53
+ FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3));
54
+}
55
+
56
static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
57
{
58
/*
59
* Return true if any form of pauth is enabled, as this
60
* predicate controls migration of the 128-bit keys.
61
*/
62
- return (id->id_aa64isar1 &
63
- (FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) |
64
- FIELD_DP64(0, ID_AA64ISAR1, API, 0xf) |
65
- FIELD_DP64(0, ID_AA64ISAR1, GPA, 0xf) |
66
- FIELD_DP64(0, ID_AA64ISAR1, GPI, 0xf))) != 0;
67
+ return isar_feature_pauth_feature(id) != PauthFeat_None;
68
}
69
70
-static inline bool isar_feature_aa64_pauth_arch(const ARMISARegisters *id)
71
+static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id)
72
{
73
/*
74
- * Return true if pauth is enabled with the architected QARMA algorithm.
75
- * QEMU will always set APA+GPA to the same value.
76
+ * Return true if pauth is enabled with the architected QARMA5 algorithm.
77
+ * QEMU will always enable or disable both APA and GPA.
78
*/
79
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0;
80
}
81
82
+static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id)
83
+{
84
+ /*
85
+ * Return true if pauth is enabled with the architected QARMA3 algorithm.
86
+ * QEMU will always enable or disable both APA3 and GPA3.
87
+ */
88
+ return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0;
89
+}
90
+
91
static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id)
92
{
93
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2;
94
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/tcg/pauth_helper.c
97
+++ b/target/arm/tcg/pauth_helper.c
98
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_computepac_impdef(uint64_t data, uint64_t modifier,
99
static uint64_t pauth_computepac(CPUARMState *env, uint64_t data,
100
uint64_t modifier, ARMPACKey key)
101
{
102
- if (cpu_isar_feature(aa64_pauth_arch, env_archcpu(env))) {
103
+ if (cpu_isar_feature(aa64_pauth_qarma5, env_archcpu(env))) {
104
return pauth_computepac_architected(data, modifier, key);
105
} else {
106
return pauth_computepac_impdef(data, modifier, key);
107
--
108
2.34.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
We have cpu properties to adjust the pauth algorithm for the
4
purpose of speed of emulation. Retain the set of pauth features
5
supported by the cpu even as the algorithm changes.
6
7
This already affects the neoverse-v1 cpu, which has FEAT_EPAC.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20230829232335.965414-5-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/cpu64.c | 70 +++++++++++++++++++++++++++---------------
15
target/arm/tcg/cpu64.c | 2 ++
16
2 files changed, 47 insertions(+), 25 deletions(-)
17
18
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu64.c
21
+++ b/target/arm/cpu64.c
22
@@ -XXX,XX +XXX,XX @@ void aarch64_add_sme_properties(Object *obj)
23
24
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
25
{
26
- int arch_val = 0, impdef_val = 0;
27
- uint64_t t;
28
+ ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu);
29
+ uint64_t isar1;
30
31
- /* Exit early if PAuth is enabled, and fall through to disable it */
32
- if ((kvm_enabled() || hvf_enabled()) && cpu->prop_pauth) {
33
- if (!cpu_isar_feature(aa64_pauth, cpu)) {
34
- error_setg(errp, "'pauth' feature not supported by %s on this host",
35
- kvm_enabled() ? "KVM" : "hvf");
36
+ /*
37
+ * These properties enable or disable Pauth as a whole, or change
38
+ * the pauth algorithm, but do not change the set of features that
39
+ * are present. We have saved a copy of those features above and
40
+ * will now place it into the field that chooses the algorithm.
41
+ *
42
+ * Begin by disabling all fields.
43
+ */
44
+ isar1 = cpu->isar.id_aa64isar1;
45
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, 0);
46
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 0);
47
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, 0);
48
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 0);
49
+
50
+ if (kvm_enabled() || hvf_enabled()) {
51
+ /*
52
+ * Exit early if PAuth is enabled and fall through to disable it.
53
+ * The algorithm selection properties are not present.
54
+ */
55
+ if (cpu->prop_pauth) {
56
+ if (features == 0) {
57
+ error_setg(errp, "'pauth' feature not supported by "
58
+ "%s on this host", current_accel_name());
59
+ }
60
+ return;
61
+ }
62
+ } else {
63
+ /* Pauth properties are only present when the model supports it. */
64
+ if (features == 0) {
65
+ assert(!cpu->prop_pauth);
66
+ return;
67
}
68
69
- return;
70
- }
71
-
72
- /* TODO: Handle HaveEnhancedPAC, HaveEnhancedPAC2, HaveFPAC. */
73
- if (cpu->prop_pauth) {
74
- if (cpu->prop_pauth_impdef) {
75
- impdef_val = 1;
76
- } else {
77
- arch_val = 1;
78
+ if (cpu->prop_pauth) {
79
+ if (cpu->prop_pauth_impdef) {
80
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, features);
81
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 1);
82
+ } else {
83
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features);
84
+ isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1);
85
+ }
86
+ } else if (cpu->prop_pauth_impdef) {
87
+ error_setg(errp, "cannot enable pauth-impdef without pauth");
88
+ error_append_hint(errp, "Add pauth=on to the CPU property list.\n");
89
}
90
- } else if (cpu->prop_pauth_impdef) {
91
- error_setg(errp, "cannot enable pauth-impdef without pauth");
92
- error_append_hint(errp, "Add pauth=on to the CPU property list.\n");
93
}
94
95
- t = cpu->isar.id_aa64isar1;
96
- t = FIELD_DP64(t, ID_AA64ISAR1, APA, arch_val);
97
- t = FIELD_DP64(t, ID_AA64ISAR1, GPA, arch_val);
98
- t = FIELD_DP64(t, ID_AA64ISAR1, API, impdef_val);
99
- t = FIELD_DP64(t, ID_AA64ISAR1, GPI, impdef_val);
100
- cpu->isar.id_aa64isar1 = t;
101
+ cpu->isar.id_aa64isar1 = isar1;
102
}
103
104
static Property arm_cpu_pauth_property =
105
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/tcg/cpu64.c
108
+++ b/target/arm/tcg/cpu64.c
109
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
110
111
t = cpu->isar.id_aa64isar1;
112
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */
113
+ t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_1);
114
+ t = FIELD_DP64(t, ID_AA64ISAR1, API, 1);
115
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); /* FEAT_JSCVT */
116
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); /* FEAT_FCMA */
117
t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* FEAT_LRCPC2 */
118
--
119
2.34.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Implement the QARMA3 cryptographic algorithm for PAC calculation.
4
Implement a cpu feature to select the algorithm and document it.
5
6
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20230829232335.965414-6-richard.henderson@linaro.org
11
Message-Id: <20230609172324.982888-4-aaron@os.amperecomputing.com>
12
[rth: Merge cpu feature addition from another patch.]
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
docs/system/arm/cpu-features.rst | 21 ++++++++-----
17
docs/system/arm/emulation.rst | 3 ++
18
target/arm/cpu.h | 1 +
19
target/arm/arm-qmp-cmds.c | 2 +-
20
target/arm/cpu64.c | 24 ++++++++++++--
21
target/arm/tcg/pauth_helper.c | 54 ++++++++++++++++++++++++++------
22
tests/qtest/arm-cpu-features.c | 12 ++++++-
23
7 files changed, 94 insertions(+), 23 deletions(-)
24
25
diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
26
index XXXXXXX..XXXXXXX 100644
27
--- a/docs/system/arm/cpu-features.rst
28
+++ b/docs/system/arm/cpu-features.rst
29
@@ -XXX,XX +XXX,XX @@ TCG VCPU Features
30
TCG VCPU features are CPU features that are specific to TCG.
31
Below is the list of TCG VCPU features and their descriptions.
32
33
-``pauth-impdef``
34
- When ``FEAT_Pauth`` is enabled, either the *impdef* (Implementation
35
- Defined) algorithm is enabled or the *architected* QARMA algorithm
36
- is enabled. By default the impdef algorithm is disabled, and QARMA
37
- is enabled.
38
+``pauth``
39
+ Enable or disable ``FEAT_Pauth`` entirely.
40
41
- The architected QARMA algorithm has good cryptographic properties,
42
- but can be quite slow to emulate. The impdef algorithm used by QEMU
43
- is non-cryptographic but significantly faster.
44
+``pauth-impdef``
45
+ When ``pauth`` is enabled, select the QEMU implementation defined algorithm.
46
+
47
+``pauth-qarma3``
48
+ When ``pauth`` is enabled, select the architected QARMA3 algorithm.
49
+
50
+Without either ``pauth-impdef`` or ``pauth-qarma3`` enabled,
51
+the architected QARMA5 algorithm is used. The architected QARMA5
52
+and QARMA3 algorithms have good cryptographic properties, but can
53
+be quite slow to emulate. The impdef algorithm used by QEMU is
54
+non-cryptographic but significantly faster.
55
56
SVE CPU Properties
57
==================
58
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
59
index XXXXXXX..XXXXXXX 100644
60
--- a/docs/system/arm/emulation.rst
61
+++ b/docs/system/arm/emulation.rst
62
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
63
- FEAT_MTE (Memory Tagging Extension)
64
- FEAT_MTE2 (Memory Tagging Extension)
65
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
66
+- FEAT_PACIMP (Pointer authentication - IMPLEMENTATION DEFINED algorithm)
67
+- FEAT_PACQARMA3 (Pointer authentication - QARMA3 algorithm)
68
+- FEAT_PACQARMA5 (Pointer authentication - QARMA5 algorithm)
69
- FEAT_PAN (Privileged access never)
70
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
71
- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
72
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
73
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/cpu.h
75
+++ b/target/arm/cpu.h
76
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
77
*/
78
bool prop_pauth;
79
bool prop_pauth_impdef;
80
+ bool prop_pauth_qarma3;
81
bool prop_lpa2;
82
83
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
84
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/arm-qmp-cmds.c
87
+++ b/target/arm/arm-qmp-cmds.c
88
@@ -XXX,XX +XXX,XX @@ static const char *cpu_model_advertised_features[] = {
89
"sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
90
"sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
91
"kvm-no-adjvtime", "kvm-steal-time",
92
- "pauth", "pauth-impdef",
93
+ "pauth", "pauth-impdef", "pauth-qarma3",
94
NULL
95
};
96
97
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/target/arm/cpu64.c
100
+++ b/target/arm/cpu64.c
101
@@ -XXX,XX +XXX,XX @@ void aarch64_add_sme_properties(Object *obj)
102
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
103
{
104
ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu);
105
- uint64_t isar1;
106
+ uint64_t isar1, isar2;
107
108
/*
109
* These properties enable or disable Pauth as a whole, or change
110
@@ -XXX,XX +XXX,XX @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
111
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, 0);
112
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 0);
113
114
+ isar2 = cpu->isar.id_aa64isar2;
115
+ isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, 0);
116
+ isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 0);
117
+
118
if (kvm_enabled() || hvf_enabled()) {
119
/*
120
* Exit early if PAuth is enabled and fall through to disable it.
121
@@ -XXX,XX +XXX,XX @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
122
}
123
124
if (cpu->prop_pauth) {
125
+ if (cpu->prop_pauth_impdef && cpu->prop_pauth_qarma3) {
126
+ error_setg(errp,
127
+ "cannot enable both pauth-impdef and pauth-qarma3");
128
+ return;
129
+ }
130
+
131
if (cpu->prop_pauth_impdef) {
132
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, features);
133
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 1);
134
+ } else if (cpu->prop_pauth_qarma3) {
135
+ isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, features);
136
+ isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 1);
137
} else {
138
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features);
139
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1);
140
}
141
- } else if (cpu->prop_pauth_impdef) {
142
- error_setg(errp, "cannot enable pauth-impdef without pauth");
143
+ } else if (cpu->prop_pauth_impdef || cpu->prop_pauth_qarma3) {
144
+ error_setg(errp, "cannot enable pauth-impdef or "
145
+ "pauth-qarma3 without pauth");
146
error_append_hint(errp, "Add pauth=on to the CPU property list.\n");
147
}
148
}
149
150
cpu->isar.id_aa64isar1 = isar1;
151
+ cpu->isar.id_aa64isar2 = isar2;
152
}
153
154
static Property arm_cpu_pauth_property =
155
DEFINE_PROP_BOOL("pauth", ARMCPU, prop_pauth, true);
156
static Property arm_cpu_pauth_impdef_property =
157
DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false);
158
+static Property arm_cpu_pauth_qarma3_property =
159
+ DEFINE_PROP_BOOL("pauth-qarma3", ARMCPU, prop_pauth_qarma3, false);
160
161
void aarch64_add_pauth_properties(Object *obj)
162
{
163
@@ -XXX,XX +XXX,XX @@ void aarch64_add_pauth_properties(Object *obj)
164
cpu->prop_pauth = cpu_isar_feature(aa64_pauth, cpu);
165
} else {
166
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property);
167
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma3_property);
168
}
169
}
170
171
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/target/arm/tcg/pauth_helper.c
174
+++ b/target/arm/tcg/pauth_helper.c
175
@@ -XXX,XX +XXX,XX @@ static uint64_t pac_sub(uint64_t i)
176
return o;
177
}
178
179
+static uint64_t pac_sub1(uint64_t i)
180
+{
181
+ static const uint8_t sub1[16] = {
182
+ 0xa, 0xd, 0xe, 0x6, 0xf, 0x7, 0x3, 0x5,
183
+ 0x9, 0x8, 0x0, 0xc, 0xb, 0x1, 0x2, 0x4,
184
+ };
185
+ uint64_t o = 0;
186
+ int b;
187
+
188
+ for (b = 0; b < 64; b += 4) {
189
+ o |= (uint64_t)sub1[(i >> b) & 0xf] << b;
190
+ }
191
+ return o;
192
+}
193
+
194
static uint64_t pac_inv_sub(uint64_t i)
195
{
196
static const uint8_t inv_sub[16] = {
197
@@ -XXX,XX +XXX,XX @@ static uint64_t tweak_inv_shuffle(uint64_t i)
198
}
199
200
static uint64_t pauth_computepac_architected(uint64_t data, uint64_t modifier,
201
- ARMPACKey key)
202
+ ARMPACKey key, bool isqarma3)
203
{
204
static const uint64_t RC[5] = {
205
0x0000000000000000ull,
206
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_computepac_architected(uint64_t data, uint64_t modifier,
207
0x452821E638D01377ull,
208
};
209
const uint64_t alpha = 0xC0AC29B7C97C50DDull;
210
+ int iterations = isqarma3 ? 2 : 4;
211
/*
212
* Note that in the ARM pseudocode, key0 contains bits <127:64>
213
* and key1 contains bits <63:0> of the 128-bit key.
214
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_computepac_architected(uint64_t data, uint64_t modifier,
215
runningmod = modifier;
216
workingval = data ^ key0;
217
218
- for (i = 0; i <= 4; ++i) {
219
+ for (i = 0; i <= iterations; ++i) {
220
roundkey = key1 ^ runningmod;
221
workingval ^= roundkey;
222
workingval ^= RC[i];
223
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_computepac_architected(uint64_t data, uint64_t modifier,
224
workingval = pac_cell_shuffle(workingval);
225
workingval = pac_mult(workingval);
226
}
227
- workingval = pac_sub(workingval);
228
+ if (isqarma3) {
229
+ workingval = pac_sub1(workingval);
230
+ } else {
231
+ workingval = pac_sub(workingval);
232
+ }
233
runningmod = tweak_shuffle(runningmod);
234
}
235
roundkey = modk0 ^ runningmod;
236
workingval ^= roundkey;
237
workingval = pac_cell_shuffle(workingval);
238
workingval = pac_mult(workingval);
239
- workingval = pac_sub(workingval);
240
+ if (isqarma3) {
241
+ workingval = pac_sub1(workingval);
242
+ } else {
243
+ workingval = pac_sub(workingval);
244
+ }
245
workingval = pac_cell_shuffle(workingval);
246
workingval = pac_mult(workingval);
247
workingval ^= key1;
248
workingval = pac_cell_inv_shuffle(workingval);
249
- workingval = pac_inv_sub(workingval);
250
+ if (isqarma3) {
251
+ workingval = pac_sub1(workingval);
252
+ } else {
253
+ workingval = pac_inv_sub(workingval);
254
+ }
255
workingval = pac_mult(workingval);
256
workingval = pac_cell_inv_shuffle(workingval);
257
workingval ^= key0;
258
workingval ^= runningmod;
259
- for (i = 0; i <= 4; ++i) {
260
- workingval = pac_inv_sub(workingval);
261
- if (i < 4) {
262
+ for (i = 0; i <= iterations; ++i) {
263
+ if (isqarma3) {
264
+ workingval = pac_sub1(workingval);
265
+ } else {
266
+ workingval = pac_inv_sub(workingval);
267
+ }
268
+ if (i < iterations) {
269
workingval = pac_mult(workingval);
270
workingval = pac_cell_inv_shuffle(workingval);
271
}
272
runningmod = tweak_inv_shuffle(runningmod);
273
roundkey = key1 ^ runningmod;
274
- workingval ^= RC[4 - i];
275
+ workingval ^= RC[iterations - i];
276
workingval ^= roundkey;
277
workingval ^= alpha;
278
}
279
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_computepac(CPUARMState *env, uint64_t data,
280
uint64_t modifier, ARMPACKey key)
281
{
282
if (cpu_isar_feature(aa64_pauth_qarma5, env_archcpu(env))) {
283
- return pauth_computepac_architected(data, modifier, key);
284
+ return pauth_computepac_architected(data, modifier, key, false);
285
+ } else if (cpu_isar_feature(aa64_pauth_qarma3, env_archcpu(env))) {
286
+ return pauth_computepac_architected(data, modifier, key, true);
287
} else {
288
return pauth_computepac_impdef(data, modifier, key);
289
}
290
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
291
index XXXXXXX..XXXXXXX 100644
292
--- a/tests/qtest/arm-cpu-features.c
293
+++ b/tests/qtest/arm-cpu-features.c
294
@@ -XXX,XX +XXX,XX @@ static void pauth_tests_default(QTestState *qts, const char *cpu_type)
295
{
296
assert_has_feature_enabled(qts, cpu_type, "pauth");
297
assert_has_feature_disabled(qts, cpu_type, "pauth-impdef");
298
+ assert_has_feature_disabled(qts, cpu_type, "pauth-qarma3");
299
assert_set_feature(qts, cpu_type, "pauth", false);
300
assert_set_feature(qts, cpu_type, "pauth", true);
301
assert_set_feature(qts, cpu_type, "pauth-impdef", true);
302
assert_set_feature(qts, cpu_type, "pauth-impdef", false);
303
- assert_error(qts, cpu_type, "cannot enable pauth-impdef without pauth",
304
+ assert_set_feature(qts, cpu_type, "pauth-qarma3", true);
305
+ assert_set_feature(qts, cpu_type, "pauth-qarma3", false);
306
+ assert_error(qts, cpu_type,
307
+ "cannot enable pauth-impdef or pauth-qarma3 without pauth",
308
"{ 'pauth': false, 'pauth-impdef': true }");
309
+ assert_error(qts, cpu_type,
310
+ "cannot enable pauth-impdef or pauth-qarma3 without pauth",
311
+ "{ 'pauth': false, 'pauth-qarma3': true }");
312
+ assert_error(qts, cpu_type,
313
+ "cannot enable both pauth-impdef and pauth-qarma3",
314
+ "{ 'pauth': true, 'pauth-impdef': true, 'pauth-qarma3': true }");
315
}
316
317
static void test_query_cpu_model_expansion(const void *data)
318
--
319
2.34.1
diff view generated by jsdifflib
New patch
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
1
2
3
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230829232335.965414-7-richard.henderson@linaro.org
8
Message-Id: <20230609172324.982888-5-aaron@os.amperecomputing.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/system/arm/emulation.rst | 1 +
13
target/arm/tcg/cpu64.c | 2 +-
14
target/arm/tcg/pauth_helper.c | 16 +++++++++++-----
15
3 files changed, 13 insertions(+), 6 deletions(-)
16
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/arm/emulation.rst
20
+++ b/docs/system/arm/emulation.rst
21
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
22
- FEAT_DotProd (Advanced SIMD dot product instructions)
23
- FEAT_DoubleFault (Double Fault Extension)
24
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
25
+- FEAT_EPAC (Enhanced pointer authentication)
26
- FEAT_ETS (Enhanced Translation Synchronization)
27
- FEAT_EVT (Enhanced Virtualization Traps)
28
- FEAT_FCMA (Floating-point complex number instructions)
29
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/tcg/cpu64.c
32
+++ b/target/arm/tcg/cpu64.c
33
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
34
35
t = cpu->isar.id_aa64isar1;
36
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */
37
- t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_1);
38
+ t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_EPAC);
39
t = FIELD_DP64(t, ID_AA64ISAR1, API, 1);
40
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); /* FEAT_JSCVT */
41
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); /* FEAT_FCMA */
42
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/tcg/pauth_helper.c
45
+++ b/target/arm/tcg/pauth_helper.c
46
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_computepac(CPUARMState *env, uint64_t data,
47
static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
48
ARMPACKey *key, bool data)
49
{
50
+ ARMCPU *cpu = env_archcpu(env);
51
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
52
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
53
+ ARMPauthFeature pauth_feature = cpu_isar_feature(pauth_feature, cpu);
54
uint64_t pac, ext_ptr, ext, test;
55
int bot_bit, top_bit;
56
57
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
58
*/
59
test = sextract64(ptr, bot_bit, top_bit - bot_bit);
60
if (test != 0 && test != -1) {
61
- /*
62
- * Note that our top_bit is one greater than the pseudocode's
63
- * version, hence "- 2" here.
64
- */
65
- pac ^= MAKE_64BIT_MASK(top_bit - 2, 1);
66
+ if (pauth_feature == PauthFeat_EPAC) {
67
+ pac = 0;
68
+ } else {
69
+ /*
70
+ * Note that our top_bit is one greater than the pseudocode's
71
+ * version, hence "- 2" here.
72
+ */
73
+ pac ^= MAKE_64BIT_MASK(top_bit - 2, 1);
74
+ }
75
}
76
77
/*
78
--
79
2.34.1
diff view generated by jsdifflib
New patch
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
1
2
3
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230829232335.965414-8-richard.henderson@linaro.org
8
Message-Id: <20230609172324.982888-6-aaron@os.amperecomputing.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/system/arm/emulation.rst | 1 +
13
target/arm/tcg/cpu64.c | 2 +-
14
target/arm/tcg/pauth_helper.c | 21 +++++++++++++++++----
15
3 files changed, 19 insertions(+), 5 deletions(-)
16
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/arm/emulation.rst
20
+++ b/docs/system/arm/emulation.rst
21
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
22
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
23
- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
24
- FEAT_PAuth (Pointer authentication)
25
+- FEAT_PAuth2 (Enhacements to pointer authentication)
26
- FEAT_PMULL (PMULL, PMULL2 instructions)
27
- FEAT_PMUv3p1 (PMU Extensions v3.1)
28
- FEAT_PMUv3p4 (PMU Extensions v3.4)
29
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/tcg/cpu64.c
32
+++ b/target/arm/tcg/cpu64.c
33
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
34
35
t = cpu->isar.id_aa64isar1;
36
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */
37
- t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_EPAC);
38
+ t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_2);
39
t = FIELD_DP64(t, ID_AA64ISAR1, API, 1);
40
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); /* FEAT_JSCVT */
41
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); /* FEAT_FCMA */
42
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/tcg/pauth_helper.c
45
+++ b/target/arm/tcg/pauth_helper.c
46
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
47
*/
48
test = sextract64(ptr, bot_bit, top_bit - bot_bit);
49
if (test != 0 && test != -1) {
50
- if (pauth_feature == PauthFeat_EPAC) {
51
+ if (pauth_feature >= PauthFeat_2) {
52
+ /* No action required */
53
+ } else if (pauth_feature == PauthFeat_EPAC) {
54
pac = 0;
55
} else {
56
/*
57
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
58
* Preserve the determination between upper and lower at bit 55,
59
* and insert pointer authentication code.
60
*/
61
+ if (pauth_feature >= PauthFeat_2) {
62
+ pac ^= ptr;
63
+ }
64
if (param.tbi) {
65
ptr &= ~MAKE_64BIT_MASK(bot_bit, 55 - bot_bit + 1);
66
pac &= MAKE_64BIT_MASK(bot_bit, 54 - bot_bit + 1);
67
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param)
68
static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
69
ARMPACKey *key, bool data, int keynumber)
70
{
71
+ ARMCPU *cpu = env_archcpu(env);
72
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
73
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
74
+ ARMPauthFeature pauth_feature = cpu_isar_feature(pauth_feature, cpu);
75
int bot_bit, top_bit;
76
- uint64_t pac, orig_ptr, test;
77
+ uint64_t pac, orig_ptr, cmp_mask;
78
79
orig_ptr = pauth_original_ptr(ptr, param);
80
pac = pauth_computepac(env, orig_ptr, modifier, *key);
81
bot_bit = 64 - param.tsz;
82
top_bit = 64 - 8 * param.tbi;
83
84
- test = (pac ^ ptr) & ~MAKE_64BIT_MASK(55, 1);
85
- if (unlikely(extract64(test, bot_bit, top_bit - bot_bit))) {
86
+ cmp_mask = MAKE_64BIT_MASK(bot_bit, top_bit - bot_bit);
87
+ cmp_mask &= ~MAKE_64BIT_MASK(55, 1);
88
+
89
+ if (pauth_feature >= PauthFeat_2) {
90
+ return ptr ^ (pac & cmp_mask);
91
+ }
92
+
93
+ if ((pac ^ ptr) & cmp_mask) {
94
int error_code = (keynumber << 1) | (keynumber ^ 1);
95
if (param.tbi) {
96
return deposit64(orig_ptr, 53, 2, error_code);
97
--
98
2.34.1
diff view generated by jsdifflib
1
The vmstate save/load code insists that subsections of a VMState must
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
have names which include their parent VMState's name as a leading
3
substring. Unfortunately it neither documents this nor checks it on
4
device init or state save, but instead fails state load with a
5
confusing error message ("Missing section footer for armv7m_nvic").
6
2
7
Fix the name of the m-security subsection of the NVIC, so that
3
An instruction is a 'combined' Pointer Authentication instruction
8
state save/load works correctly for the security-enabled NVIC.
4
if it does something in addition to PAC -- for instance, branching
5
to or loading an address from the authenticated pointer.
9
6
7
Knowing whether a PAC operation is 'combined' is needed to
8
implement FEAT_FPACCOMBINE.
9
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20230829232335.965414-9-richard.henderson@linaro.org
15
Message-Id: <20230609172324.982888-7-aaron@os.amperecomputing.com>
16
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180727113854.20283-2-peter.maydell@linaro.org
13
---
18
---
14
hw/intc/armv7m_nvic.c | 2 +-
19
target/arm/tcg/helper-a64.h | 4 ++
15
1 file changed, 1 insertion(+), 1 deletion(-)
20
target/arm/tcg/pauth_helper.c | 71 +++++++++++++++++++++++++++-------
21
target/arm/tcg/translate-a64.c | 12 +++---
22
3 files changed, 68 insertions(+), 19 deletions(-)
16
23
17
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
24
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
18
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/armv7m_nvic.c
26
--- a/target/arm/tcg/helper-a64.h
20
+++ b/hw/intc/armv7m_nvic.c
27
+++ b/target/arm/tcg/helper-a64.h
21
@@ -XXX,XX +XXX,XX @@ static int nvic_security_post_load(void *opaque, int version_id)
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(pacda, TCG_CALL_NO_WG, i64, env, i64, i64)
29
DEF_HELPER_FLAGS_3(pacdb, TCG_CALL_NO_WG, i64, env, i64, i64)
30
DEF_HELPER_FLAGS_3(pacga, TCG_CALL_NO_WG, i64, env, i64, i64)
31
DEF_HELPER_FLAGS_3(autia, TCG_CALL_NO_WG, i64, env, i64, i64)
32
+DEF_HELPER_FLAGS_3(autia_combined, TCG_CALL_NO_WG, i64, env, i64, i64)
33
DEF_HELPER_FLAGS_3(autib, TCG_CALL_NO_WG, i64, env, i64, i64)
34
+DEF_HELPER_FLAGS_3(autib_combined, TCG_CALL_NO_WG, i64, env, i64, i64)
35
DEF_HELPER_FLAGS_3(autda, TCG_CALL_NO_WG, i64, env, i64, i64)
36
+DEF_HELPER_FLAGS_3(autda_combined, TCG_CALL_NO_WG, i64, env, i64, i64)
37
DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64)
38
+DEF_HELPER_FLAGS_3(autdb_combined, TCG_CALL_NO_WG, i64, env, i64, i64)
39
DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64)
40
DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64)
41
42
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/tcg/pauth_helper.c
45
+++ b/target/arm/tcg/pauth_helper.c
46
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param)
22
}
47
}
23
48
24
static const VMStateDescription vmstate_nvic_security = {
49
static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
25
- .name = "nvic/m-security",
50
- ARMPACKey *key, bool data, int keynumber)
26
+ .name = "armv7m_nvic/m-security",
51
+ ARMPACKey *key, bool data, int keynumber,
27
.version_id = 1,
52
+ uintptr_t ra, bool is_combined)
28
.minimum_version_id = 1,
53
{
29
.needed = nvic_security_needed,
54
ARMCPU *cpu = env_archcpu(env);
55
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
56
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(pacga)(CPUARMState *env, uint64_t x, uint64_t y)
57
return pac & 0xffffffff00000000ull;
58
}
59
60
-uint64_t HELPER(autia)(CPUARMState *env, uint64_t x, uint64_t y)
61
+static uint64_t pauth_autia(CPUARMState *env, uint64_t x, uint64_t y,
62
+ uintptr_t ra, bool is_combined)
63
{
64
int el = arm_current_el(env);
65
if (!pauth_key_enabled(env, el, SCTLR_EnIA)) {
66
return x;
67
}
68
- pauth_check_trap(env, el, GETPC());
69
- return pauth_auth(env, x, y, &env->keys.apia, false, 0);
70
+ pauth_check_trap(env, el, ra);
71
+ return pauth_auth(env, x, y, &env->keys.apia, false, 0, ra, is_combined);
72
}
73
74
-uint64_t HELPER(autib)(CPUARMState *env, uint64_t x, uint64_t y)
75
+uint64_t HELPER(autia)(CPUARMState *env, uint64_t x, uint64_t y)
76
+{
77
+ return pauth_autia(env, x, y, GETPC(), false);
78
+}
79
+
80
+uint64_t HELPER(autia_combined)(CPUARMState *env, uint64_t x, uint64_t y)
81
+{
82
+ return pauth_autia(env, x, y, GETPC(), true);
83
+}
84
+
85
+static uint64_t pauth_autib(CPUARMState *env, uint64_t x, uint64_t y,
86
+ uintptr_t ra, bool is_combined)
87
{
88
int el = arm_current_el(env);
89
if (!pauth_key_enabled(env, el, SCTLR_EnIB)) {
90
return x;
91
}
92
- pauth_check_trap(env, el, GETPC());
93
- return pauth_auth(env, x, y, &env->keys.apib, false, 1);
94
+ pauth_check_trap(env, el, ra);
95
+ return pauth_auth(env, x, y, &env->keys.apib, false, 1, ra, is_combined);
96
}
97
98
-uint64_t HELPER(autda)(CPUARMState *env, uint64_t x, uint64_t y)
99
+uint64_t HELPER(autib)(CPUARMState *env, uint64_t x, uint64_t y)
100
+{
101
+ return pauth_autib(env, x, y, GETPC(), false);
102
+}
103
+
104
+uint64_t HELPER(autib_combined)(CPUARMState *env, uint64_t x, uint64_t y)
105
+{
106
+ return pauth_autib(env, x, y, GETPC(), true);
107
+}
108
+
109
+static uint64_t pauth_autda(CPUARMState *env, uint64_t x, uint64_t y,
110
+ uintptr_t ra, bool is_combined)
111
{
112
int el = arm_current_el(env);
113
if (!pauth_key_enabled(env, el, SCTLR_EnDA)) {
114
return x;
115
}
116
- pauth_check_trap(env, el, GETPC());
117
- return pauth_auth(env, x, y, &env->keys.apda, true, 0);
118
+ pauth_check_trap(env, el, ra);
119
+ return pauth_auth(env, x, y, &env->keys.apda, true, 0, ra, is_combined);
120
}
121
122
-uint64_t HELPER(autdb)(CPUARMState *env, uint64_t x, uint64_t y)
123
+uint64_t HELPER(autda)(CPUARMState *env, uint64_t x, uint64_t y)
124
+{
125
+ return pauth_autda(env, x, y, GETPC(), false);
126
+}
127
+
128
+uint64_t HELPER(autda_combined)(CPUARMState *env, uint64_t x, uint64_t y)
129
+{
130
+ return pauth_autda(env, x, y, GETPC(), true);
131
+}
132
+
133
+static uint64_t pauth_autdb(CPUARMState *env, uint64_t x, uint64_t y,
134
+ uintptr_t ra, bool is_combined)
135
{
136
int el = arm_current_el(env);
137
if (!pauth_key_enabled(env, el, SCTLR_EnDB)) {
138
return x;
139
}
140
- pauth_check_trap(env, el, GETPC());
141
- return pauth_auth(env, x, y, &env->keys.apdb, true, 1);
142
+ pauth_check_trap(env, el, ra);
143
+ return pauth_auth(env, x, y, &env->keys.apdb, true, 1, ra, is_combined);
144
+}
145
+
146
+uint64_t HELPER(autdb)(CPUARMState *env, uint64_t x, uint64_t y)
147
+{
148
+ return pauth_autdb(env, x, y, GETPC(), false);
149
+}
150
+
151
+uint64_t HELPER(autdb_combined)(CPUARMState *env, uint64_t x, uint64_t y)
152
+{
153
+ return pauth_autdb(env, x, y, GETPC(), true);
154
}
155
156
uint64_t HELPER(xpaci)(CPUARMState *env, uint64_t a)
157
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
158
index XXXXXXX..XXXXXXX 100644
159
--- a/target/arm/tcg/translate-a64.c
160
+++ b/target/arm/tcg/translate-a64.c
161
@@ -XXX,XX +XXX,XX @@ static TCGv_i64 auth_branch_target(DisasContext *s, TCGv_i64 dst,
162
163
truedst = tcg_temp_new_i64();
164
if (use_key_a) {
165
- gen_helper_autia(truedst, cpu_env, dst, modifier);
166
+ gen_helper_autia_combined(truedst, cpu_env, dst, modifier);
167
} else {
168
- gen_helper_autib(truedst, cpu_env, dst, modifier);
169
+ gen_helper_autib_combined(truedst, cpu_env, dst, modifier);
170
}
171
return truedst;
172
}
173
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRA(DisasContext *s, arg_LDRA *a)
174
175
if (s->pauth_active) {
176
if (!a->m) {
177
- gen_helper_autda(dirty_addr, cpu_env, dirty_addr,
178
- tcg_constant_i64(0));
179
+ gen_helper_autda_combined(dirty_addr, cpu_env, dirty_addr,
180
+ tcg_constant_i64(0));
181
} else {
182
- gen_helper_autdb(dirty_addr, cpu_env, dirty_addr,
183
- tcg_constant_i64(0));
184
+ gen_helper_autdb_combined(dirty_addr, cpu_env, dirty_addr,
185
+ tcg_constant_i64(0));
186
}
187
}
188
30
--
189
--
31
2.17.1
190
2.34.1
32
191
33
192
diff view generated by jsdifflib
New patch
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
1
2
3
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230829232335.965414-10-richard.henderson@linaro.org
7
Message-Id: <20230609172324.982888-8-aaron@os.amperecomputing.com>
8
[rth: Simplify fpac comparison, reusing cmp_mask]
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/system/arm/emulation.rst | 2 ++
13
target/arm/syndrome.h | 7 +++++++
14
target/arm/tcg/cpu64.c | 2 +-
15
target/arm/tcg/pauth_helper.c | 18 +++++++++++++++++-
16
4 files changed, 27 insertions(+), 2 deletions(-)
17
18
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
19
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/emulation.rst
21
+++ b/docs/system/arm/emulation.rst
22
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
23
- FEAT_FGT (Fine-Grained Traps)
24
- FEAT_FHM (Floating-point half-precision multiplication instructions)
25
- FEAT_FP16 (Half-precision floating-point data processing)
26
+- FEAT_FPAC (Faulting on AUT* instructions)
27
+- FEAT_FPACCOMBINE (Faulting on combined pointer authentication instructions)
28
- FEAT_FRINTTS (Floating-point to integer instructions)
29
- FEAT_FlagM (Flag manipulation instructions v2)
30
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
31
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/syndrome.h
34
+++ b/target/arm/syndrome.h
35
@@ -XXX,XX +XXX,XX @@ enum arm_exception_class {
36
EC_SYSTEMREGISTERTRAP = 0x18,
37
EC_SVEACCESSTRAP = 0x19,
38
EC_ERETTRAP = 0x1a,
39
+ EC_PACFAIL = 0x1c,
40
EC_SMETRAP = 0x1d,
41
EC_GPC = 0x1e,
42
EC_INSNABORT = 0x20,
43
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_smetrap(SMEExceptionType etype, bool is_16bit)
44
| (is_16bit ? 0 : ARM_EL_IL) | etype;
45
}
46
47
+static inline uint32_t syn_pacfail(bool data, int keynumber)
48
+{
49
+ int error_code = (data << 1) | keynumber;
50
+ return (EC_PACFAIL << ARM_EL_EC_SHIFT) | ARM_EL_IL | error_code;
51
+}
52
+
53
static inline uint32_t syn_pactrap(void)
54
{
55
return EC_PACTRAP << ARM_EL_EC_SHIFT;
56
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/tcg/cpu64.c
59
+++ b/target/arm/tcg/cpu64.c
60
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
61
62
t = cpu->isar.id_aa64isar1;
63
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */
64
- t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_2);
65
+ t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_FPACCOMBINED);
66
t = FIELD_DP64(t, ID_AA64ISAR1, API, 1);
67
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); /* FEAT_JSCVT */
68
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); /* FEAT_FCMA */
69
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/tcg/pauth_helper.c
72
+++ b/target/arm/tcg/pauth_helper.c
73
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param)
74
}
75
}
76
77
+static G_NORETURN
78
+void pauth_fail_exception(CPUARMState *env, bool data,
79
+ int keynumber, uintptr_t ra)
80
+{
81
+ raise_exception_ra(env, EXCP_UDEF, syn_pacfail(data, keynumber),
82
+ exception_target_el(env), ra);
83
+}
84
+
85
static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
86
ARMPACKey *key, bool data, int keynumber,
87
uintptr_t ra, bool is_combined)
88
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
89
cmp_mask &= ~MAKE_64BIT_MASK(55, 1);
90
91
if (pauth_feature >= PauthFeat_2) {
92
- return ptr ^ (pac & cmp_mask);
93
+ ARMPauthFeature fault_feature =
94
+ is_combined ? PauthFeat_FPACCOMBINED : PauthFeat_FPAC;
95
+ uint64_t result = ptr ^ (pac & cmp_mask);
96
+
97
+ if (pauth_feature >= fault_feature
98
+ && ((result ^ sextract64(result, 55, 1)) & cmp_mask)) {
99
+ pauth_fail_exception(env, data, keynumber, ra);
100
+ }
101
+ return result;
102
}
103
104
if ((pac ^ ptr) & cmp_mask) {
105
--
106
2.34.1
diff view generated by jsdifflib
1
In the tz-mpc device we allocate a data block for the LUT,
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
which we then clear to zero in the device's reset method.
3
This is conceptually fine, but unfortunately results in a
4
valgrind complaint about use of uninitialized data on startup:
5
2
6
==30906== Conditional jump or move depends on uninitialised value(s)
3
Fix when using GCC v11.4 (Ubuntu 11.4.0-1ubuntu1~22.04) with CFLAGS=-Og:
7
==30906== at 0x503609: tz_mpc_translate (tz-mpc.c:439)
8
==30906== by 0x3F3D90: address_space_translate_iommu (exec.c:511)
9
==30906== by 0x3F3FF8: flatview_do_translate (exec.c:584)
10
==30906== by 0x3F4292: flatview_translate (exec.c:644)
11
==30906== by 0x3F2120: address_space_translate (memory.h:1962)
12
==30906== by 0x3FB753: address_space_ldl_internal (memory_ldst.inc.c:36)
13
==30906== by 0x3FB8A6: address_space_ldl (memory_ldst.inc.c:80)
14
==30906== by 0x619037: ldl_phys (memory_ldst_phys.inc.h:25)
15
==30906== by 0x61985D: arm_cpu_reset (cpu.c:255)
16
==30906== by 0x98791B: cpu_reset (cpu.c:249)
17
==30906== by 0x57FFDB: armv7m_reset (armv7m.c:265)
18
==30906== by 0x7B1775: qemu_devices_reset (reset.c:69)
19
4
20
This is because of a reset ordering problem -- the TZ MPC
5
[4/6] Compiling C object libcommon.fa.p/hw_intc_arm_gicv3_its.c.o
21
resets after the CPU, but an M-profile CPU's reset function
6
FAILED: libcommon.fa.p/hw_intc_arm_gicv3_its.c.o
22
includes memory loads to get the initial PC and SP, which
7
inlined from ‘lookup_vte’ at hw/intc/arm_gicv3_its.c:453:9,
23
then go through an MPC that hasn't yet been reset.
8
inlined from ‘vmovp_callback’ at hw/intc/arm_gicv3_its.c:1039:14:
9
hw/intc/arm_gicv3_its.c:347:9: error: ‘vte.rdbase’ may be used uninitialized [-Werror=maybe-uninitialized]
10
347 | trace_gicv3_its_vte_read(vpeid, vte->valid, vte->vptsize,
11
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12
348 | vte->vptaddr, vte->rdbase);
13
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
14
hw/intc/arm_gicv3_its.c: In function ‘vmovp_callback’:
15
hw/intc/arm_gicv3_its.c:1036:13: note: ‘vte’ declared here
16
1036 | VTEntry vte;
17
| ^~~
24
18
25
The simplest fix for this is to zero the LUT when we
19
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
26
initialize the data, which will result in the MPC's
20
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
27
translate function giving the right answers for these
21
Message-id: 20230831131348.69032-1-philmd@linaro.org
28
early memory accesses.
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
hw/intc/arm_gicv3_its.c | 15 ++++++---------
25
1 file changed, 6 insertions(+), 9 deletions(-)
29
26
30
Reported-by: Thomas Huth <thuth@redhat.com>
27
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Tested-by: Thomas Huth <thuth@redhat.com>
33
Message-id: 20180724153616.32352-1-peter.maydell@linaro.org
34
---
35
hw/misc/tz-mpc.c | 2 +-
36
1 file changed, 1 insertion(+), 1 deletion(-)
37
38
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
39
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/misc/tz-mpc.c
29
--- a/hw/intc/arm_gicv3_its.c
41
+++ b/hw/misc/tz-mpc.c
30
+++ b/hw/intc/arm_gicv3_its.c
42
@@ -XXX,XX +XXX,XX @@ static void tz_mpc_realize(DeviceState *dev, Error **errp)
31
@@ -XXX,XX +XXX,XX @@ static MemTxResult get_vte(GICv3ITSState *s, uint32_t vpeid, VTEntry *vte)
43
address_space_init(&s->blocked_io_as, &s->blocked_io,
32
if (entry_addr == -1) {
44
"tz-mpc-blocked-io");
33
/* No L2 table entry, i.e. no valid VTE, or a memory error */
45
34
vte->valid = false;
46
- s->blk_lut = g_new(uint32_t, s->blk_max);
35
- goto out;
47
+ s->blk_lut = g_new0(uint32_t, s->blk_max);
36
+ trace_gicv3_its_vte_read_fault(vpeid);
37
+ return MEMTX_OK;
38
}
39
vteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
40
if (res != MEMTX_OK) {
41
- goto out;
42
+ trace_gicv3_its_vte_read_fault(vpeid);
43
+ return res;
44
}
45
vte->valid = FIELD_EX64(vteval, VTE, VALID);
46
vte->vptsize = FIELD_EX64(vteval, VTE, VPTSIZE);
47
vte->vptaddr = FIELD_EX64(vteval, VTE, VPTADDR);
48
vte->rdbase = FIELD_EX64(vteval, VTE, RDBASE);
49
-out:
50
- if (res != MEMTX_OK) {
51
- trace_gicv3_its_vte_read_fault(vpeid);
52
- } else {
53
- trace_gicv3_its_vte_read(vpeid, vte->valid, vte->vptsize,
54
- vte->vptaddr, vte->rdbase);
55
- }
56
+ trace_gicv3_its_vte_read(vpeid, vte->valid, vte->vptsize,
57
+ vte->vptaddr, vte->rdbase);
58
return res;
48
}
59
}
49
60
50
static int tz_mpc_post_load(void *opaque, int version_id)
51
--
61
--
52
2.17.1
62
2.34.1
53
63
54
64
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
1
2
3
Introduce the Xilinx Configuration Frame Interface (CFI) for transmitting
4
CFI data packets between the Xilinx Configuration Frame Unit models
5
(CFU_APB, CFU_FDRO and CFU_SFR), the Xilinx CFRAME controller (CFRAME_REG)
6
and the Xilinx CFRAME broadcast controller (CFRAME_BCAST_REG) models (when
7
emulating bitstream programming and readback).
8
9
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
10
Reviewed-by: Sai Pavan Boddu <sai.pavan.boddu@amd.com>
11
Acked-by: Edgar E. Iglesias <edgar@zeroasic.com>
12
Message-id: 20230831165701.2016397-2-francisco.iglesias@amd.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
MAINTAINERS | 6 ++++
16
include/hw/misc/xlnx-cfi-if.h | 59 +++++++++++++++++++++++++++++++++++
17
hw/misc/xlnx-cfi-if.c | 34 ++++++++++++++++++++
18
hw/misc/meson.build | 1 +
19
4 files changed, 100 insertions(+)
20
create mode 100644 include/hw/misc/xlnx-cfi-if.h
21
create mode 100644 hw/misc/xlnx-cfi-if.c
22
23
diff --git a/MAINTAINERS b/MAINTAINERS
24
index XXXXXXX..XXXXXXX 100644
25
--- a/MAINTAINERS
26
+++ b/MAINTAINERS
27
@@ -XXX,XX +XXX,XX @@ S: Maintained
28
F: hw/ssi/xlnx-versal-ospi.c
29
F: include/hw/ssi/xlnx-versal-ospi.h
30
31
+Xilinx Versal CFI
32
+M: Francisco Iglesias <francisco.iglesias@amd.com>
33
+S: Maintained
34
+F: hw/misc/xlnx-cfi-if.c
35
+F: include/hw/misc/xlnx-cfi-if.h
36
+
37
STM32F100
38
M: Alexandre Iooss <erdnaxe@crans.org>
39
L: qemu-arm@nongnu.org
40
diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h
41
new file mode 100644
42
index XXXXXXX..XXXXXXX
43
--- /dev/null
44
+++ b/include/hw/misc/xlnx-cfi-if.h
45
@@ -XXX,XX +XXX,XX @@
46
+/*
47
+ * Xilinx CFI interface
48
+ *
49
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
50
+ *
51
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
52
+ *
53
+ * SPDX-License-Identifier: GPL-2.0-or-later
54
+ */
55
+#ifndef XLNX_CFI_IF_H
56
+#define XLNX_CFI_IF_H 1
57
+
58
+#include "qemu/help-texts.h"
59
+#include "hw/hw.h"
60
+#include "qom/object.h"
61
+
62
+#define TYPE_XLNX_CFI_IF "xlnx-cfi-if"
63
+typedef struct XlnxCfiIfClass XlnxCfiIfClass;
64
+DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF)
65
+
66
+#define XLNX_CFI_IF(obj) \
67
+ INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF)
68
+
69
+typedef enum {
70
+ PACKET_TYPE_CFU = 0x52,
71
+ PACKET_TYPE_CFRAME = 0xA1,
72
+} xlnx_cfi_packet_type;
73
+
74
+typedef enum {
75
+ CFRAME_FAR = 1,
76
+ CFRAME_SFR = 2,
77
+ CFRAME_FDRI = 4,
78
+ CFRAME_CMD = 6,
79
+} xlnx_cfi_reg_addr;
80
+
81
+typedef struct XlnxCfiPacket {
82
+ uint8_t reg_addr;
83
+ uint32_t data[4];
84
+} XlnxCfiPacket;
85
+
86
+typedef struct XlnxCfiIf {
87
+ Object Parent;
88
+} XlnxCfiIf;
89
+
90
+typedef struct XlnxCfiIfClass {
91
+ InterfaceClass parent;
92
+
93
+ void (*cfi_transfer_packet)(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
94
+} XlnxCfiIfClass;
95
+
96
+/**
97
+ * Transfer a XlnxCfiPacket.
98
+ *
99
+ * @cfi_if: the object implementing this interface
100
+ * @XlnxCfiPacket: a pointer to the XlnxCfiPacket to transfer
101
+ */
102
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
103
+
104
+#endif /* XLNX_CFI_IF_H */
105
diff --git a/hw/misc/xlnx-cfi-if.c b/hw/misc/xlnx-cfi-if.c
106
new file mode 100644
107
index XXXXXXX..XXXXXXX
108
--- /dev/null
109
+++ b/hw/misc/xlnx-cfi-if.c
110
@@ -XXX,XX +XXX,XX @@
111
+/*
112
+ * Xilinx CFI interface
113
+ *
114
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
115
+ *
116
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
117
+ *
118
+ * SPDX-License-Identifier: GPL-2.0-or-later
119
+ */
120
+#include "qemu/osdep.h"
121
+#include "hw/misc/xlnx-cfi-if.h"
122
+
123
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
124
+{
125
+ XlnxCfiIfClass *xcic = XLNX_CFI_IF_GET_CLASS(cfi_if);
126
+
127
+ if (xcic->cfi_transfer_packet) {
128
+ xcic->cfi_transfer_packet(cfi_if, pkt);
129
+ }
130
+}
131
+
132
+static const TypeInfo xlnx_cfi_if_info = {
133
+ .name = TYPE_XLNX_CFI_IF,
134
+ .parent = TYPE_INTERFACE,
135
+ .class_size = sizeof(XlnxCfiIfClass),
136
+};
137
+
138
+static void xlnx_cfi_if_register_types(void)
139
+{
140
+ type_register_static(&xlnx_cfi_if_info);
141
+}
142
+
143
+type_init(xlnx_cfi_if_register_types)
144
+
145
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
146
index XXXXXXX..XXXXXXX 100644
147
--- a/hw/misc/meson.build
148
+++ b/hw/misc/meson.build
149
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
150
system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
151
'xlnx-versal-xramc.c',
152
'xlnx-versal-pmc-iou-slcr.c',
153
+ 'xlnx-cfi-if.c',
154
))
155
system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
156
system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
157
--
158
2.34.1
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
1
2
3
Introduce a model of the software programming interface (CFU_APB) of
4
Xilinx Versal's Configuration Frame Unit.
5
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230831165701.2016397-3-francisco.iglesias@amd.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
MAINTAINERS | 2 +
12
include/hw/misc/xlnx-versal-cfu.h | 231 ++++++++++++++++++
13
hw/misc/xlnx-versal-cfu.c | 380 ++++++++++++++++++++++++++++++
14
hw/misc/meson.build | 1 +
15
4 files changed, 614 insertions(+)
16
create mode 100644 include/hw/misc/xlnx-versal-cfu.h
17
create mode 100644 hw/misc/xlnx-versal-cfu.c
18
19
diff --git a/MAINTAINERS b/MAINTAINERS
20
index XXXXXXX..XXXXXXX 100644
21
--- a/MAINTAINERS
22
+++ b/MAINTAINERS
23
@@ -XXX,XX +XXX,XX @@ M: Francisco Iglesias <francisco.iglesias@amd.com>
24
S: Maintained
25
F: hw/misc/xlnx-cfi-if.c
26
F: include/hw/misc/xlnx-cfi-if.h
27
+F: hw/misc/xlnx-versal-cfu.c
28
+F: include/hw/misc/xlnx-versal-cfu.h
29
30
STM32F100
31
M: Alexandre Iooss <erdnaxe@crans.org>
32
diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/xlnx-versal-cfu.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * QEMU model of the CFU Configuration Unit.
40
+ *
41
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
42
+ *
43
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
44
+ *
45
+ * SPDX-License-Identifier: GPL-2.0-or-later
46
+ *
47
+ * References:
48
+ * [1] Versal ACAP Technical Reference Manual,
49
+ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
50
+ *
51
+ * [2] Versal ACAP Register Reference,
52
+ * https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html
53
+ */
54
+#ifndef HW_MISC_XLNX_VERSAL_CFU_APB_H
55
+#define HW_MISC_XLNX_VERSAL_CFU_APB_H
56
+
57
+#include "hw/sysbus.h"
58
+#include "hw/register.h"
59
+#include "hw/misc/xlnx-cfi-if.h"
60
+
61
+#define TYPE_XLNX_VERSAL_CFU_APB "xlnx,versal-cfu-apb"
62
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, XLNX_VERSAL_CFU_APB)
63
+
64
+REG32(CFU_ISR, 0x0)
65
+ FIELD(CFU_ISR, USR_GTS_EVENT, 9, 1)
66
+ FIELD(CFU_ISR, USR_GSR_EVENT, 8, 1)
67
+ FIELD(CFU_ISR, SLVERR, 7, 1)
68
+ FIELD(CFU_ISR, DECOMP_ERROR, 6, 1)
69
+ FIELD(CFU_ISR, BAD_CFI_PACKET, 5, 1)
70
+ FIELD(CFU_ISR, AXI_ALIGN_ERROR, 4, 1)
71
+ FIELD(CFU_ISR, CFI_ROW_ERROR, 3, 1)
72
+ FIELD(CFU_ISR, CRC32_ERROR, 2, 1)
73
+ FIELD(CFU_ISR, CRC8_ERROR, 1, 1)
74
+ FIELD(CFU_ISR, SEU_ENDOFCALIB, 0, 1)
75
+REG32(CFU_IMR, 0x4)
76
+ FIELD(CFU_IMR, USR_GTS_EVENT, 9, 1)
77
+ FIELD(CFU_IMR, USR_GSR_EVENT, 8, 1)
78
+ FIELD(CFU_IMR, SLVERR, 7, 1)
79
+ FIELD(CFU_IMR, DECOMP_ERROR, 6, 1)
80
+ FIELD(CFU_IMR, BAD_CFI_PACKET, 5, 1)
81
+ FIELD(CFU_IMR, AXI_ALIGN_ERROR, 4, 1)
82
+ FIELD(CFU_IMR, CFI_ROW_ERROR, 3, 1)
83
+ FIELD(CFU_IMR, CRC32_ERROR, 2, 1)
84
+ FIELD(CFU_IMR, CRC8_ERROR, 1, 1)
85
+ FIELD(CFU_IMR, SEU_ENDOFCALIB, 0, 1)
86
+REG32(CFU_IER, 0x8)
87
+ FIELD(CFU_IER, USR_GTS_EVENT, 9, 1)
88
+ FIELD(CFU_IER, USR_GSR_EVENT, 8, 1)
89
+ FIELD(CFU_IER, SLVERR, 7, 1)
90
+ FIELD(CFU_IER, DECOMP_ERROR, 6, 1)
91
+ FIELD(CFU_IER, BAD_CFI_PACKET, 5, 1)
92
+ FIELD(CFU_IER, AXI_ALIGN_ERROR, 4, 1)
93
+ FIELD(CFU_IER, CFI_ROW_ERROR, 3, 1)
94
+ FIELD(CFU_IER, CRC32_ERROR, 2, 1)
95
+ FIELD(CFU_IER, CRC8_ERROR, 1, 1)
96
+ FIELD(CFU_IER, SEU_ENDOFCALIB, 0, 1)
97
+REG32(CFU_IDR, 0xc)
98
+ FIELD(CFU_IDR, USR_GTS_EVENT, 9, 1)
99
+ FIELD(CFU_IDR, USR_GSR_EVENT, 8, 1)
100
+ FIELD(CFU_IDR, SLVERR, 7, 1)
101
+ FIELD(CFU_IDR, DECOMP_ERROR, 6, 1)
102
+ FIELD(CFU_IDR, BAD_CFI_PACKET, 5, 1)
103
+ FIELD(CFU_IDR, AXI_ALIGN_ERROR, 4, 1)
104
+ FIELD(CFU_IDR, CFI_ROW_ERROR, 3, 1)
105
+ FIELD(CFU_IDR, CRC32_ERROR, 2, 1)
106
+ FIELD(CFU_IDR, CRC8_ERROR, 1, 1)
107
+ FIELD(CFU_IDR, SEU_ENDOFCALIB, 0, 1)
108
+REG32(CFU_ITR, 0x10)
109
+ FIELD(CFU_ITR, USR_GTS_EVENT, 9, 1)
110
+ FIELD(CFU_ITR, USR_GSR_EVENT, 8, 1)
111
+ FIELD(CFU_ITR, SLVERR, 7, 1)
112
+ FIELD(CFU_ITR, DECOMP_ERROR, 6, 1)
113
+ FIELD(CFU_ITR, BAD_CFI_PACKET, 5, 1)
114
+ FIELD(CFU_ITR, AXI_ALIGN_ERROR, 4, 1)
115
+ FIELD(CFU_ITR, CFI_ROW_ERROR, 3, 1)
116
+ FIELD(CFU_ITR, CRC32_ERROR, 2, 1)
117
+ FIELD(CFU_ITR, CRC8_ERROR, 1, 1)
118
+ FIELD(CFU_ITR, SEU_ENDOFCALIB, 0, 1)
119
+REG32(CFU_PROTECT, 0x14)
120
+ FIELD(CFU_PROTECT, ACTIVE, 0, 1)
121
+REG32(CFU_FGCR, 0x18)
122
+ FIELD(CFU_FGCR, GCLK_CAL, 14, 1)
123
+ FIELD(CFU_FGCR, SC_HBC_TRIGGER, 13, 1)
124
+ FIELD(CFU_FGCR, GLOW, 12, 1)
125
+ FIELD(CFU_FGCR, GPWRDWN, 11, 1)
126
+ FIELD(CFU_FGCR, GCAP, 10, 1)
127
+ FIELD(CFU_FGCR, GSCWE, 9, 1)
128
+ FIELD(CFU_FGCR, GHIGH_B, 8, 1)
129
+ FIELD(CFU_FGCR, GMC_B, 7, 1)
130
+ FIELD(CFU_FGCR, GWE, 6, 1)
131
+ FIELD(CFU_FGCR, GRESTORE, 5, 1)
132
+ FIELD(CFU_FGCR, GTS_CFG_B, 4, 1)
133
+ FIELD(CFU_FGCR, GLUTMASK, 3, 1)
134
+ FIELD(CFU_FGCR, EN_GLOBS_B, 2, 1)
135
+ FIELD(CFU_FGCR, EOS, 1, 1)
136
+ FIELD(CFU_FGCR, INIT_COMPLETE, 0, 1)
137
+REG32(CFU_CTL, 0x1c)
138
+ FIELD(CFU_CTL, GSR_GSC, 15, 1)
139
+ FIELD(CFU_CTL, SLVERR_EN, 14, 1)
140
+ FIELD(CFU_CTL, CRC32_RESET, 13, 1)
141
+ FIELD(CFU_CTL, AXI_ERROR_EN, 12, 1)
142
+ FIELD(CFU_CTL, FLUSH_AXI, 11, 1)
143
+ FIELD(CFU_CTL, SSI_PER_SLR_PR, 10, 1)
144
+ FIELD(CFU_CTL, GCAP_CLK_EN, 9, 1)
145
+ FIELD(CFU_CTL, STATUS_SYNC_DISABLE, 8, 1)
146
+ FIELD(CFU_CTL, IGNORE_CFI_ERROR, 7, 1)
147
+ FIELD(CFU_CTL, CFRAME_DISABLE, 6, 1)
148
+ FIELD(CFU_CTL, QWORD_CNT_RESET, 5, 1)
149
+ FIELD(CFU_CTL, CRC8_DISABLE, 4, 1)
150
+ FIELD(CFU_CTL, CRC32_CHECK, 3, 1)
151
+ FIELD(CFU_CTL, DECOMPRESS, 2, 1)
152
+ FIELD(CFU_CTL, SEU_GO, 1, 1)
153
+ FIELD(CFU_CTL, CFI_LOCAL_RESET, 0, 1)
154
+REG32(CFU_CRAM_RW, 0x20)
155
+ FIELD(CFU_CRAM_RW, RFIFO_AFULL_DEPTH, 18, 9)
156
+ FIELD(CFU_CRAM_RW, RD_WAVE_CNT_LEFT, 12, 6)
157
+ FIELD(CFU_CRAM_RW, RD_WAVE_CNT, 6, 6)
158
+ FIELD(CFU_CRAM_RW, WR_WAVE_CNT, 0, 6)
159
+REG32(CFU_MASK, 0x28)
160
+REG32(CFU_CRC_EXPECT, 0x2c)
161
+REG32(CFU_CFRAME_LEFT_T0, 0x60)
162
+ FIELD(CFU_CFRAME_LEFT_T0, NUM, 0, 20)
163
+REG32(CFU_CFRAME_LEFT_T1, 0x64)
164
+ FIELD(CFU_CFRAME_LEFT_T1, NUM, 0, 20)
165
+REG32(CFU_CFRAME_LEFT_T2, 0x68)
166
+ FIELD(CFU_CFRAME_LEFT_T2, NUM, 0, 20)
167
+REG32(CFU_ROW_RANGE, 0x6c)
168
+ FIELD(CFU_ROW_RANGE, HALF_FSR, 5, 1)
169
+ FIELD(CFU_ROW_RANGE, NUM, 0, 5)
170
+REG32(CFU_STATUS, 0x100)
171
+ FIELD(CFU_STATUS, SEU_WRITE_ERROR, 30, 1)
172
+ FIELD(CFU_STATUS, FRCNT_ERROR, 29, 1)
173
+ FIELD(CFU_STATUS, RSVD_ERROR, 28, 1)
174
+ FIELD(CFU_STATUS, FDRO_ERROR, 27, 1)
175
+ FIELD(CFU_STATUS, FDRI_ERROR, 26, 1)
176
+ FIELD(CFU_STATUS, FDRI_READ_ERROR, 25, 1)
177
+ FIELD(CFU_STATUS, READ_FDRI_ERROR, 24, 1)
178
+ FIELD(CFU_STATUS, READ_SFR_ERROR, 23, 1)
179
+ FIELD(CFU_STATUS, READ_STREAM_ERROR, 22, 1)
180
+ FIELD(CFU_STATUS, UNKNOWN_STREAM_PKT, 21, 1)
181
+ FIELD(CFU_STATUS, USR_GTS, 20, 1)
182
+ FIELD(CFU_STATUS, USR_GSR, 19, 1)
183
+ FIELD(CFU_STATUS, AXI_BAD_WSTRB, 18, 1)
184
+ FIELD(CFU_STATUS, AXI_BAD_AR_SIZE, 17, 1)
185
+ FIELD(CFU_STATUS, AXI_BAD_AW_SIZE, 16, 1)
186
+ FIELD(CFU_STATUS, AXI_BAD_ARADDR, 15, 1)
187
+ FIELD(CFU_STATUS, AXI_BAD_AWADDR, 14, 1)
188
+ FIELD(CFU_STATUS, SCAN_CLEAR_PASS, 13, 1)
189
+ FIELD(CFU_STATUS, HC_SEC_ERROR, 12, 1)
190
+ FIELD(CFU_STATUS, GHIGH_B_ISHIGH, 11, 1)
191
+ FIELD(CFU_STATUS, GHIGH_B_ISLOW, 10, 1)
192
+ FIELD(CFU_STATUS, GMC_B_ISHIGH, 9, 1)
193
+ FIELD(CFU_STATUS, GMC_B_ISLOW, 8, 1)
194
+ FIELD(CFU_STATUS, GPWRDWN_B_ISHIGH, 7, 1)
195
+ FIELD(CFU_STATUS, CFI_SEU_CRC_ERROR, 6, 1)
196
+ FIELD(CFU_STATUS, CFI_SEU_ECC_ERROR, 5, 1)
197
+ FIELD(CFU_STATUS, CFI_SEU_HEARTBEAT, 4, 1)
198
+ FIELD(CFU_STATUS, SCAN_CLEAR_DONE, 3, 1)
199
+ FIELD(CFU_STATUS, HC_COMPLETE, 2, 1)
200
+ FIELD(CFU_STATUS, CFI_CFRAME_BUSY, 1, 1)
201
+ FIELD(CFU_STATUS, CFU_STREAM_BUSY, 0, 1)
202
+REG32(CFU_INTERNAL_STATUS, 0x104)
203
+ FIELD(CFU_INTERNAL_STATUS, SSI_EOS, 22, 1)
204
+ FIELD(CFU_INTERNAL_STATUS, SSI_GWE, 21, 1)
205
+ FIELD(CFU_INTERNAL_STATUS, RFIFO_EMPTY, 20, 1)
206
+ FIELD(CFU_INTERNAL_STATUS, RFIFO_FULL, 19, 1)
207
+ FIELD(CFU_INTERNAL_STATUS, SEL_SFR, 18, 1)
208
+ FIELD(CFU_INTERNAL_STATUS, STREAM_CFRAME, 17, 1)
209
+ FIELD(CFU_INTERNAL_STATUS, FDRI_PHASE, 16, 1)
210
+ FIELD(CFU_INTERNAL_STATUS, CFI_PIPE_EN, 15, 1)
211
+ FIELD(CFU_INTERNAL_STATUS, AWFIFO_DCNT, 10, 5)
212
+ FIELD(CFU_INTERNAL_STATUS, WFIFO_DCNT, 5, 5)
213
+ FIELD(CFU_INTERNAL_STATUS, REPAIR_BUSY, 4, 1)
214
+ FIELD(CFU_INTERNAL_STATUS, TRIMU_BUSY, 3, 1)
215
+ FIELD(CFU_INTERNAL_STATUS, TRIMB_BUSY, 2, 1)
216
+ FIELD(CFU_INTERNAL_STATUS, HCLEANR_BUSY, 1, 1)
217
+ FIELD(CFU_INTERNAL_STATUS, HCLEAN_BUSY, 0, 1)
218
+REG32(CFU_QWORD_CNT, 0x108)
219
+REG32(CFU_CRC_LIVE, 0x10c)
220
+REG32(CFU_PENDING_READ_CNT, 0x110)
221
+ FIELD(CFU_PENDING_READ_CNT, NUM, 0, 25)
222
+REG32(CFU_FDRI_CNT, 0x114)
223
+REG32(CFU_ECO1, 0x118)
224
+REG32(CFU_ECO2, 0x11c)
225
+
226
+#define R_MAX (R_CFU_ECO2 + 1)
227
+
228
+#define NUM_STREAM 2
229
+#define WFIFO_SZ 4
230
+
231
+struct XlnxVersalCFUAPB {
232
+ SysBusDevice parent_obj;
233
+ MemoryRegion iomem;
234
+ MemoryRegion iomem_stream[NUM_STREAM];
235
+ qemu_irq irq_cfu_imr;
236
+
237
+ /* 128-bit wfifo. */
238
+ uint32_t wfifo[WFIFO_SZ];
239
+
240
+ uint32_t regs[R_MAX];
241
+ RegisterInfo regs_info[R_MAX];
242
+
243
+ uint8_t fdri_row_addr;
244
+
245
+ struct {
246
+ XlnxCfiIf *cframe[15];
247
+ } cfg;
248
+};
249
+
250
+/**
251
+ * This is a helper function for updating a CFI data write fifo, an array of 4
252
+ * uint32_t and 128 bits of data that are allowed to be written through 4
253
+ * sequential 32 bit accesses. After the last index has been written into the
254
+ * write fifo (wfifo), the data is copied to and returned in a secondary fifo
255
+ * provided to the function (wfifo_ret), and the write fifo is cleared
256
+ * (zeroized).
257
+ *
258
+ * @addr: the address used when calculating the wfifo array index to update
259
+ * @value: the value to write into the wfifo array
260
+ * @wfifo: the wfifo to update
261
+ * @wfifo_out: will return the wfifo data when all 128 bits have been written
262
+ *
263
+ * @return: true if all 128 bits have been updated.
264
+ */
265
+bool update_wfifo(hwaddr addr, uint64_t value,
266
+ uint32_t *wfifo, uint32_t *wfifo_ret);
267
+
268
+#endif
269
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
270
new file mode 100644
271
index XXXXXXX..XXXXXXX
272
--- /dev/null
273
+++ b/hw/misc/xlnx-versal-cfu.c
274
@@ -XXX,XX +XXX,XX @@
275
+/*
276
+ * QEMU model of the CFU Configuration Unit.
277
+ *
278
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
279
+ *
280
+ * Written by Edgar E. Iglesias <edgar.iglesias@gmail.com>,
281
+ * Sai Pavan Boddu <sai.pavan.boddu@amd.com>,
282
+ * Francisco Iglesias <francisco.iglesias@amd.com>
283
+ *
284
+ * SPDX-License-Identifier: GPL-2.0-or-later
285
+ */
286
+
287
+#include "qemu/osdep.h"
288
+#include "hw/sysbus.h"
289
+#include "hw/register.h"
290
+#include "hw/irq.h"
291
+#include "qemu/bitops.h"
292
+#include "qemu/log.h"
293
+#include "qemu/units.h"
294
+#include "migration/vmstate.h"
295
+#include "hw/qdev-properties.h"
296
+#include "hw/qdev-properties-system.h"
297
+#include "hw/misc/xlnx-versal-cfu.h"
298
+
299
+#ifndef XLNX_VERSAL_CFU_APB_ERR_DEBUG
300
+#define XLNX_VERSAL_CFU_APB_ERR_DEBUG 0
301
+#endif
302
+
303
+#define KEYHOLE_STREAM_4K (4 * KiB)
304
+#define KEYHOLE_STREAM_256K (256 * KiB)
305
+#define CFRAME_BROADCAST_ROW 0x1F
306
+
307
+bool update_wfifo(hwaddr addr, uint64_t value,
308
+ uint32_t *wfifo, uint32_t *wfifo_ret)
309
+{
310
+ unsigned int idx = extract32(addr, 2, 2);
311
+
312
+ wfifo[idx] = value;
313
+
314
+ if (idx == 3) {
315
+ memcpy(wfifo_ret, wfifo, WFIFO_SZ * sizeof(uint32_t));
316
+ memset(wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
317
+ return true;
318
+ }
319
+
320
+ return false;
321
+}
322
+
323
+static void cfu_imr_update_irq(XlnxVersalCFUAPB *s)
324
+{
325
+ bool pending = s->regs[R_CFU_ISR] & ~s->regs[R_CFU_IMR];
326
+ qemu_set_irq(s->irq_cfu_imr, pending);
327
+}
328
+
329
+static void cfu_isr_postw(RegisterInfo *reg, uint64_t val64)
330
+{
331
+ XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
332
+ cfu_imr_update_irq(s);
333
+}
334
+
335
+static uint64_t cfu_ier_prew(RegisterInfo *reg, uint64_t val64)
336
+{
337
+ XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
338
+ uint32_t val = val64;
339
+
340
+ s->regs[R_CFU_IMR] &= ~val;
341
+ cfu_imr_update_irq(s);
342
+ return 0;
343
+}
344
+
345
+static uint64_t cfu_idr_prew(RegisterInfo *reg, uint64_t val64)
346
+{
347
+ XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
348
+ uint32_t val = val64;
349
+
350
+ s->regs[R_CFU_IMR] |= val;
351
+ cfu_imr_update_irq(s);
352
+ return 0;
353
+}
354
+
355
+static uint64_t cfu_itr_prew(RegisterInfo *reg, uint64_t val64)
356
+{
357
+ XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
358
+ uint32_t val = val64;
359
+
360
+ s->regs[R_CFU_ISR] |= val;
361
+ cfu_imr_update_irq(s);
362
+ return 0;
363
+}
364
+
365
+static void cfu_fgcr_postw(RegisterInfo *reg, uint64_t val64)
366
+{
367
+ XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
368
+ uint32_t val = (uint32_t)val64;
369
+
370
+ /* Do a scan. It always looks good. */
371
+ if (FIELD_EX32(val, CFU_FGCR, SC_HBC_TRIGGER)) {
372
+ ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_PASS, 1);
373
+ ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_DONE, 1);
374
+ }
375
+}
376
+
377
+static const RegisterAccessInfo cfu_apb_regs_info[] = {
378
+ { .name = "CFU_ISR", .addr = A_CFU_ISR,
379
+ .rsvd = 0xfffffc00,
380
+ .w1c = 0x3ff,
381
+ .post_write = cfu_isr_postw,
382
+ },{ .name = "CFU_IMR", .addr = A_CFU_IMR,
383
+ .reset = 0x3ff,
384
+ .rsvd = 0xfffffc00,
385
+ .ro = 0x3ff,
386
+ },{ .name = "CFU_IER", .addr = A_CFU_IER,
387
+ .rsvd = 0xfffffc00,
388
+ .pre_write = cfu_ier_prew,
389
+ },{ .name = "CFU_IDR", .addr = A_CFU_IDR,
390
+ .rsvd = 0xfffffc00,
391
+ .pre_write = cfu_idr_prew,
392
+ },{ .name = "CFU_ITR", .addr = A_CFU_ITR,
393
+ .rsvd = 0xfffffc00,
394
+ .pre_write = cfu_itr_prew,
395
+ },{ .name = "CFU_PROTECT", .addr = A_CFU_PROTECT,
396
+ .reset = 0x1,
397
+ },{ .name = "CFU_FGCR", .addr = A_CFU_FGCR,
398
+ .rsvd = 0xffff8000,
399
+ .post_write = cfu_fgcr_postw,
400
+ },{ .name = "CFU_CTL", .addr = A_CFU_CTL,
401
+ .rsvd = 0xffff0000,
402
+ },{ .name = "CFU_CRAM_RW", .addr = A_CFU_CRAM_RW,
403
+ .reset = 0x401f7d9,
404
+ .rsvd = 0xf8000000,
405
+ },{ .name = "CFU_MASK", .addr = A_CFU_MASK,
406
+ },{ .name = "CFU_CRC_EXPECT", .addr = A_CFU_CRC_EXPECT,
407
+ },{ .name = "CFU_CFRAME_LEFT_T0", .addr = A_CFU_CFRAME_LEFT_T0,
408
+ .rsvd = 0xfff00000,
409
+ },{ .name = "CFU_CFRAME_LEFT_T1", .addr = A_CFU_CFRAME_LEFT_T1,
410
+ .rsvd = 0xfff00000,
411
+ },{ .name = "CFU_CFRAME_LEFT_T2", .addr = A_CFU_CFRAME_LEFT_T2,
412
+ .rsvd = 0xfff00000,
413
+ },{ .name = "CFU_ROW_RANGE", .addr = A_CFU_ROW_RANGE,
414
+ .rsvd = 0xffffffc0,
415
+ .ro = 0x3f,
416
+ },{ .name = "CFU_STATUS", .addr = A_CFU_STATUS,
417
+ .rsvd = 0x80000000,
418
+ .ro = 0x7fffffff,
419
+ },{ .name = "CFU_INTERNAL_STATUS", .addr = A_CFU_INTERNAL_STATUS,
420
+ .rsvd = 0xff800000,
421
+ .ro = 0x7fffff,
422
+ },{ .name = "CFU_QWORD_CNT", .addr = A_CFU_QWORD_CNT,
423
+ .ro = 0xffffffff,
424
+ },{ .name = "CFU_CRC_LIVE", .addr = A_CFU_CRC_LIVE,
425
+ .ro = 0xffffffff,
426
+ },{ .name = "CFU_PENDING_READ_CNT", .addr = A_CFU_PENDING_READ_CNT,
427
+ .rsvd = 0xfe000000,
428
+ .ro = 0x1ffffff,
429
+ },{ .name = "CFU_FDRI_CNT", .addr = A_CFU_FDRI_CNT,
430
+ .ro = 0xffffffff,
431
+ },{ .name = "CFU_ECO1", .addr = A_CFU_ECO1,
432
+ },{ .name = "CFU_ECO2", .addr = A_CFU_ECO2,
433
+ }
434
+};
435
+
436
+static void cfu_apb_reset(DeviceState *dev)
437
+{
438
+ XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(dev);
439
+ unsigned int i;
440
+
441
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
442
+ register_reset(&s->regs_info[i]);
443
+ }
444
+ memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
445
+
446
+ s->regs[R_CFU_STATUS] |= R_CFU_STATUS_HC_COMPLETE_MASK;
447
+ cfu_imr_update_irq(s);
448
+}
449
+
450
+static const MemoryRegionOps cfu_apb_ops = {
451
+ .read = register_read_memory,
452
+ .write = register_write_memory,
453
+ .endianness = DEVICE_LITTLE_ENDIAN,
454
+ .valid = {
455
+ .min_access_size = 4,
456
+ .max_access_size = 4,
457
+ },
458
+};
459
+
460
+static void cfu_transfer_cfi_packet(XlnxVersalCFUAPB *s, uint8_t row_addr,
461
+ XlnxCfiPacket *pkt)
462
+{
463
+ if (row_addr == CFRAME_BROADCAST_ROW) {
464
+ for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
465
+ if (s->cfg.cframe[i]) {
466
+ xlnx_cfi_transfer_packet(s->cfg.cframe[i], pkt);
467
+ }
468
+ }
469
+ } else {
470
+ assert(row_addr < ARRAY_SIZE(s->cfg.cframe));
471
+
472
+ if (s->cfg.cframe[row_addr]) {
473
+ xlnx_cfi_transfer_packet(s->cfg.cframe[row_addr], pkt);
474
+ }
475
+ }
476
+}
477
+
478
+static uint64_t cfu_stream_read(void *opaque, hwaddr addr, unsigned size)
479
+{
480
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
481
+ HWADDR_PRIx "\n", __func__, addr);
482
+ return 0;
483
+}
484
+
485
+static void cfu_stream_write(void *opaque, hwaddr addr, uint64_t value,
486
+ unsigned size)
487
+{
488
+ XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(opaque);
489
+ uint32_t wfifo[WFIFO_SZ];
490
+
491
+ if (update_wfifo(addr, value, s->wfifo, wfifo)) {
492
+ uint8_t packet_type, row_addr, reg_addr;
493
+
494
+ packet_type = extract32(wfifo[0], 24, 8);
495
+ row_addr = extract32(wfifo[0], 16, 5);
496
+ reg_addr = extract32(wfifo[0], 8, 6);
497
+
498
+ /* Compressed bitstreams are not supported yet. */
499
+ if (ARRAY_FIELD_EX32(s->regs, CFU_CTL, DECOMPRESS) == 0) {
500
+ if (s->regs[R_CFU_FDRI_CNT]) {
501
+ XlnxCfiPacket pkt = {
502
+ .reg_addr = CFRAME_FDRI,
503
+ .data[0] = wfifo[0],
504
+ .data[1] = wfifo[1],
505
+ .data[2] = wfifo[2],
506
+ .data[3] = wfifo[3]
507
+ };
508
+
509
+ cfu_transfer_cfi_packet(s, s->fdri_row_addr, &pkt);
510
+
511
+ s->regs[R_CFU_FDRI_CNT]--;
512
+
513
+ } else if (packet_type == PACKET_TYPE_CFU &&
514
+ reg_addr == CFRAME_FDRI) {
515
+
516
+ /* Load R_CFU_FDRI_CNT, must be multiple of 25 */
517
+ s->regs[R_CFU_FDRI_CNT] = wfifo[1];
518
+
519
+ /* Store target row_addr */
520
+ s->fdri_row_addr = row_addr;
521
+
522
+ if (wfifo[1] % 25 != 0) {
523
+ qemu_log_mask(LOG_GUEST_ERROR,
524
+ "CFU FDRI_CNT is not loaded with "
525
+ "a multiple of 25 value\n");
526
+ }
527
+
528
+ } else if (packet_type == PACKET_TYPE_CFRAME) {
529
+ XlnxCfiPacket pkt = {
530
+ .reg_addr = reg_addr,
531
+ .data[0] = wfifo[1],
532
+ .data[1] = wfifo[2],
533
+ .data[2] = wfifo[3],
534
+ };
535
+ cfu_transfer_cfi_packet(s, row_addr, &pkt);
536
+ }
537
+ }
538
+ }
539
+}
540
+
541
+static const MemoryRegionOps cfu_stream_ops = {
542
+ .read = cfu_stream_read,
543
+ .write = cfu_stream_write,
544
+ .endianness = DEVICE_LITTLE_ENDIAN,
545
+ .valid = {
546
+ .min_access_size = 4,
547
+ .max_access_size = 8,
548
+ },
549
+};
550
+
551
+static void cfu_apb_init(Object *obj)
552
+{
553
+ XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
554
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
555
+ RegisterInfoArray *reg_array;
556
+ unsigned int i;
557
+ char *name;
558
+
559
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_VERSAL_CFU_APB, R_MAX * 4);
560
+ reg_array =
561
+ register_init_block32(DEVICE(obj), cfu_apb_regs_info,
562
+ ARRAY_SIZE(cfu_apb_regs_info),
563
+ s->regs_info, s->regs,
564
+ &cfu_apb_ops,
565
+ XLNX_VERSAL_CFU_APB_ERR_DEBUG,
566
+ R_MAX * 4);
567
+ memory_region_add_subregion(&s->iomem,
568
+ 0x0,
569
+ &reg_array->mem);
570
+ sysbus_init_mmio(sbd, &s->iomem);
571
+ for (i = 0; i < NUM_STREAM; i++) {
572
+ name = g_strdup_printf(TYPE_XLNX_VERSAL_CFU_APB "-stream%d", i);
573
+ memory_region_init_io(&s->iomem_stream[i], obj, &cfu_stream_ops, s,
574
+ name, i == 0 ? KEYHOLE_STREAM_4K :
575
+ KEYHOLE_STREAM_256K);
576
+ sysbus_init_mmio(sbd, &s->iomem_stream[i]);
577
+ g_free(name);
578
+ }
579
+ sysbus_init_irq(sbd, &s->irq_cfu_imr);
580
+}
581
+
582
+static Property cfu_props[] = {
583
+ DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0],
584
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
585
+ DEFINE_PROP_LINK("cframe1", XlnxVersalCFUAPB, cfg.cframe[1],
586
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
587
+ DEFINE_PROP_LINK("cframe2", XlnxVersalCFUAPB, cfg.cframe[2],
588
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
589
+ DEFINE_PROP_LINK("cframe3", XlnxVersalCFUAPB, cfg.cframe[3],
590
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
591
+ DEFINE_PROP_LINK("cframe4", XlnxVersalCFUAPB, cfg.cframe[4],
592
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
593
+ DEFINE_PROP_LINK("cframe5", XlnxVersalCFUAPB, cfg.cframe[5],
594
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
595
+ DEFINE_PROP_LINK("cframe6", XlnxVersalCFUAPB, cfg.cframe[6],
596
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
597
+ DEFINE_PROP_LINK("cframe7", XlnxVersalCFUAPB, cfg.cframe[7],
598
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
599
+ DEFINE_PROP_LINK("cframe8", XlnxVersalCFUAPB, cfg.cframe[8],
600
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
601
+ DEFINE_PROP_LINK("cframe9", XlnxVersalCFUAPB, cfg.cframe[9],
602
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
603
+ DEFINE_PROP_LINK("cframe10", XlnxVersalCFUAPB, cfg.cframe[10],
604
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
605
+ DEFINE_PROP_LINK("cframe11", XlnxVersalCFUAPB, cfg.cframe[11],
606
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
607
+ DEFINE_PROP_LINK("cframe12", XlnxVersalCFUAPB, cfg.cframe[12],
608
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
609
+ DEFINE_PROP_LINK("cframe13", XlnxVersalCFUAPB, cfg.cframe[13],
610
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
611
+ DEFINE_PROP_LINK("cframe14", XlnxVersalCFUAPB, cfg.cframe[14],
612
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
613
+ DEFINE_PROP_END_OF_LIST(),
614
+};
615
+
616
+static const VMStateDescription vmstate_cfu_apb = {
617
+ .name = TYPE_XLNX_VERSAL_CFU_APB,
618
+ .version_id = 1,
619
+ .minimum_version_id = 1,
620
+ .fields = (VMStateField[]) {
621
+ VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFUAPB, 4),
622
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCFUAPB, R_MAX),
623
+ VMSTATE_UINT8(fdri_row_addr, XlnxVersalCFUAPB),
624
+ VMSTATE_END_OF_LIST(),
625
+ }
626
+};
627
+
628
+static void cfu_apb_class_init(ObjectClass *klass, void *data)
629
+{
630
+ DeviceClass *dc = DEVICE_CLASS(klass);
631
+
632
+ dc->reset = cfu_apb_reset;
633
+ dc->vmsd = &vmstate_cfu_apb;
634
+ device_class_set_props(dc, cfu_props);
635
+}
636
+
637
+static const TypeInfo cfu_apb_info = {
638
+ .name = TYPE_XLNX_VERSAL_CFU_APB,
639
+ .parent = TYPE_SYS_BUS_DEVICE,
640
+ .instance_size = sizeof(XlnxVersalCFUAPB),
641
+ .class_init = cfu_apb_class_init,
642
+ .instance_init = cfu_apb_init,
643
+ .interfaces = (InterfaceInfo[]) {
644
+ { TYPE_XLNX_CFI_IF },
645
+ { }
646
+ }
647
+};
648
+
649
+static void cfu_apb_register_types(void)
650
+{
651
+ type_register_static(&cfu_apb_info);
652
+}
653
+
654
+type_init(cfu_apb_register_types)
655
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
656
index XXXXXXX..XXXXXXX 100644
657
--- a/hw/misc/meson.build
658
+++ b/hw/misc/meson.build
659
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
660
system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
661
'xlnx-versal-xramc.c',
662
'xlnx-versal-pmc-iou-slcr.c',
663
+ 'xlnx-versal-cfu.c',
664
'xlnx-cfi-if.c',
665
))
666
system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
667
--
668
2.34.1
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
1
2
3
Introduce a model of Xilinx Versal's Configuration Frame Unit's data out
4
port (CFU_FDRO).
5
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230831165701.2016397-4-francisco.iglesias@amd.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/misc/xlnx-versal-cfu.h | 12 ++++
12
hw/misc/xlnx-versal-cfu.c | 96 +++++++++++++++++++++++++++++++
13
2 files changed, 108 insertions(+)
14
15
diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/xlnx-versal-cfu.h
18
+++ b/include/hw/misc/xlnx-versal-cfu.h
19
@@ -XXX,XX +XXX,XX @@
20
#include "hw/sysbus.h"
21
#include "hw/register.h"
22
#include "hw/misc/xlnx-cfi-if.h"
23
+#include "qemu/fifo32.h"
24
25
#define TYPE_XLNX_VERSAL_CFU_APB "xlnx,versal-cfu-apb"
26
OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, XLNX_VERSAL_CFU_APB)
27
28
+#define TYPE_XLNX_VERSAL_CFU_FDRO "xlnx,versal-cfu-fdro"
29
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUFDRO, XLNX_VERSAL_CFU_FDRO)
30
+
31
REG32(CFU_ISR, 0x0)
32
FIELD(CFU_ISR, USR_GTS_EVENT, 9, 1)
33
FIELD(CFU_ISR, USR_GSR_EVENT, 8, 1)
34
@@ -XXX,XX +XXX,XX @@ struct XlnxVersalCFUAPB {
35
} cfg;
36
};
37
38
+
39
+struct XlnxVersalCFUFDRO {
40
+ SysBusDevice parent_obj;
41
+ MemoryRegion iomem_fdro;
42
+
43
+ Fifo32 fdro_data;
44
+};
45
+
46
/**
47
* This is a helper function for updating a CFI data write fifo, an array of 4
48
* uint32_t and 128 bits of data that are allowed to be written through 4
49
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/misc/xlnx-versal-cfu.c
52
+++ b/hw/misc/xlnx-versal-cfu.c
53
@@ -XXX,XX +XXX,XX @@ static void cfu_stream_write(void *opaque, hwaddr addr, uint64_t value,
54
}
55
}
56
57
+static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
58
+{
59
+ XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
60
+ uint64_t ret = 0;
61
+
62
+ if (!fifo32_is_empty(&s->fdro_data)) {
63
+ ret = fifo32_pop(&s->fdro_data);
64
+ }
65
+
66
+ return ret;
67
+}
68
+
69
+static void cfu_fdro_write(void *opaque, hwaddr addr, uint64_t value,
70
+ unsigned size)
71
+{
72
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported write from addr=%"
73
+ HWADDR_PRIx "\n", __func__, addr);
74
+}
75
+
76
static const MemoryRegionOps cfu_stream_ops = {
77
.read = cfu_stream_read,
78
.write = cfu_stream_write,
79
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps cfu_stream_ops = {
80
},
81
};
82
83
+static const MemoryRegionOps cfu_fdro_ops = {
84
+ .read = cfu_fdro_read,
85
+ .write = cfu_fdro_write,
86
+ .endianness = DEVICE_LITTLE_ENDIAN,
87
+ .valid = {
88
+ .min_access_size = 4,
89
+ .max_access_size = 4,
90
+ },
91
+};
92
+
93
static void cfu_apb_init(Object *obj)
94
{
95
XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
96
@@ -XXX,XX +XXX,XX @@ static void cfu_apb_init(Object *obj)
97
sysbus_init_irq(sbd, &s->irq_cfu_imr);
98
}
99
100
+static void cfu_fdro_init(Object *obj)
101
+{
102
+ XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
103
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
104
+
105
+ memory_region_init_io(&s->iomem_fdro, obj, &cfu_fdro_ops, s,
106
+ TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K);
107
+ sysbus_init_mmio(sbd, &s->iomem_fdro);
108
+ fifo32_create(&s->fdro_data, 8 * KiB / sizeof(uint32_t));
109
+}
110
+
111
+static void cfu_fdro_reset_enter(Object *obj, ResetType type)
112
+{
113
+ XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
114
+
115
+ fifo32_reset(&s->fdro_data);
116
+}
117
+
118
+static void cfu_fdro_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
119
+{
120
+ XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(cfi_if);
121
+
122
+ if (fifo32_num_free(&s->fdro_data) >= ARRAY_SIZE(pkt->data)) {
123
+ for (int i = 0; i < ARRAY_SIZE(pkt->data); i++) {
124
+ fifo32_push(&s->fdro_data, pkt->data[i]);
125
+ }
126
+ } else {
127
+ /* It is a programming error to fill the fifo. */
128
+ qemu_log_mask(LOG_GUEST_ERROR,
129
+ "CFU_FDRO: CFI data dropped due to full read fifo\n");
130
+ }
131
+}
132
+
133
static Property cfu_props[] = {
134
DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0],
135
TYPE_XLNX_CFI_IF, XlnxCfiIf *),
136
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_cfu_apb = {
137
}
138
};
139
140
+static const VMStateDescription vmstate_cfu_fdro = {
141
+ .name = TYPE_XLNX_VERSAL_CFU_FDRO,
142
+ .version_id = 1,
143
+ .minimum_version_id = 1,
144
+ .fields = (VMStateField[]) {
145
+ VMSTATE_FIFO32(fdro_data, XlnxVersalCFUFDRO),
146
+ VMSTATE_END_OF_LIST(),
147
+ }
148
+};
149
+
150
static void cfu_apb_class_init(ObjectClass *klass, void *data)
151
{
152
DeviceClass *dc = DEVICE_CLASS(klass);
153
@@ -XXX,XX +XXX,XX @@ static void cfu_apb_class_init(ObjectClass *klass, void *data)
154
device_class_set_props(dc, cfu_props);
155
}
156
157
+static void cfu_fdro_class_init(ObjectClass *klass, void *data)
158
+{
159
+ DeviceClass *dc = DEVICE_CLASS(klass);
160
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
161
+ XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass);
162
+
163
+ dc->vmsd = &vmstate_cfu_fdro;
164
+ xcic->cfi_transfer_packet = cfu_fdro_cfi_transfer_packet;
165
+ rc->phases.enter = cfu_fdro_reset_enter;
166
+}
167
+
168
static const TypeInfo cfu_apb_info = {
169
.name = TYPE_XLNX_VERSAL_CFU_APB,
170
.parent = TYPE_SYS_BUS_DEVICE,
171
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cfu_apb_info = {
172
}
173
};
174
175
+static const TypeInfo cfu_fdro_info = {
176
+ .name = TYPE_XLNX_VERSAL_CFU_FDRO,
177
+ .parent = TYPE_SYS_BUS_DEVICE,
178
+ .instance_size = sizeof(XlnxVersalCFUFDRO),
179
+ .class_init = cfu_fdro_class_init,
180
+ .instance_init = cfu_fdro_init,
181
+ .interfaces = (InterfaceInfo[]) {
182
+ { TYPE_XLNX_CFI_IF },
183
+ { }
184
+ }
185
+};
186
+
187
static void cfu_apb_register_types(void)
188
{
189
type_register_static(&cfu_apb_info);
190
+ type_register_static(&cfu_fdro_info);
191
}
192
193
type_init(cfu_apb_register_types)
194
--
195
2.34.1
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
1
2
3
Introduce a model of Xilinx Versal's Configuration Frame Unit's Single
4
Frame Read port (CFU_SFR).
5
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230831165701.2016397-5-francisco.iglesias@amd.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/misc/xlnx-versal-cfu.h | 15 ++++++
12
hw/misc/xlnx-versal-cfu.c | 87 +++++++++++++++++++++++++++++++
13
2 files changed, 102 insertions(+)
14
15
diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/xlnx-versal-cfu.h
18
+++ b/include/hw/misc/xlnx-versal-cfu.h
19
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, XLNX_VERSAL_CFU_APB)
20
#define TYPE_XLNX_VERSAL_CFU_FDRO "xlnx,versal-cfu-fdro"
21
OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUFDRO, XLNX_VERSAL_CFU_FDRO)
22
23
+#define TYPE_XLNX_VERSAL_CFU_SFR "xlnx,versal-cfu-sfr"
24
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUSFR, XLNX_VERSAL_CFU_SFR)
25
+
26
REG32(CFU_ISR, 0x0)
27
FIELD(CFU_ISR, USR_GTS_EVENT, 9, 1)
28
FIELD(CFU_ISR, USR_GSR_EVENT, 8, 1)
29
@@ -XXX,XX +XXX,XX @@ struct XlnxVersalCFUFDRO {
30
Fifo32 fdro_data;
31
};
32
33
+struct XlnxVersalCFUSFR {
34
+ SysBusDevice parent_obj;
35
+ MemoryRegion iomem_sfr;
36
+
37
+ /* 128-bit wfifo. */
38
+ uint32_t wfifo[WFIFO_SZ];
39
+
40
+ struct {
41
+ XlnxVersalCFUAPB *cfu;
42
+ } cfg;
43
+};
44
+
45
/**
46
* This is a helper function for updating a CFI data write fifo, an array of 4
47
* uint32_t and 128 bits of data that are allowed to be written through 4
48
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/misc/xlnx-versal-cfu.c
51
+++ b/hw/misc/xlnx-versal-cfu.c
52
@@ -XXX,XX +XXX,XX @@ static void cfu_stream_write(void *opaque, hwaddr addr, uint64_t value,
53
}
54
}
55
56
+static uint64_t cfu_sfr_read(void *opaque, hwaddr addr, unsigned size)
57
+{
58
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
59
+ HWADDR_PRIx "\n", __func__, addr);
60
+ return 0;
61
+}
62
+
63
+static void cfu_sfr_write(void *opaque, hwaddr addr, uint64_t value,
64
+ unsigned size)
65
+{
66
+ XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(opaque);
67
+ uint32_t wfifo[WFIFO_SZ];
68
+
69
+ if (update_wfifo(addr, value, s->wfifo, wfifo)) {
70
+ uint8_t row_addr = extract32(wfifo[0], 23, 5);
71
+ uint32_t frame_addr = extract32(wfifo[0], 0, 23);
72
+ XlnxCfiPacket pkt = { .reg_addr = CFRAME_SFR,
73
+ .data[0] = frame_addr };
74
+
75
+ if (s->cfg.cfu) {
76
+ cfu_transfer_cfi_packet(s->cfg.cfu, row_addr, &pkt);
77
+ }
78
+ }
79
+}
80
+
81
static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
82
{
83
XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
84
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps cfu_stream_ops = {
85
},
86
};
87
88
+static const MemoryRegionOps cfu_sfr_ops = {
89
+ .read = cfu_sfr_read,
90
+ .write = cfu_sfr_write,
91
+ .endianness = DEVICE_LITTLE_ENDIAN,
92
+ .valid = {
93
+ .min_access_size = 4,
94
+ .max_access_size = 4,
95
+ },
96
+};
97
+
98
static const MemoryRegionOps cfu_fdro_ops = {
99
.read = cfu_fdro_read,
100
.write = cfu_fdro_write,
101
@@ -XXX,XX +XXX,XX @@ static void cfu_apb_init(Object *obj)
102
sysbus_init_irq(sbd, &s->irq_cfu_imr);
103
}
104
105
+static void cfu_sfr_init(Object *obj)
106
+{
107
+ XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
109
+
110
+ memory_region_init_io(&s->iomem_sfr, obj, &cfu_sfr_ops, s,
111
+ TYPE_XLNX_VERSAL_CFU_SFR, KEYHOLE_STREAM_4K);
112
+ sysbus_init_mmio(sbd, &s->iomem_sfr);
113
+}
114
+
115
+static void cfu_sfr_reset_enter(Object *obj, ResetType type)
116
+{
117
+ XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
118
+
119
+ memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
120
+}
121
+
122
static void cfu_fdro_init(Object *obj)
123
{
124
XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
125
@@ -XXX,XX +XXX,XX @@ static Property cfu_props[] = {
126
DEFINE_PROP_END_OF_LIST(),
127
};
128
129
+static Property cfu_sfr_props[] = {
130
+ DEFINE_PROP_LINK("cfu", XlnxVersalCFUSFR, cfg.cfu,
131
+ TYPE_XLNX_VERSAL_CFU_APB, XlnxVersalCFUAPB *),
132
+ DEFINE_PROP_END_OF_LIST(),
133
+};
134
+
135
static const VMStateDescription vmstate_cfu_apb = {
136
.name = TYPE_XLNX_VERSAL_CFU_APB,
137
.version_id = 1,
138
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_cfu_fdro = {
139
}
140
};
141
142
+static const VMStateDescription vmstate_cfu_sfr = {
143
+ .name = TYPE_XLNX_VERSAL_CFU_SFR,
144
+ .version_id = 1,
145
+ .minimum_version_id = 1,
146
+ .fields = (VMStateField[]) {
147
+ VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFUSFR, 4),
148
+ VMSTATE_END_OF_LIST(),
149
+ }
150
+};
151
+
152
static void cfu_apb_class_init(ObjectClass *klass, void *data)
153
{
154
DeviceClass *dc = DEVICE_CLASS(klass);
155
@@ -XXX,XX +XXX,XX @@ static void cfu_fdro_class_init(ObjectClass *klass, void *data)
156
rc->phases.enter = cfu_fdro_reset_enter;
157
}
158
159
+static void cfu_sfr_class_init(ObjectClass *klass, void *data)
160
+{
161
+ DeviceClass *dc = DEVICE_CLASS(klass);
162
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
163
+
164
+ device_class_set_props(dc, cfu_sfr_props);
165
+ dc->vmsd = &vmstate_cfu_sfr;
166
+ rc->phases.enter = cfu_sfr_reset_enter;
167
+}
168
+
169
static const TypeInfo cfu_apb_info = {
170
.name = TYPE_XLNX_VERSAL_CFU_APB,
171
.parent = TYPE_SYS_BUS_DEVICE,
172
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cfu_fdro_info = {
173
}
174
};
175
176
+static const TypeInfo cfu_sfr_info = {
177
+ .name = TYPE_XLNX_VERSAL_CFU_SFR,
178
+ .parent = TYPE_SYS_BUS_DEVICE,
179
+ .instance_size = sizeof(XlnxVersalCFUSFR),
180
+ .class_init = cfu_sfr_class_init,
181
+ .instance_init = cfu_sfr_init,
182
+};
183
+
184
static void cfu_apb_register_types(void)
185
{
186
type_register_static(&cfu_apb_info);
187
type_register_static(&cfu_fdro_info);
188
+ type_register_static(&cfu_sfr_info);
189
}
190
191
type_init(cfu_apb_register_types)
192
--
193
2.34.1
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
1
2
3
Introduce a model of Xilinx Versal's Configuration Frame controller
4
(CFRAME_REG).
5
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Message-id: 20230831165701.2016397-6-francisco.iglesias@amd.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
MAINTAINERS | 2 +
12
include/hw/misc/xlnx-versal-cframe-reg.h | 286 ++++++++++
13
hw/misc/xlnx-versal-cframe-reg.c | 697 +++++++++++++++++++++++
14
hw/misc/meson.build | 1 +
15
4 files changed, 986 insertions(+)
16
create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h
17
create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
18
19
diff --git a/MAINTAINERS b/MAINTAINERS
20
index XXXXXXX..XXXXXXX 100644
21
--- a/MAINTAINERS
22
+++ b/MAINTAINERS
23
@@ -XXX,XX +XXX,XX @@ F: hw/misc/xlnx-cfi-if.c
24
F: include/hw/misc/xlnx-cfi-if.h
25
F: hw/misc/xlnx-versal-cfu.c
26
F: include/hw/misc/xlnx-versal-cfu.h
27
+F: hw/misc/xlnx-versal-cframe-reg.c
28
+F: include/hw/misc/xlnx-versal-cframe-reg.h
29
30
STM32F100
31
M: Alexandre Iooss <erdnaxe@crans.org>
32
diff --git a/include/hw/misc/xlnx-versal-cframe-reg.h b/include/hw/misc/xlnx-versal-cframe-reg.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/xlnx-versal-cframe-reg.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * QEMU model of the Configuration Frame Control module
40
+ *
41
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
42
+ *
43
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
44
+ *
45
+ * SPDX-License-Identifier: GPL-2.0-or-later
46
+ *
47
+ * References:
48
+ * [1] Versal ACAP Technical Reference Manual,
49
+ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
50
+ *
51
+ * [2] Versal ACAP Register Reference,
52
+ * https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html
53
+ */
54
+#ifndef HW_MISC_XLNX_VERSAL_CFRAME_REG_H
55
+#define HW_MISC_XLNX_VERSAL_CFRAME_REG_H
56
+
57
+#include "hw/sysbus.h"
58
+#include "hw/register.h"
59
+#include "hw/misc/xlnx-cfi-if.h"
60
+#include "hw/misc/xlnx-versal-cfu.h"
61
+#include "qemu/fifo32.h"
62
+
63
+#define TYPE_XLNX_VERSAL_CFRAME_REG "xlnx,cframe-reg"
64
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFrameReg, XLNX_VERSAL_CFRAME_REG)
65
+
66
+/*
67
+ * The registers in this module are 128 bits wide but it is ok to write
68
+ * and read them through 4 sequential 32 bit accesses (address[3:2] = 0,
69
+ * 1, 2, 3).
70
+ */
71
+REG32(CRC0, 0x0)
72
+ FIELD(CRC, CRC, 0, 32)
73
+REG32(CRC1, 0x4)
74
+REG32(CRC2, 0x8)
75
+REG32(CRC3, 0xc)
76
+REG32(FAR0, 0x10)
77
+ FIELD(FAR0, SEGMENT, 23, 2)
78
+ FIELD(FAR0, BLOCKTYPE, 20, 3)
79
+ FIELD(FAR0, FRAME_ADDR, 0, 20)
80
+REG32(FAR1, 0x14)
81
+REG32(FAR2, 0x18)
82
+REG32(FAR3, 0x1c)
83
+REG32(FAR_SFR0, 0x20)
84
+ FIELD(FAR_SFR0, BLOCKTYPE, 20, 3)
85
+ FIELD(FAR_SFR0, FRAME_ADDR, 0, 20)
86
+REG32(FAR_SFR1, 0x24)
87
+REG32(FAR_SFR2, 0x28)
88
+REG32(FAR_SFR3, 0x2c)
89
+REG32(FDRI0, 0x40)
90
+REG32(FDRI1, 0x44)
91
+REG32(FDRI2, 0x48)
92
+REG32(FDRI3, 0x4c)
93
+REG32(FRCNT0, 0x50)
94
+ FIELD(FRCNT0, FRCNT, 0, 32)
95
+REG32(FRCNT1, 0x54)
96
+REG32(FRCNT2, 0x58)
97
+REG32(FRCNT3, 0x5c)
98
+REG32(CMD0, 0x60)
99
+ FIELD(CMD0, CMD, 0, 5)
100
+REG32(CMD1, 0x64)
101
+REG32(CMD2, 0x68)
102
+REG32(CMD3, 0x6c)
103
+REG32(CR_MASK0, 0x70)
104
+REG32(CR_MASK1, 0x74)
105
+REG32(CR_MASK2, 0x78)
106
+REG32(CR_MASK3, 0x7c)
107
+REG32(CTL0, 0x80)
108
+ FIELD(CTL, PER_FRAME_CRC, 0, 1)
109
+REG32(CTL1, 0x84)
110
+REG32(CTL2, 0x88)
111
+REG32(CTL3, 0x8c)
112
+REG32(CFRM_ISR0, 0x150)
113
+ FIELD(CFRM_ISR0, READ_BROADCAST_ERROR, 21, 1)
114
+ FIELD(CFRM_ISR0, CMD_MISSING_ERROR, 20, 1)
115
+ FIELD(CFRM_ISR0, RW_ROWOFF_ERROR, 19, 1)
116
+ FIELD(CFRM_ISR0, READ_REG_ADDR_ERROR, 18, 1)
117
+ FIELD(CFRM_ISR0, READ_BLK_TYPE_ERROR, 17, 1)
118
+ FIELD(CFRM_ISR0, READ_FRAME_ADDR_ERROR, 16, 1)
119
+ FIELD(CFRM_ISR0, WRITE_REG_ADDR_ERROR, 15, 1)
120
+ FIELD(CFRM_ISR0, WRITE_BLK_TYPE_ERROR, 13, 1)
121
+ FIELD(CFRM_ISR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
122
+ FIELD(CFRM_ISR0, MFW_OVERRUN_ERROR, 11, 1)
123
+ FIELD(CFRM_ISR0, FAR_FIFO_UNDERFLOW, 10, 1)
124
+ FIELD(CFRM_ISR0, FAR_FIFO_OVERFLOW, 9, 1)
125
+ FIELD(CFRM_ISR0, PER_FRAME_SEQ_ERROR, 8, 1)
126
+ FIELD(CFRM_ISR0, CRC_ERROR, 7, 1)
127
+ FIELD(CFRM_ISR0, WRITE_OVERRUN_ERROR, 6, 1)
128
+ FIELD(CFRM_ISR0, READ_OVERRUN_ERROR, 5, 1)
129
+ FIELD(CFRM_ISR0, CMD_INTERRUPT_ERROR, 4, 1)
130
+ FIELD(CFRM_ISR0, WRITE_INTERRUPT_ERROR, 3, 1)
131
+ FIELD(CFRM_ISR0, READ_INTERRUPT_ERROR, 2, 1)
132
+ FIELD(CFRM_ISR0, SEU_CRC_ERROR, 1, 1)
133
+ FIELD(CFRM_ISR0, SEU_ECC_ERROR, 0, 1)
134
+REG32(CFRM_ISR1, 0x154)
135
+REG32(CFRM_ISR2, 0x158)
136
+REG32(CFRM_ISR3, 0x15c)
137
+REG32(CFRM_IMR0, 0x160)
138
+ FIELD(CFRM_IMR0, READ_BROADCAST_ERROR, 21, 1)
139
+ FIELD(CFRM_IMR0, CMD_MISSING_ERROR, 20, 1)
140
+ FIELD(CFRM_IMR0, RW_ROWOFF_ERROR, 19, 1)
141
+ FIELD(CFRM_IMR0, READ_REG_ADDR_ERROR, 18, 1)
142
+ FIELD(CFRM_IMR0, READ_BLK_TYPE_ERROR, 17, 1)
143
+ FIELD(CFRM_IMR0, READ_FRAME_ADDR_ERROR, 16, 1)
144
+ FIELD(CFRM_IMR0, WRITE_REG_ADDR_ERROR, 15, 1)
145
+ FIELD(CFRM_IMR0, WRITE_BLK_TYPE_ERROR, 13, 1)
146
+ FIELD(CFRM_IMR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
147
+ FIELD(CFRM_IMR0, MFW_OVERRUN_ERROR, 11, 1)
148
+ FIELD(CFRM_IMR0, FAR_FIFO_UNDERFLOW, 10, 1)
149
+ FIELD(CFRM_IMR0, FAR_FIFO_OVERFLOW, 9, 1)
150
+ FIELD(CFRM_IMR0, PER_FRAME_SEQ_ERROR, 8, 1)
151
+ FIELD(CFRM_IMR0, CRC_ERROR, 7, 1)
152
+ FIELD(CFRM_IMR0, WRITE_OVERRUN_ERROR, 6, 1)
153
+ FIELD(CFRM_IMR0, READ_OVERRUN_ERROR, 5, 1)
154
+ FIELD(CFRM_IMR0, CMD_INTERRUPT_ERROR, 4, 1)
155
+ FIELD(CFRM_IMR0, WRITE_INTERRUPT_ERROR, 3, 1)
156
+ FIELD(CFRM_IMR0, READ_INTERRUPT_ERROR, 2, 1)
157
+ FIELD(CFRM_IMR0, SEU_CRC_ERROR, 1, 1)
158
+ FIELD(CFRM_IMR0, SEU_ECC_ERROR, 0, 1)
159
+REG32(CFRM_IMR1, 0x164)
160
+REG32(CFRM_IMR2, 0x168)
161
+REG32(CFRM_IMR3, 0x16c)
162
+REG32(CFRM_IER0, 0x170)
163
+ FIELD(CFRM_IER0, READ_BROADCAST_ERROR, 21, 1)
164
+ FIELD(CFRM_IER0, CMD_MISSING_ERROR, 20, 1)
165
+ FIELD(CFRM_IER0, RW_ROWOFF_ERROR, 19, 1)
166
+ FIELD(CFRM_IER0, READ_REG_ADDR_ERROR, 18, 1)
167
+ FIELD(CFRM_IER0, READ_BLK_TYPE_ERROR, 17, 1)
168
+ FIELD(CFRM_IER0, READ_FRAME_ADDR_ERROR, 16, 1)
169
+ FIELD(CFRM_IER0, WRITE_REG_ADDR_ERROR, 15, 1)
170
+ FIELD(CFRM_IER0, WRITE_BLK_TYPE_ERROR, 13, 1)
171
+ FIELD(CFRM_IER0, WRITE_FRAME_ADDR_ERROR, 12, 1)
172
+ FIELD(CFRM_IER0, MFW_OVERRUN_ERROR, 11, 1)
173
+ FIELD(CFRM_IER0, FAR_FIFO_UNDERFLOW, 10, 1)
174
+ FIELD(CFRM_IER0, FAR_FIFO_OVERFLOW, 9, 1)
175
+ FIELD(CFRM_IER0, PER_FRAME_SEQ_ERROR, 8, 1)
176
+ FIELD(CFRM_IER0, CRC_ERROR, 7, 1)
177
+ FIELD(CFRM_IER0, WRITE_OVERRUN_ERROR, 6, 1)
178
+ FIELD(CFRM_IER0, READ_OVERRUN_ERROR, 5, 1)
179
+ FIELD(CFRM_IER0, CMD_INTERRUPT_ERROR, 4, 1)
180
+ FIELD(CFRM_IER0, WRITE_INTERRUPT_ERROR, 3, 1)
181
+ FIELD(CFRM_IER0, READ_INTERRUPT_ERROR, 2, 1)
182
+ FIELD(CFRM_IER0, SEU_CRC_ERROR, 1, 1)
183
+ FIELD(CFRM_IER0, SEU_ECC_ERROR, 0, 1)
184
+REG32(CFRM_IER1, 0x174)
185
+REG32(CFRM_IER2, 0x178)
186
+REG32(CFRM_IER3, 0x17c)
187
+REG32(CFRM_IDR0, 0x180)
188
+ FIELD(CFRM_IDR0, READ_BROADCAST_ERROR, 21, 1)
189
+ FIELD(CFRM_IDR0, CMD_MISSING_ERROR, 20, 1)
190
+ FIELD(CFRM_IDR0, RW_ROWOFF_ERROR, 19, 1)
191
+ FIELD(CFRM_IDR0, READ_REG_ADDR_ERROR, 18, 1)
192
+ FIELD(CFRM_IDR0, READ_BLK_TYPE_ERROR, 17, 1)
193
+ FIELD(CFRM_IDR0, READ_FRAME_ADDR_ERROR, 16, 1)
194
+ FIELD(CFRM_IDR0, WRITE_REG_ADDR_ERROR, 15, 1)
195
+ FIELD(CFRM_IDR0, WRITE_BLK_TYPE_ERROR, 13, 1)
196
+ FIELD(CFRM_IDR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
197
+ FIELD(CFRM_IDR0, MFW_OVERRUN_ERROR, 11, 1)
198
+ FIELD(CFRM_IDR0, FAR_FIFO_UNDERFLOW, 10, 1)
199
+ FIELD(CFRM_IDR0, FAR_FIFO_OVERFLOW, 9, 1)
200
+ FIELD(CFRM_IDR0, PER_FRAME_SEQ_ERROR, 8, 1)
201
+ FIELD(CFRM_IDR0, CRC_ERROR, 7, 1)
202
+ FIELD(CFRM_IDR0, WRITE_OVERRUN_ERROR, 6, 1)
203
+ FIELD(CFRM_IDR0, READ_OVERRUN_ERROR, 5, 1)
204
+ FIELD(CFRM_IDR0, CMD_INTERRUPT_ERROR, 4, 1)
205
+ FIELD(CFRM_IDR0, WRITE_INTERRUPT_ERROR, 3, 1)
206
+ FIELD(CFRM_IDR0, READ_INTERRUPT_ERROR, 2, 1)
207
+ FIELD(CFRM_IDR0, SEU_CRC_ERROR, 1, 1)
208
+ FIELD(CFRM_IDR0, SEU_ECC_ERROR, 0, 1)
209
+REG32(CFRM_IDR1, 0x184)
210
+REG32(CFRM_IDR2, 0x188)
211
+REG32(CFRM_IDR3, 0x18c)
212
+REG32(CFRM_ITR0, 0x190)
213
+ FIELD(CFRM_ITR0, READ_BROADCAST_ERROR, 21, 1)
214
+ FIELD(CFRM_ITR0, CMD_MISSING_ERROR, 20, 1)
215
+ FIELD(CFRM_ITR0, RW_ROWOFF_ERROR, 19, 1)
216
+ FIELD(CFRM_ITR0, READ_REG_ADDR_ERROR, 18, 1)
217
+ FIELD(CFRM_ITR0, READ_BLK_TYPE_ERROR, 17, 1)
218
+ FIELD(CFRM_ITR0, READ_FRAME_ADDR_ERROR, 16, 1)
219
+ FIELD(CFRM_ITR0, WRITE_REG_ADDR_ERROR, 15, 1)
220
+ FIELD(CFRM_ITR0, WRITE_BLK_TYPE_ERROR, 13, 1)
221
+ FIELD(CFRM_ITR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
222
+ FIELD(CFRM_ITR0, MFW_OVERRUN_ERROR, 11, 1)
223
+ FIELD(CFRM_ITR0, FAR_FIFO_UNDERFLOW, 10, 1)
224
+ FIELD(CFRM_ITR0, FAR_FIFO_OVERFLOW, 9, 1)
225
+ FIELD(CFRM_ITR0, PER_FRAME_SEQ_ERROR, 8, 1)
226
+ FIELD(CFRM_ITR0, CRC_ERROR, 7, 1)
227
+ FIELD(CFRM_ITR0, WRITE_OVERRUN_ERROR, 6, 1)
228
+ FIELD(CFRM_ITR0, READ_OVERRUN_ERROR, 5, 1)
229
+ FIELD(CFRM_ITR0, CMD_INTERRUPT_ERROR, 4, 1)
230
+ FIELD(CFRM_ITR0, WRITE_INTERRUPT_ERROR, 3, 1)
231
+ FIELD(CFRM_ITR0, READ_INTERRUPT_ERROR, 2, 1)
232
+ FIELD(CFRM_ITR0, SEU_CRC_ERROR, 1, 1)
233
+ FIELD(CFRM_ITR0, SEU_ECC_ERROR, 0, 1)
234
+REG32(CFRM_ITR1, 0x194)
235
+REG32(CFRM_ITR2, 0x198)
236
+REG32(CFRM_ITR3, 0x19c)
237
+REG32(SEU_SYNDRM00, 0x1a0)
238
+REG32(SEU_SYNDRM01, 0x1a4)
239
+REG32(SEU_SYNDRM02, 0x1a8)
240
+REG32(SEU_SYNDRM03, 0x1ac)
241
+REG32(SEU_SYNDRM10, 0x1b0)
242
+REG32(SEU_SYNDRM11, 0x1b4)
243
+REG32(SEU_SYNDRM12, 0x1b8)
244
+REG32(SEU_SYNDRM13, 0x1bc)
245
+REG32(SEU_SYNDRM20, 0x1c0)
246
+REG32(SEU_SYNDRM21, 0x1c4)
247
+REG32(SEU_SYNDRM22, 0x1c8)
248
+REG32(SEU_SYNDRM23, 0x1cc)
249
+REG32(SEU_SYNDRM30, 0x1d0)
250
+REG32(SEU_SYNDRM31, 0x1d4)
251
+REG32(SEU_SYNDRM32, 0x1d8)
252
+REG32(SEU_SYNDRM33, 0x1dc)
253
+REG32(SEU_VIRTUAL_SYNDRM0, 0x1e0)
254
+REG32(SEU_VIRTUAL_SYNDRM1, 0x1e4)
255
+REG32(SEU_VIRTUAL_SYNDRM2, 0x1e8)
256
+REG32(SEU_VIRTUAL_SYNDRM3, 0x1ec)
257
+REG32(SEU_CRC0, 0x1f0)
258
+REG32(SEU_CRC1, 0x1f4)
259
+REG32(SEU_CRC2, 0x1f8)
260
+REG32(SEU_CRC3, 0x1fc)
261
+REG32(CFRAME_FAR_BOT0, 0x200)
262
+REG32(CFRAME_FAR_BOT1, 0x204)
263
+REG32(CFRAME_FAR_BOT2, 0x208)
264
+REG32(CFRAME_FAR_BOT3, 0x20c)
265
+REG32(CFRAME_FAR_TOP0, 0x210)
266
+REG32(CFRAME_FAR_TOP1, 0x214)
267
+REG32(CFRAME_FAR_TOP2, 0x218)
268
+REG32(CFRAME_FAR_TOP3, 0x21c)
269
+REG32(LAST_FRAME_BOT0, 0x220)
270
+ FIELD(LAST_FRAME_BOT0, BLOCKTYPE1_LAST_FRAME_LSB, 20, 12)
271
+ FIELD(LAST_FRAME_BOT0, BLOCKTYPE0_LAST_FRAME, 0, 20)
272
+REG32(LAST_FRAME_BOT1, 0x224)
273
+ FIELD(LAST_FRAME_BOT1, BLOCKTYPE3_LAST_FRAME_LSB, 28, 4)
274
+ FIELD(LAST_FRAME_BOT1, BLOCKTYPE2_LAST_FRAME, 8, 20)
275
+ FIELD(LAST_FRAME_BOT1, BLOCKTYPE1_LAST_FRAME_MSB, 0, 8)
276
+REG32(LAST_FRAME_BOT2, 0x228)
277
+ FIELD(LAST_FRAME_BOT2, BLOCKTYPE3_LAST_FRAME_MSB, 0, 16)
278
+REG32(LAST_FRAME_BOT3, 0x22c)
279
+REG32(LAST_FRAME_TOP0, 0x230)
280
+ FIELD(LAST_FRAME_TOP0, BLOCKTYPE5_LAST_FRAME_LSB, 20, 12)
281
+ FIELD(LAST_FRAME_TOP0, BLOCKTYPE4_LAST_FRAME, 0, 20)
282
+REG32(LAST_FRAME_TOP1, 0x234)
283
+ FIELD(LAST_FRAME_TOP1, BLOCKTYPE6_LAST_FRAME, 8, 20)
284
+ FIELD(LAST_FRAME_TOP1, BLOCKTYPE5_LAST_FRAME_MSB, 0, 8)
285
+REG32(LAST_FRAME_TOP2, 0x238)
286
+REG32(LAST_FRAME_TOP3, 0x23c)
287
+
288
+#define CFRAME_REG_R_MAX (R_LAST_FRAME_TOP3 + 1)
289
+
290
+#define FRAME_NUM_QWORDS 25
291
+#define FRAME_NUM_WORDS (FRAME_NUM_QWORDS * 4) /* 25 * 128 bits */
292
+
293
+typedef struct XlnxCFrame {
294
+ uint32_t data[FRAME_NUM_WORDS];
295
+} XlnxCFrame;
296
+
297
+struct XlnxVersalCFrameReg {
298
+ SysBusDevice parent_obj;
299
+ MemoryRegion iomem;
300
+ MemoryRegion iomem_fdri;
301
+ qemu_irq irq_cfrm_imr;
302
+
303
+ /* 128-bit wfifo. */
304
+ uint32_t wfifo[WFIFO_SZ];
305
+
306
+ uint32_t regs[CFRAME_REG_R_MAX];
307
+ RegisterInfo regs_info[CFRAME_REG_R_MAX];
308
+
309
+ bool rowon;
310
+ bool wcfg;
311
+ bool rcfg;
312
+
313
+ GTree *cframes;
314
+ Fifo32 new_f_data;
315
+
316
+ struct {
317
+ XlnxCfiIf *cfu_fdro;
318
+ uint32_t blktype_num_frames[7];
319
+ } cfg;
320
+ bool row_configured;
321
+};
322
+
323
+#endif
324
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
325
new file mode 100644
326
index XXXXXXX..XXXXXXX
327
--- /dev/null
328
+++ b/hw/misc/xlnx-versal-cframe-reg.c
329
@@ -XXX,XX +XXX,XX @@
330
+/*
331
+ * QEMU model of the Configuration Frame Control module
332
+ *
333
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
334
+ *
335
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
336
+ *
337
+ * SPDX-License-Identifier: GPL-2.0-or-later
338
+ */
339
+
340
+#include "qemu/osdep.h"
341
+#include "hw/sysbus.h"
342
+#include "hw/register.h"
343
+#include "hw/registerfields.h"
344
+#include "qemu/bitops.h"
345
+#include "qemu/log.h"
346
+#include "qemu/units.h"
347
+#include "qapi/error.h"
348
+#include "hw/qdev-properties.h"
349
+#include "migration/vmstate.h"
350
+#include "hw/irq.h"
351
+#include "hw/misc/xlnx-versal-cframe-reg.h"
352
+
353
+#ifndef XLNX_VERSAL_CFRAME_REG_ERR_DEBUG
354
+#define XLNX_VERSAL_CFRAME_REG_ERR_DEBUG 0
355
+#endif
356
+
357
+#define KEYHOLE_STREAM_4K (4 * KiB)
358
+#define N_WORDS_128BIT 4
359
+
360
+#define MAX_BLOCKTYPE 6
361
+#define MAX_BLOCKTYPE_FRAMES 0xFFFFF
362
+
363
+enum {
364
+ CFRAME_CMD_WCFG = 1,
365
+ CFRAME_CMD_ROWON = 2,
366
+ CFRAME_CMD_ROWOFF = 3,
367
+ CFRAME_CMD_RCFG = 4,
368
+ CFRAME_CMD_DLPARK = 5,
369
+};
370
+
371
+static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
372
+{
373
+ guint ua = GPOINTER_TO_UINT(a);
374
+ guint ub = GPOINTER_TO_UINT(b);
375
+ return (ua > ub) - (ua < ub);
376
+}
377
+
378
+static void cfrm_imr_update_irq(XlnxVersalCFrameReg *s)
379
+{
380
+ bool pending = s->regs[R_CFRM_ISR0] & ~s->regs[R_CFRM_IMR0];
381
+ qemu_set_irq(s->irq_cfrm_imr, pending);
382
+}
383
+
384
+static void cfrm_isr_postw(RegisterInfo *reg, uint64_t val64)
385
+{
386
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
387
+ cfrm_imr_update_irq(s);
388
+}
389
+
390
+static uint64_t cfrm_ier_prew(RegisterInfo *reg, uint64_t val64)
391
+{
392
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
393
+
394
+ s->regs[R_CFRM_IMR0] &= ~s->regs[R_CFRM_IER0];
395
+ s->regs[R_CFRM_IER0] = 0;
396
+ cfrm_imr_update_irq(s);
397
+ return 0;
398
+}
399
+
400
+static uint64_t cfrm_idr_prew(RegisterInfo *reg, uint64_t val64)
401
+{
402
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
403
+
404
+ s->regs[R_CFRM_IMR0] |= s->regs[R_CFRM_IDR0];
405
+ s->regs[R_CFRM_IDR0] = 0;
406
+ cfrm_imr_update_irq(s);
407
+ return 0;
408
+}
409
+
410
+static uint64_t cfrm_itr_prew(RegisterInfo *reg, uint64_t val64)
411
+{
412
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
413
+
414
+ s->regs[R_CFRM_ISR0] |= s->regs[R_CFRM_ITR0];
415
+ s->regs[R_CFRM_ITR0] = 0;
416
+ cfrm_imr_update_irq(s);
417
+ return 0;
418
+}
419
+
420
+static void cframe_incr_far(XlnxVersalCFrameReg *s)
421
+{
422
+ uint32_t faddr = ARRAY_FIELD_EX32(s->regs, FAR0, FRAME_ADDR);
423
+ uint32_t blktype = ARRAY_FIELD_EX32(s->regs, FAR0, BLOCKTYPE);
424
+
425
+ assert(blktype <= MAX_BLOCKTYPE);
426
+
427
+ faddr++;
428
+ if (faddr > s->cfg.blktype_num_frames[blktype]) {
429
+ /* Restart from 0 and increment block type */
430
+ faddr = 0;
431
+ blktype++;
432
+
433
+ assert(blktype <= MAX_BLOCKTYPE);
434
+
435
+ ARRAY_FIELD_DP32(s->regs, FAR0, BLOCKTYPE, blktype);
436
+ }
437
+
438
+ ARRAY_FIELD_DP32(s->regs, FAR0, FRAME_ADDR, faddr);
439
+}
440
+
441
+static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val)
442
+{
443
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
444
+
445
+ if (s->row_configured && s->rowon && s->wcfg) {
446
+
447
+ if (fifo32_num_free(&s->new_f_data) >= N_WORDS_128BIT) {
448
+ fifo32_push(&s->new_f_data, s->regs[R_FDRI0]);
449
+ fifo32_push(&s->new_f_data, s->regs[R_FDRI1]);
450
+ fifo32_push(&s->new_f_data, s->regs[R_FDRI2]);
451
+ fifo32_push(&s->new_f_data, s->regs[R_FDRI3]);
452
+ }
453
+
454
+ if (fifo32_is_full(&s->new_f_data)) {
455
+ uint32_t addr = extract32(s->regs[R_FAR0], 0, 23);
456
+ XlnxCFrame *f = g_new(XlnxCFrame, 1);
457
+
458
+ for (int i = 0; i < FRAME_NUM_WORDS; i++) {
459
+ f->data[i] = fifo32_pop(&s->new_f_data);
460
+ }
461
+
462
+ g_tree_replace(s->cframes, GUINT_TO_POINTER(addr), f);
463
+
464
+ cframe_incr_far(s);
465
+
466
+ fifo32_reset(&s->new_f_data);
467
+ }
468
+ }
469
+}
470
+
471
+static void cfrm_readout_frames(XlnxVersalCFrameReg *s, uint32_t start_addr,
472
+ uint32_t end_addr)
473
+{
474
+ /*
475
+ * NB: when our minimum glib version is at least 2.68 we can improve the
476
+ * performance of the cframe traversal by using g_tree_lookup_node and
477
+ * g_tree_node_next (instead of calling g_tree_lookup for finding each
478
+ * cframe).
479
+ */
480
+ for (uint32_t addr = start_addr; addr < end_addr; addr++) {
481
+ XlnxCFrame *f = g_tree_lookup(s->cframes, GUINT_TO_POINTER(addr));
482
+
483
+ /* Transmit the data if a frame was found */
484
+ if (f) {
485
+ for (int i = 0; i < FRAME_NUM_WORDS; i += 4) {
486
+ XlnxCfiPacket pkt = {};
487
+
488
+ pkt.data[0] = f->data[i];
489
+ pkt.data[1] = f->data[i + 1];
490
+ pkt.data[2] = f->data[i + 2];
491
+ pkt.data[3] = f->data[i + 3];
492
+
493
+ if (s->cfg.cfu_fdro) {
494
+ xlnx_cfi_transfer_packet(s->cfg.cfu_fdro, &pkt);
495
+ }
496
+ }
497
+ }
498
+ }
499
+}
500
+
501
+static void cfrm_frcnt_post_write(RegisterInfo *reg, uint64_t val)
502
+{
503
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
504
+
505
+ if (s->row_configured && s->rowon && s->rcfg) {
506
+ uint32_t start_addr = extract32(s->regs[R_FAR0], 0, 23);
507
+ uint32_t end_addr = start_addr + s->regs[R_FRCNT0] / FRAME_NUM_QWORDS;
508
+
509
+ cfrm_readout_frames(s, start_addr, end_addr);
510
+ }
511
+}
512
+
513
+static void cfrm_cmd_post_write(RegisterInfo *reg, uint64_t val)
514
+{
515
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
516
+
517
+ if (s->row_configured) {
518
+ uint8_t cmd = ARRAY_FIELD_EX32(s->regs, CMD0, CMD);
519
+
520
+ switch (cmd) {
521
+ case CFRAME_CMD_WCFG:
522
+ s->wcfg = true;
523
+ break;
524
+ case CFRAME_CMD_ROWON:
525
+ s->rowon = true;
526
+ break;
527
+ case CFRAME_CMD_ROWOFF:
528
+ s->rowon = false;
529
+ break;
530
+ case CFRAME_CMD_RCFG:
531
+ s->rcfg = true;
532
+ break;
533
+ case CFRAME_CMD_DLPARK:
534
+ s->wcfg = false;
535
+ s->rcfg = false;
536
+ break;
537
+ default:
538
+ break;
539
+ };
540
+ }
541
+}
542
+
543
+static uint64_t cfrm_last_frame_bot_post_read(RegisterInfo *reg,
544
+ uint64_t val64)
545
+{
546
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
547
+ uint64_t val = 0;
548
+
549
+ switch (reg->access->addr) {
550
+ case A_LAST_FRAME_BOT0:
551
+ val = FIELD_DP32(val, LAST_FRAME_BOT0, BLOCKTYPE1_LAST_FRAME_LSB,
552
+ s->cfg.blktype_num_frames[1]);
553
+ val = FIELD_DP32(val, LAST_FRAME_BOT0, BLOCKTYPE0_LAST_FRAME,
554
+ s->cfg.blktype_num_frames[0]);
555
+ break;
556
+ case A_LAST_FRAME_BOT1:
557
+ val = FIELD_DP32(val, LAST_FRAME_BOT1, BLOCKTYPE3_LAST_FRAME_LSB,
558
+ s->cfg.blktype_num_frames[3]);
559
+ val = FIELD_DP32(val, LAST_FRAME_BOT1, BLOCKTYPE2_LAST_FRAME,
560
+ s->cfg.blktype_num_frames[2]);
561
+ val = FIELD_DP32(val, LAST_FRAME_BOT1, BLOCKTYPE1_LAST_FRAME_MSB,
562
+ (s->cfg.blktype_num_frames[1] >> 12));
563
+ break;
564
+ case A_LAST_FRAME_BOT2:
565
+ val = FIELD_DP32(val, LAST_FRAME_BOT2, BLOCKTYPE3_LAST_FRAME_MSB,
566
+ (s->cfg.blktype_num_frames[3] >> 4));
567
+ break;
568
+ case A_LAST_FRAME_BOT3:
569
+ default:
570
+ break;
571
+ }
572
+
573
+ return val;
574
+}
575
+
576
+static uint64_t cfrm_last_frame_top_post_read(RegisterInfo *reg,
577
+ uint64_t val64)
578
+{
579
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
580
+ uint64_t val = 0;
581
+
582
+ switch (reg->access->addr) {
583
+ case A_LAST_FRAME_TOP0:
584
+ val = FIELD_DP32(val, LAST_FRAME_TOP0, BLOCKTYPE5_LAST_FRAME_LSB,
585
+ s->cfg.blktype_num_frames[5]);
586
+ val = FIELD_DP32(val, LAST_FRAME_TOP0, BLOCKTYPE4_LAST_FRAME,
587
+ s->cfg.blktype_num_frames[4]);
588
+ break;
589
+ case A_LAST_FRAME_TOP1:
590
+ val = FIELD_DP32(val, LAST_FRAME_TOP1, BLOCKTYPE6_LAST_FRAME,
591
+ s->cfg.blktype_num_frames[6]);
592
+ val = FIELD_DP32(val, LAST_FRAME_TOP1, BLOCKTYPE5_LAST_FRAME_MSB,
593
+ (s->cfg.blktype_num_frames[5] >> 12));
594
+ break;
595
+ case A_LAST_FRAME_TOP2:
596
+ case A_LAST_FRAME_BOT3:
597
+ default:
598
+ break;
599
+ }
600
+
601
+ return val;
602
+}
603
+
604
+static void cfrm_far_sfr_post_write(RegisterInfo *reg, uint64_t val)
605
+{
606
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
607
+
608
+ if (s->row_configured && s->rowon && s->rcfg) {
609
+ uint32_t start_addr = extract32(s->regs[R_FAR_SFR0], 0, 23);
610
+
611
+ /* Readback 1 frame */
612
+ cfrm_readout_frames(s, start_addr, start_addr + 1);
613
+ }
614
+}
615
+
616
+static const RegisterAccessInfo cframe_reg_regs_info[] = {
617
+ { .name = "CRC0", .addr = A_CRC0,
618
+ .rsvd = 0x00000000,
619
+ },{ .name = "CRC1", .addr = A_CRC0,
620
+ .rsvd = 0xffffffff,
621
+ },{ .name = "CRC2", .addr = A_CRC0,
622
+ .rsvd = 0xffffffff,
623
+ },{ .name = "CRC3", .addr = A_CRC0,
624
+ .rsvd = 0xffffffff,
625
+ },{ .name = "FAR0", .addr = A_FAR0,
626
+ .rsvd = 0xfe000000,
627
+ },{ .name = "FAR1", .addr = A_FAR1,
628
+ .rsvd = 0xffffffff,
629
+ },{ .name = "FAR2", .addr = A_FAR2,
630
+ .rsvd = 0xffffffff,
631
+ },{ .name = "FAR3", .addr = A_FAR3,
632
+ .rsvd = 0xffffffff,
633
+ },{ .name = "FAR_SFR0", .addr = A_FAR_SFR0,
634
+ .rsvd = 0xff800000,
635
+ },{ .name = "FAR_SFR1", .addr = A_FAR_SFR1,
636
+ .rsvd = 0xffffffff,
637
+ },{ .name = "FAR_SFR2", .addr = A_FAR_SFR2,
638
+ .rsvd = 0xffffffff,
639
+ },{ .name = "FAR_SFR3", .addr = A_FAR_SFR3,
640
+ .rsvd = 0xffffffff,
641
+ .post_write = cfrm_far_sfr_post_write,
642
+ },{ .name = "FDRI0", .addr = A_FDRI0,
643
+ },{ .name = "FDRI1", .addr = A_FDRI1,
644
+ },{ .name = "FDRI2", .addr = A_FDRI2,
645
+ },{ .name = "FDRI3", .addr = A_FDRI3,
646
+ .post_write = cfrm_fdri_post_write,
647
+ },{ .name = "FRCNT0", .addr = A_FRCNT0,
648
+ .rsvd = 0x00000000,
649
+ },{ .name = "FRCNT1", .addr = A_FRCNT1,
650
+ .rsvd = 0xffffffff,
651
+ },{ .name = "FRCNT2", .addr = A_FRCNT2,
652
+ .rsvd = 0xffffffff,
653
+ },{ .name = "FRCNT3", .addr = A_FRCNT3,
654
+ .rsvd = 0xffffffff,
655
+ .post_write = cfrm_frcnt_post_write
656
+ },{ .name = "CMD0", .addr = A_CMD0,
657
+ .rsvd = 0xffffffe0,
658
+ },{ .name = "CMD1", .addr = A_CMD1,
659
+ .rsvd = 0xffffffff,
660
+ },{ .name = "CMD2", .addr = A_CMD2,
661
+ .rsvd = 0xffffffff,
662
+ },{ .name = "CMD3", .addr = A_CMD3,
663
+ .rsvd = 0xffffffff,
664
+ .post_write = cfrm_cmd_post_write
665
+ },{ .name = "CR_MASK0", .addr = A_CR_MASK0,
666
+ .rsvd = 0x00000000,
667
+ },{ .name = "CR_MASK1", .addr = A_CR_MASK1,
668
+ .rsvd = 0x00000000,
669
+ },{ .name = "CR_MASK2", .addr = A_CR_MASK2,
670
+ .rsvd = 0x00000000,
671
+ },{ .name = "CR_MASK3", .addr = A_CR_MASK3,
672
+ .rsvd = 0xffffffff,
673
+ },{ .name = "CTL0", .addr = A_CTL0,
674
+ .rsvd = 0xfffffff8,
675
+ },{ .name = "CTL1", .addr = A_CTL1,
676
+ .rsvd = 0xffffffff,
677
+ },{ .name = "CTL2", .addr = A_CTL2,
678
+ .rsvd = 0xffffffff,
679
+ },{ .name = "CTL3", .addr = A_CTL3,
680
+ .rsvd = 0xffffffff,
681
+ },{ .name = "CFRM_ISR0", .addr = A_CFRM_ISR0,
682
+ .rsvd = 0xffc04000,
683
+ .w1c = 0x3bfff,
684
+ },{ .name = "CFRM_ISR1", .addr = A_CFRM_ISR1,
685
+ .rsvd = 0xffffffff,
686
+ },{ .name = "CFRM_ISR2", .addr = A_CFRM_ISR2,
687
+ .rsvd = 0xffffffff,
688
+ },{ .name = "CFRM_ISR3", .addr = A_CFRM_ISR3,
689
+ .rsvd = 0xffffffff,
690
+ .post_write = cfrm_isr_postw,
691
+ },{ .name = "CFRM_IMR0", .addr = A_CFRM_IMR0,
692
+ .rsvd = 0xffc04000,
693
+ .ro = 0xfffff,
694
+ .reset = 0x3bfff,
695
+ },{ .name = "CFRM_IMR1", .addr = A_CFRM_IMR1,
696
+ .rsvd = 0xffffffff,
697
+ },{ .name = "CFRM_IMR2", .addr = A_CFRM_IMR2,
698
+ .rsvd = 0xffffffff,
699
+ },{ .name = "CFRM_IMR3", .addr = A_CFRM_IMR3,
700
+ .rsvd = 0xffffffff,
701
+ },{ .name = "CFRM_IER0", .addr = A_CFRM_IER0,
702
+ .rsvd = 0xffc04000,
703
+ },{ .name = "CFRM_IER1", .addr = A_CFRM_IER1,
704
+ .rsvd = 0xffffffff,
705
+ },{ .name = "CFRM_IER2", .addr = A_CFRM_IER2,
706
+ .rsvd = 0xffffffff,
707
+ },{ .name = "CFRM_IER3", .addr = A_CFRM_IER3,
708
+ .rsvd = 0xffffffff,
709
+ .pre_write = cfrm_ier_prew,
710
+ },{ .name = "CFRM_IDR0", .addr = A_CFRM_IDR0,
711
+ .rsvd = 0xffc04000,
712
+ },{ .name = "CFRM_IDR1", .addr = A_CFRM_IDR1,
713
+ .rsvd = 0xffffffff,
714
+ },{ .name = "CFRM_IDR2", .addr = A_CFRM_IDR2,
715
+ .rsvd = 0xffffffff,
716
+ },{ .name = "CFRM_IDR3", .addr = A_CFRM_IDR3,
717
+ .rsvd = 0xffffffff,
718
+ .pre_write = cfrm_idr_prew,
719
+ },{ .name = "CFRM_ITR0", .addr = A_CFRM_ITR0,
720
+ .rsvd = 0xffc04000,
721
+ },{ .name = "CFRM_ITR1", .addr = A_CFRM_ITR1,
722
+ .rsvd = 0xffffffff,
723
+ },{ .name = "CFRM_ITR2", .addr = A_CFRM_ITR2,
724
+ .rsvd = 0xffffffff,
725
+ },{ .name = "CFRM_ITR3", .addr = A_CFRM_ITR3,
726
+ .rsvd = 0xffffffff,
727
+ .pre_write = cfrm_itr_prew,
728
+ },{ .name = "SEU_SYNDRM00", .addr = A_SEU_SYNDRM00,
729
+ },{ .name = "SEU_SYNDRM01", .addr = A_SEU_SYNDRM01,
730
+ },{ .name = "SEU_SYNDRM02", .addr = A_SEU_SYNDRM02,
731
+ },{ .name = "SEU_SYNDRM03", .addr = A_SEU_SYNDRM03,
732
+ },{ .name = "SEU_SYNDRM10", .addr = A_SEU_SYNDRM10,
733
+ },{ .name = "SEU_SYNDRM11", .addr = A_SEU_SYNDRM11,
734
+ },{ .name = "SEU_SYNDRM12", .addr = A_SEU_SYNDRM12,
735
+ },{ .name = "SEU_SYNDRM13", .addr = A_SEU_SYNDRM13,
736
+ },{ .name = "SEU_SYNDRM20", .addr = A_SEU_SYNDRM20,
737
+ },{ .name = "SEU_SYNDRM21", .addr = A_SEU_SYNDRM21,
738
+ },{ .name = "SEU_SYNDRM22", .addr = A_SEU_SYNDRM22,
739
+ },{ .name = "SEU_SYNDRM23", .addr = A_SEU_SYNDRM23,
740
+ },{ .name = "SEU_SYNDRM30", .addr = A_SEU_SYNDRM30,
741
+ },{ .name = "SEU_SYNDRM31", .addr = A_SEU_SYNDRM31,
742
+ },{ .name = "SEU_SYNDRM32", .addr = A_SEU_SYNDRM32,
743
+ },{ .name = "SEU_SYNDRM33", .addr = A_SEU_SYNDRM33,
744
+ },{ .name = "SEU_VIRTUAL_SYNDRM0", .addr = A_SEU_VIRTUAL_SYNDRM0,
745
+ },{ .name = "SEU_VIRTUAL_SYNDRM1", .addr = A_SEU_VIRTUAL_SYNDRM1,
746
+ },{ .name = "SEU_VIRTUAL_SYNDRM2", .addr = A_SEU_VIRTUAL_SYNDRM2,
747
+ },{ .name = "SEU_VIRTUAL_SYNDRM3", .addr = A_SEU_VIRTUAL_SYNDRM3,
748
+ },{ .name = "SEU_CRC0", .addr = A_SEU_CRC0,
749
+ },{ .name = "SEU_CRC1", .addr = A_SEU_CRC1,
750
+ },{ .name = "SEU_CRC2", .addr = A_SEU_CRC2,
751
+ },{ .name = "SEU_CRC3", .addr = A_SEU_CRC3,
752
+ },{ .name = "CFRAME_FAR_BOT0", .addr = A_CFRAME_FAR_BOT0,
753
+ },{ .name = "CFRAME_FAR_BOT1", .addr = A_CFRAME_FAR_BOT1,
754
+ },{ .name = "CFRAME_FAR_BOT2", .addr = A_CFRAME_FAR_BOT2,
755
+ },{ .name = "CFRAME_FAR_BOT3", .addr = A_CFRAME_FAR_BOT3,
756
+ },{ .name = "CFRAME_FAR_TOP0", .addr = A_CFRAME_FAR_TOP0,
757
+ },{ .name = "CFRAME_FAR_TOP1", .addr = A_CFRAME_FAR_TOP1,
758
+ },{ .name = "CFRAME_FAR_TOP2", .addr = A_CFRAME_FAR_TOP2,
759
+ },{ .name = "CFRAME_FAR_TOP3", .addr = A_CFRAME_FAR_TOP3,
760
+ },{ .name = "LAST_FRAME_BOT0", .addr = A_LAST_FRAME_BOT0,
761
+ .ro = 0xffffffff,
762
+ .post_read = cfrm_last_frame_bot_post_read,
763
+ },{ .name = "LAST_FRAME_BOT1", .addr = A_LAST_FRAME_BOT1,
764
+ .ro = 0xffffffff,
765
+ .post_read = cfrm_last_frame_bot_post_read,
766
+ },{ .name = "LAST_FRAME_BOT2", .addr = A_LAST_FRAME_BOT2,
767
+ .ro = 0xffffffff,
768
+ .post_read = cfrm_last_frame_bot_post_read,
769
+ },{ .name = "LAST_FRAME_BOT3", .addr = A_LAST_FRAME_BOT3,
770
+ .ro = 0xffffffff,
771
+ .post_read = cfrm_last_frame_bot_post_read,
772
+ },{ .name = "LAST_FRAME_TOP0", .addr = A_LAST_FRAME_TOP0,
773
+ .ro = 0xffffffff,
774
+ .post_read = cfrm_last_frame_top_post_read,
775
+ },{ .name = "LAST_FRAME_TOP1", .addr = A_LAST_FRAME_TOP1,
776
+ .ro = 0xffffffff,
777
+ .post_read = cfrm_last_frame_top_post_read,
778
+ },{ .name = "LAST_FRAME_TOP2", .addr = A_LAST_FRAME_TOP2,
779
+ .ro = 0xffffffff,
780
+ .post_read = cfrm_last_frame_top_post_read,
781
+ },{ .name = "LAST_FRAME_TOP3", .addr = A_LAST_FRAME_TOP3,
782
+ .ro = 0xffffffff,
783
+ .post_read = cfrm_last_frame_top_post_read,
784
+ }
785
+};
786
+
787
+static void cframe_reg_cfi_transfer_packet(XlnxCfiIf *cfi_if,
788
+ XlnxCfiPacket *pkt)
789
+{
790
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(cfi_if);
791
+ uint64_t we = MAKE_64BIT_MASK(0, 4 * 8);
792
+
793
+ if (!s->row_configured) {
794
+ return;
795
+ }
796
+
797
+ switch (pkt->reg_addr) {
798
+ case CFRAME_FAR:
799
+ s->regs[R_FAR0] = pkt->data[0];
800
+ break;
801
+ case CFRAME_SFR:
802
+ s->regs[R_FAR_SFR0] = pkt->data[0];
803
+ register_write(&s->regs_info[R_FAR_SFR3], 0,
804
+ we, object_get_typename(OBJECT(s)),
805
+ XLNX_VERSAL_CFRAME_REG_ERR_DEBUG);
806
+ break;
807
+ case CFRAME_FDRI:
808
+ s->regs[R_FDRI0] = pkt->data[0];
809
+ s->regs[R_FDRI1] = pkt->data[1];
810
+ s->regs[R_FDRI2] = pkt->data[2];
811
+ register_write(&s->regs_info[R_FDRI3], pkt->data[3],
812
+ we, object_get_typename(OBJECT(s)),
813
+ XLNX_VERSAL_CFRAME_REG_ERR_DEBUG);
814
+ break;
815
+ case CFRAME_CMD:
816
+ ARRAY_FIELD_DP32(s->regs, CMD0, CMD, pkt->data[0]);
817
+
818
+ register_write(&s->regs_info[R_CMD3], 0,
819
+ we, object_get_typename(OBJECT(s)),
820
+ XLNX_VERSAL_CFRAME_REG_ERR_DEBUG);
821
+ break;
822
+ default:
823
+ break;
824
+ }
825
+}
826
+
827
+static uint64_t cframe_reg_fdri_read(void *opaque, hwaddr addr, unsigned size)
828
+{
829
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
830
+ HWADDR_PRIx "\n", __func__, addr);
831
+ return 0;
832
+}
833
+
834
+static void cframe_reg_fdri_write(void *opaque, hwaddr addr, uint64_t value,
835
+ unsigned size)
836
+{
837
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(opaque);
838
+ uint32_t wfifo[WFIFO_SZ];
839
+
840
+ if (update_wfifo(addr, value, s->wfifo, wfifo)) {
841
+ uint64_t we = MAKE_64BIT_MASK(0, 4 * 8);
842
+
843
+ s->regs[R_FDRI0] = wfifo[0];
844
+ s->regs[R_FDRI1] = wfifo[1];
845
+ s->regs[R_FDRI2] = wfifo[2];
846
+ register_write(&s->regs_info[R_FDRI3], wfifo[3],
847
+ we, object_get_typename(OBJECT(s)),
848
+ XLNX_VERSAL_CFRAME_REG_ERR_DEBUG);
849
+ }
850
+}
851
+
852
+static void cframe_reg_reset_enter(Object *obj, ResetType type)
853
+{
854
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(obj);
855
+ unsigned int i;
856
+
857
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
858
+ register_reset(&s->regs_info[i]);
859
+ }
860
+ memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
861
+ fifo32_reset(&s->new_f_data);
862
+
863
+ if (g_tree_nnodes(s->cframes)) {
864
+ /*
865
+ * Take a reference so when g_tree_destroy() unrefs it we keep the
866
+ * GTree and only destroy its contents. NB: when our minimum
867
+ * glib version is at least 2.70 we could use g_tree_remove_all().
868
+ */
869
+ g_tree_ref(s->cframes);
870
+ g_tree_destroy(s->cframes);
871
+ }
872
+}
873
+
874
+static void cframe_reg_reset_hold(Object *obj)
875
+{
876
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(obj);
877
+
878
+ cfrm_imr_update_irq(s);
879
+}
880
+
881
+static const MemoryRegionOps cframe_reg_ops = {
882
+ .read = register_read_memory,
883
+ .write = register_write_memory,
884
+ .endianness = DEVICE_LITTLE_ENDIAN,
885
+ .valid = {
886
+ .min_access_size = 4,
887
+ .max_access_size = 4,
888
+ },
889
+};
890
+
891
+static const MemoryRegionOps cframe_reg_fdri_ops = {
892
+ .read = cframe_reg_fdri_read,
893
+ .write = cframe_reg_fdri_write,
894
+ .endianness = DEVICE_LITTLE_ENDIAN,
895
+ .valid = {
896
+ .min_access_size = 4,
897
+ .max_access_size = 4,
898
+ },
899
+};
900
+
901
+static void cframe_reg_realize(DeviceState *dev, Error **errp)
902
+{
903
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev);
904
+
905
+ for (int i = 0; i < ARRAY_SIZE(s->cfg.blktype_num_frames); i++) {
906
+ if (s->cfg.blktype_num_frames[i] > MAX_BLOCKTYPE_FRAMES) {
907
+ error_setg(errp,
908
+ "blktype-frames%d > 0xFFFFF (max frame per block)",
909
+ i);
910
+ return;
911
+ }
912
+ if (s->cfg.blktype_num_frames[i]) {
913
+ s->row_configured = true;
914
+ }
915
+ }
916
+}
917
+
918
+static void cframe_reg_init(Object *obj)
919
+{
920
+ XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(obj);
921
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
922
+ RegisterInfoArray *reg_array;
923
+
924
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_VERSAL_CFRAME_REG,
925
+ CFRAME_REG_R_MAX * 4);
926
+ reg_array =
927
+ register_init_block32(DEVICE(obj), cframe_reg_regs_info,
928
+ ARRAY_SIZE(cframe_reg_regs_info),
929
+ s->regs_info, s->regs,
930
+ &cframe_reg_ops,
931
+ XLNX_VERSAL_CFRAME_REG_ERR_DEBUG,
932
+ CFRAME_REG_R_MAX * 4);
933
+ memory_region_add_subregion(&s->iomem,
934
+ 0x0,
935
+ &reg_array->mem);
936
+ sysbus_init_mmio(sbd, &s->iomem);
937
+ memory_region_init_io(&s->iomem_fdri, obj, &cframe_reg_fdri_ops, s,
938
+ TYPE_XLNX_VERSAL_CFRAME_REG "-fdri",
939
+ KEYHOLE_STREAM_4K);
940
+ sysbus_init_mmio(sbd, &s->iomem_fdri);
941
+ sysbus_init_irq(sbd, &s->irq_cfrm_imr);
942
+
943
+ s->cframes = g_tree_new_full((GCompareDataFunc)int_cmp, NULL,
944
+ NULL, (GDestroyNotify)g_free);
945
+ fifo32_create(&s->new_f_data, FRAME_NUM_WORDS);
946
+}
947
+
948
+static const VMStateDescription vmstate_cframe = {
949
+ .name = "cframe",
950
+ .version_id = 1,
951
+ .minimum_version_id = 1,
952
+ .fields = (VMStateField[]) {
953
+ VMSTATE_UINT32_ARRAY(data, XlnxCFrame, FRAME_NUM_WORDS),
954
+ VMSTATE_END_OF_LIST()
955
+ }
956
+};
957
+
958
+static const VMStateDescription vmstate_cframe_reg = {
959
+ .name = TYPE_XLNX_VERSAL_CFRAME_REG,
960
+ .version_id = 1,
961
+ .minimum_version_id = 1,
962
+ .fields = (VMStateField[]) {
963
+ VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFrameReg, 4),
964
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCFrameReg, CFRAME_REG_R_MAX),
965
+ VMSTATE_BOOL(rowon, XlnxVersalCFrameReg),
966
+ VMSTATE_BOOL(wcfg, XlnxVersalCFrameReg),
967
+ VMSTATE_BOOL(rcfg, XlnxVersalCFrameReg),
968
+ VMSTATE_GTREE_DIRECT_KEY_V(cframes, XlnxVersalCFrameReg, 1,
969
+ &vmstate_cframe, XlnxCFrame),
970
+ VMSTATE_FIFO32(new_f_data, XlnxVersalCFrameReg),
971
+ VMSTATE_END_OF_LIST(),
972
+ }
973
+};
974
+
975
+static Property cframe_regs_props[] = {
976
+ DEFINE_PROP_LINK("cfu-fdro", XlnxVersalCFrameReg, cfg.cfu_fdro,
977
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
978
+ DEFINE_PROP_UINT32("blktype0-frames", XlnxVersalCFrameReg,
979
+ cfg.blktype_num_frames[0], 0),
980
+ DEFINE_PROP_UINT32("blktype1-frames", XlnxVersalCFrameReg,
981
+ cfg.blktype_num_frames[1], 0),
982
+ DEFINE_PROP_UINT32("blktype2-frames", XlnxVersalCFrameReg,
983
+ cfg.blktype_num_frames[2], 0),
984
+ DEFINE_PROP_UINT32("blktype3-frames", XlnxVersalCFrameReg,
985
+ cfg.blktype_num_frames[3], 0),
986
+ DEFINE_PROP_UINT32("blktype4-frames", XlnxVersalCFrameReg,
987
+ cfg.blktype_num_frames[4], 0),
988
+ DEFINE_PROP_UINT32("blktype5-frames", XlnxVersalCFrameReg,
989
+ cfg.blktype_num_frames[5], 0),
990
+ DEFINE_PROP_UINT32("blktype6-frames", XlnxVersalCFrameReg,
991
+ cfg.blktype_num_frames[6], 0),
992
+ DEFINE_PROP_END_OF_LIST(),
993
+};
994
+
995
+static void cframe_reg_class_init(ObjectClass *klass, void *data)
996
+{
997
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
998
+ DeviceClass *dc = DEVICE_CLASS(klass);
999
+ XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass);
1000
+
1001
+ dc->vmsd = &vmstate_cframe_reg;
1002
+ dc->realize = cframe_reg_realize;
1003
+ rc->phases.enter = cframe_reg_reset_enter;
1004
+ rc->phases.hold = cframe_reg_reset_hold;
1005
+ device_class_set_props(dc, cframe_regs_props);
1006
+ xcic->cfi_transfer_packet = cframe_reg_cfi_transfer_packet;
1007
+}
1008
+
1009
+static const TypeInfo cframe_reg_info = {
1010
+ .name = TYPE_XLNX_VERSAL_CFRAME_REG,
1011
+ .parent = TYPE_SYS_BUS_DEVICE,
1012
+ .instance_size = sizeof(XlnxVersalCFrameReg),
1013
+ .class_init = cframe_reg_class_init,
1014
+ .instance_init = cframe_reg_init,
1015
+ .interfaces = (InterfaceInfo[]) {
1016
+ { TYPE_XLNX_CFI_IF },
1017
+ { }
1018
+ }
1019
+};
1020
+
1021
+static void cframe_reg_register_types(void)
1022
+{
1023
+ type_register_static(&cframe_reg_info);
1024
+}
1025
+
1026
+type_init(cframe_reg_register_types)
1027
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
1028
index XXXXXXX..XXXXXXX 100644
1029
--- a/hw/misc/meson.build
1030
+++ b/hw/misc/meson.build
1031
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
1032
'xlnx-versal-pmc-iou-slcr.c',
1033
'xlnx-versal-cfu.c',
1034
'xlnx-cfi-if.c',
1035
+ 'xlnx-versal-cframe-reg.c',
1036
))
1037
system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
1038
system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
1039
--
1040
2.34.1
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
1
2
3
Introduce a model of Xilinx Versal's Configuration Frame broadcast
4
controller (CFRAME_BCAST_REG).
5
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230831165701.2016397-7-francisco.iglesias@amd.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/misc/xlnx-versal-cframe-reg.h | 17 +++
12
hw/misc/xlnx-versal-cframe-reg.c | 161 +++++++++++++++++++++++
13
2 files changed, 178 insertions(+)
14
15
diff --git a/include/hw/misc/xlnx-versal-cframe-reg.h b/include/hw/misc/xlnx-versal-cframe-reg.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/xlnx-versal-cframe-reg.h
18
+++ b/include/hw/misc/xlnx-versal-cframe-reg.h
19
@@ -XXX,XX +XXX,XX @@
20
#define TYPE_XLNX_VERSAL_CFRAME_REG "xlnx,cframe-reg"
21
OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFrameReg, XLNX_VERSAL_CFRAME_REG)
22
23
+#define TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "xlnx.cframe-bcast-reg"
24
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFrameBcastReg,
25
+ XLNX_VERSAL_CFRAME_BCAST_REG)
26
+
27
/*
28
* The registers in this module are 128 bits wide but it is ok to write
29
* and read them through 4 sequential 32 bit accesses (address[3:2] = 0,
30
@@ -XXX,XX +XXX,XX @@ struct XlnxVersalCFrameReg {
31
bool row_configured;
32
};
33
34
+struct XlnxVersalCFrameBcastReg {
35
+ SysBusDevice parent_obj;
36
+ MemoryRegion iomem_reg;
37
+ MemoryRegion iomem_fdri;
38
+
39
+ /* 128-bit wfifo. */
40
+ uint32_t wfifo[WFIFO_SZ];
41
+
42
+ struct {
43
+ XlnxCfiIf *cframe[15];
44
+ } cfg;
45
+};
46
+
47
#endif
48
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/misc/xlnx-versal-cframe-reg.c
51
+++ b/hw/misc/xlnx-versal-cframe-reg.c
52
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps cframe_reg_fdri_ops = {
53
},
54
};
55
56
+static uint64_t cframes_bcast_reg_read(void *opaque, hwaddr addr, unsigned size)
57
+{
58
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
59
+ HWADDR_PRIx "\n", __func__, addr);
60
+ return 0;
61
+}
62
+
63
+static void cframes_bcast_write(XlnxVersalCFrameBcastReg *s, uint8_t reg_addr,
64
+ uint32_t *wfifo)
65
+{
66
+ XlnxCfiPacket pkt = {
67
+ .reg_addr = reg_addr,
68
+ .data[0] = wfifo[0],
69
+ .data[1] = wfifo[1],
70
+ .data[2] = wfifo[2],
71
+ .data[3] = wfifo[3]
72
+ };
73
+
74
+ for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
75
+ if (s->cfg.cframe[i]) {
76
+ xlnx_cfi_transfer_packet(s->cfg.cframe[i], &pkt);
77
+ }
78
+ }
79
+}
80
+
81
+static void cframes_bcast_reg_write(void *opaque, hwaddr addr, uint64_t value,
82
+ unsigned size)
83
+{
84
+ XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
85
+ uint32_t wfifo[WFIFO_SZ];
86
+
87
+ if (update_wfifo(addr, value, s->wfifo, wfifo)) {
88
+ uint8_t reg_addr = extract32(addr, 4, 6);
89
+
90
+ cframes_bcast_write(s, reg_addr, wfifo);
91
+ }
92
+}
93
+
94
+static uint64_t cframes_bcast_fdri_read(void *opaque, hwaddr addr,
95
+ unsigned size)
96
+{
97
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
98
+ HWADDR_PRIx "\n", __func__, addr);
99
+ return 0;
100
+}
101
+
102
+static void cframes_bcast_fdri_write(void *opaque, hwaddr addr, uint64_t value,
103
+ unsigned size)
104
+{
105
+ XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
106
+ uint32_t wfifo[WFIFO_SZ];
107
+
108
+ if (update_wfifo(addr, value, s->wfifo, wfifo)) {
109
+ cframes_bcast_write(s, CFRAME_FDRI, wfifo);
110
+ }
111
+}
112
+
113
+static const MemoryRegionOps cframes_bcast_reg_reg_ops = {
114
+ .read = cframes_bcast_reg_read,
115
+ .write = cframes_bcast_reg_write,
116
+ .endianness = DEVICE_LITTLE_ENDIAN,
117
+ .valid = {
118
+ .min_access_size = 4,
119
+ .max_access_size = 4,
120
+ },
121
+};
122
+
123
+static const MemoryRegionOps cframes_bcast_reg_fdri_ops = {
124
+ .read = cframes_bcast_fdri_read,
125
+ .write = cframes_bcast_fdri_write,
126
+ .endianness = DEVICE_LITTLE_ENDIAN,
127
+ .valid = {
128
+ .min_access_size = 4,
129
+ .max_access_size = 4,
130
+ },
131
+};
132
+
133
static void cframe_reg_realize(DeviceState *dev, Error **errp)
134
{
135
XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev);
136
@@ -XXX,XX +XXX,XX @@ static Property cframe_regs_props[] = {
137
DEFINE_PROP_END_OF_LIST(),
138
};
139
140
+static void cframe_bcast_reg_init(Object *obj)
141
+{
142
+ XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
143
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
144
+
145
+ memory_region_init_io(&s->iomem_reg, obj, &cframes_bcast_reg_reg_ops, s,
146
+ TYPE_XLNX_VERSAL_CFRAME_BCAST_REG, KEYHOLE_STREAM_4K);
147
+ memory_region_init_io(&s->iomem_fdri, obj, &cframes_bcast_reg_fdri_ops, s,
148
+ TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "-fdri",
149
+ KEYHOLE_STREAM_4K);
150
+ sysbus_init_mmio(sbd, &s->iomem_reg);
151
+ sysbus_init_mmio(sbd, &s->iomem_fdri);
152
+}
153
+
154
+static void cframe_bcast_reg_reset_enter(Object *obj, ResetType type)
155
+{
156
+ XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
157
+
158
+ memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
159
+}
160
+
161
+static const VMStateDescription vmstate_cframe_bcast_reg = {
162
+ .name = TYPE_XLNX_VERSAL_CFRAME_BCAST_REG,
163
+ .version_id = 1,
164
+ .minimum_version_id = 1,
165
+ .fields = (VMStateField[]) {
166
+ VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFrameBcastReg, 4),
167
+ VMSTATE_END_OF_LIST(),
168
+ }
169
+};
170
+
171
+static Property cframe_bcast_regs_props[] = {
172
+ DEFINE_PROP_LINK("cframe0", XlnxVersalCFrameBcastReg, cfg.cframe[0],
173
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
174
+ DEFINE_PROP_LINK("cframe1", XlnxVersalCFrameBcastReg, cfg.cframe[1],
175
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
176
+ DEFINE_PROP_LINK("cframe2", XlnxVersalCFrameBcastReg, cfg.cframe[2],
177
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
178
+ DEFINE_PROP_LINK("cframe3", XlnxVersalCFrameBcastReg, cfg.cframe[3],
179
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
180
+ DEFINE_PROP_LINK("cframe4", XlnxVersalCFrameBcastReg, cfg.cframe[4],
181
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
182
+ DEFINE_PROP_LINK("cframe5", XlnxVersalCFrameBcastReg, cfg.cframe[5],
183
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
184
+ DEFINE_PROP_LINK("cframe6", XlnxVersalCFrameBcastReg, cfg.cframe[6],
185
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
186
+ DEFINE_PROP_LINK("cframe7", XlnxVersalCFrameBcastReg, cfg.cframe[7],
187
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
188
+ DEFINE_PROP_LINK("cframe8", XlnxVersalCFrameBcastReg, cfg.cframe[8],
189
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
190
+ DEFINE_PROP_LINK("cframe9", XlnxVersalCFrameBcastReg, cfg.cframe[9],
191
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
192
+ DEFINE_PROP_LINK("cframe10", XlnxVersalCFrameBcastReg, cfg.cframe[10],
193
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
194
+ DEFINE_PROP_LINK("cframe11", XlnxVersalCFrameBcastReg, cfg.cframe[11],
195
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
196
+ DEFINE_PROP_LINK("cframe12", XlnxVersalCFrameBcastReg, cfg.cframe[12],
197
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
198
+ DEFINE_PROP_LINK("cframe13", XlnxVersalCFrameBcastReg, cfg.cframe[13],
199
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
200
+ DEFINE_PROP_LINK("cframe14", XlnxVersalCFrameBcastReg, cfg.cframe[14],
201
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
202
+ DEFINE_PROP_END_OF_LIST(),
203
+};
204
+
205
static void cframe_reg_class_init(ObjectClass *klass, void *data)
206
{
207
ResettableClass *rc = RESETTABLE_CLASS(klass);
208
@@ -XXX,XX +XXX,XX @@ static void cframe_reg_class_init(ObjectClass *klass, void *data)
209
xcic->cfi_transfer_packet = cframe_reg_cfi_transfer_packet;
210
}
211
212
+static void cframe_bcast_reg_class_init(ObjectClass *klass, void *data)
213
+{
214
+ DeviceClass *dc = DEVICE_CLASS(klass);
215
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
216
+
217
+ dc->vmsd = &vmstate_cframe_bcast_reg;
218
+ device_class_set_props(dc, cframe_bcast_regs_props);
219
+ rc->phases.enter = cframe_bcast_reg_reset_enter;
220
+}
221
+
222
static const TypeInfo cframe_reg_info = {
223
.name = TYPE_XLNX_VERSAL_CFRAME_REG,
224
.parent = TYPE_SYS_BUS_DEVICE,
225
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cframe_reg_info = {
226
}
227
};
228
229
+static const TypeInfo cframe_bcast_reg_info = {
230
+ .name = TYPE_XLNX_VERSAL_CFRAME_BCAST_REG,
231
+ .parent = TYPE_SYS_BUS_DEVICE,
232
+ .instance_size = sizeof(XlnxVersalCFrameBcastReg),
233
+ .class_init = cframe_bcast_reg_class_init,
234
+ .instance_init = cframe_bcast_reg_init,
235
+};
236
+
237
static void cframe_reg_register_types(void)
238
{
239
type_register_static(&cframe_reg_info);
240
+ type_register_static(&cframe_bcast_reg_info);
241
}
242
243
type_init(cframe_reg_register_types)
244
--
245
2.34.1
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
1
2
3
Connect the Configuration Frame Unit (CFU_APB, CFU_FDRO and CFU_SFR) to
4
the Versal machine.
5
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Acked-by: Edgar E. Iglesias <edgar@zeroasic.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20230831165701.2016397-8-francisco.iglesias@amd.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/xlnx-versal.h | 16 ++++++++++++++
13
hw/arm/xlnx-versal.c | 42 ++++++++++++++++++++++++++++++++++++
14
2 files changed, 58 insertions(+)
15
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-versal.h
19
+++ b/include/hw/arm/xlnx-versal.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/misc/xlnx-versal-crl.h"
22
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
23
#include "hw/net/xlnx-versal-canfd.h"
24
+#include "hw/misc/xlnx-versal-cfu.h"
25
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
27
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
28
@@ -XXX,XX +XXX,XX @@ struct Versal {
29
XlnxEFuse efuse;
30
XlnxVersalEFuseCtrl efuse_ctrl;
31
XlnxVersalEFuseCache efuse_cache;
32
+ XlnxVersalCFUAPB cfu_apb;
33
+ XlnxVersalCFUFDRO cfu_fdro;
34
+ XlnxVersalCFUSFR cfu_sfr;
35
36
OrIRQState apb_irq_orgate;
37
} pmc;
38
@@ -XXX,XX +XXX,XX @@ struct Versal {
39
#define VERSAL_GEM1_WAKE_IRQ_0 59
40
#define VERSAL_ADMA_IRQ_0 60
41
#define VERSAL_XRAM_IRQ_0 79
42
+#define VERSAL_CFU_IRQ_0 120
43
#define VERSAL_PMC_APB_IRQ 121
44
#define VERSAL_OSPI_IRQ 124
45
#define VERSAL_SD0_IRQ_0 126
46
@@ -XXX,XX +XXX,XX @@ struct Versal {
47
#define MM_PMC_EFUSE_CACHE 0xf1250000
48
#define MM_PMC_EFUSE_CACHE_SIZE 0x00C00
49
50
+#define MM_PMC_CFU_APB 0xf12b0000
51
+#define MM_PMC_CFU_APB_SIZE 0x10000
52
+#define MM_PMC_CFU_STREAM 0xf12c0000
53
+#define MM_PMC_CFU_STREAM_SIZE 0x1000
54
+#define MM_PMC_CFU_SFR 0xf12c1000
55
+#define MM_PMC_CFU_SFR_SIZE 0x1000
56
+#define MM_PMC_CFU_FDRO 0xf12c2000
57
+#define MM_PMC_CFU_FDRO_SIZE 0x1000
58
+#define MM_PMC_CFU_STREAM_2 0xf1f80000
59
+#define MM_PMC_CFU_STREAM_2_SIZE 0x40000
60
+
61
#define MM_PMC_CRP 0xf1260000U
62
#define MM_PMC_CRP_SIZE 0x10000
63
#define MM_PMC_RTC 0xf12a0000
64
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/arm/xlnx-versal.c
67
+++ b/hw/arm/xlnx-versal.c
68
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
69
qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
70
}
71
72
+static void versal_create_cfu(Versal *s, qemu_irq *pic)
73
+{
74
+ SysBusDevice *sbd;
75
+
76
+ /* CFU FDRO */
77
+ object_initialize_child(OBJECT(s), "cfu-fdro", &s->pmc.cfu_fdro,
78
+ TYPE_XLNX_VERSAL_CFU_FDRO);
79
+ sbd = SYS_BUS_DEVICE(&s->pmc.cfu_fdro);
80
+
81
+ sysbus_realize(sbd, &error_fatal);
82
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_FDRO,
83
+ sysbus_mmio_get_region(sbd, 0));
84
+
85
+ /* CFU APB */
86
+ object_initialize_child(OBJECT(s), "cfu-apb", &s->pmc.cfu_apb,
87
+ TYPE_XLNX_VERSAL_CFU_APB);
88
+ sbd = SYS_BUS_DEVICE(&s->pmc.cfu_apb);
89
+
90
+ sysbus_realize(sbd, &error_fatal);
91
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_APB,
92
+ sysbus_mmio_get_region(sbd, 0));
93
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM,
94
+ sysbus_mmio_get_region(sbd, 1));
95
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM_2,
96
+ sysbus_mmio_get_region(sbd, 2));
97
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
98
+
99
+ /* CFU SFR */
100
+ object_initialize_child(OBJECT(s), "cfu-sfr", &s->pmc.cfu_sfr,
101
+ TYPE_XLNX_VERSAL_CFU_SFR);
102
+
103
+ sbd = SYS_BUS_DEVICE(&s->pmc.cfu_sfr);
104
+
105
+ object_property_set_link(OBJECT(&s->pmc.cfu_sfr),
106
+ "cfu", OBJECT(&s->pmc.cfu_apb), &error_abort);
107
+
108
+ sysbus_realize(sbd, &error_fatal);
109
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_SFR,
110
+ sysbus_mmio_get_region(sbd, 0));
111
+}
112
+
113
static void versal_create_crl(Versal *s, qemu_irq *pic)
114
{
115
SysBusDevice *sbd;
116
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
117
versal_create_pmc_iou_slcr(s, pic);
118
versal_create_ospi(s, pic);
119
versal_create_crl(s, pic);
120
+ versal_create_cfu(s, pic);
121
versal_map_ddr(s);
122
versal_unimp(s);
123
124
--
125
2.34.1
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
1
2
3
Connect the Configuration Frame controller (CFRAME_REG) and the
4
Configuration Frame broadcast controller (CFRAME_BCAST_REG) to the
5
Versal machine.
6
7
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20230831165701.2016397-9-francisco.iglesias@amd.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/xlnx-versal.h | 69 +++++++++++++++++++++
13
hw/arm/xlnx-versal.c | 113 ++++++++++++++++++++++++++++++++++-
14
2 files changed, 181 insertions(+), 1 deletion(-)
15
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-versal.h
19
+++ b/include/hw/arm/xlnx-versal.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
22
#include "hw/net/xlnx-versal-canfd.h"
23
#include "hw/misc/xlnx-versal-cfu.h"
24
+#include "hw/misc/xlnx-versal-cframe-reg.h"
25
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
27
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
29
#define XLNX_VERSAL_NR_IRQS 192
30
#define XLNX_VERSAL_NR_CANFD 2
31
#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000)
32
+#define XLNX_VERSAL_NR_CFRAME 15
33
34
struct Versal {
35
/*< private >*/
36
@@ -XXX,XX +XXX,XX @@ struct Versal {
37
XlnxVersalCFUAPB cfu_apb;
38
XlnxVersalCFUFDRO cfu_fdro;
39
XlnxVersalCFUSFR cfu_sfr;
40
+ XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
41
+ XlnxVersalCFrameBcastReg cframe_bcast;
42
43
OrIRQState apb_irq_orgate;
44
} pmc;
45
@@ -XXX,XX +XXX,XX @@ struct Versal {
46
#define MM_PMC_CFU_STREAM_2 0xf1f80000
47
#define MM_PMC_CFU_STREAM_2_SIZE 0x40000
48
49
+#define MM_PMC_CFRAME0_REG 0xf12d0000
50
+#define MM_PMC_CFRAME0_REG_SIZE 0x1000
51
+#define MM_PMC_CFRAME0_FDRI 0xf12d1000
52
+#define MM_PMC_CFRAME0_FDRI_SIZE 0x1000
53
+#define MM_PMC_CFRAME1_REG 0xf12d2000
54
+#define MM_PMC_CFRAME1_REG_SIZE 0x1000
55
+#define MM_PMC_CFRAME1_FDRI 0xf12d3000
56
+#define MM_PMC_CFRAME1_FDRI_SIZE 0x1000
57
+#define MM_PMC_CFRAME2_REG 0xf12d4000
58
+#define MM_PMC_CFRAME2_REG_SIZE 0x1000
59
+#define MM_PMC_CFRAME2_FDRI 0xf12d5000
60
+#define MM_PMC_CFRAME2_FDRI_SIZE 0x1000
61
+#define MM_PMC_CFRAME3_REG 0xf12d6000
62
+#define MM_PMC_CFRAME3_REG_SIZE 0x1000
63
+#define MM_PMC_CFRAME3_FDRI 0xf12d7000
64
+#define MM_PMC_CFRAME3_FDRI_SIZE 0x1000
65
+#define MM_PMC_CFRAME4_REG 0xf12d8000
66
+#define MM_PMC_CFRAME4_REG_SIZE 0x1000
67
+#define MM_PMC_CFRAME4_FDRI 0xf12d9000
68
+#define MM_PMC_CFRAME4_FDRI_SIZE 0x1000
69
+#define MM_PMC_CFRAME5_REG 0xf12da000
70
+#define MM_PMC_CFRAME5_REG_SIZE 0x1000
71
+#define MM_PMC_CFRAME5_FDRI 0xf12db000
72
+#define MM_PMC_CFRAME5_FDRI_SIZE 0x1000
73
+#define MM_PMC_CFRAME6_REG 0xf12dc000
74
+#define MM_PMC_CFRAME6_REG_SIZE 0x1000
75
+#define MM_PMC_CFRAME6_FDRI 0xf12dd000
76
+#define MM_PMC_CFRAME6_FDRI_SIZE 0x1000
77
+#define MM_PMC_CFRAME7_REG 0xf12de000
78
+#define MM_PMC_CFRAME7_REG_SIZE 0x1000
79
+#define MM_PMC_CFRAME7_FDRI 0xf12df000
80
+#define MM_PMC_CFRAME7_FDRI_SIZE 0x1000
81
+#define MM_PMC_CFRAME8_REG 0xf12e0000
82
+#define MM_PMC_CFRAME8_REG_SIZE 0x1000
83
+#define MM_PMC_CFRAME8_FDRI 0xf12e1000
84
+#define MM_PMC_CFRAME8_FDRI_SIZE 0x1000
85
+#define MM_PMC_CFRAME9_REG 0xf12e2000
86
+#define MM_PMC_CFRAME9_REG_SIZE 0x1000
87
+#define MM_PMC_CFRAME9_FDRI 0xf12e3000
88
+#define MM_PMC_CFRAME9_FDRI_SIZE 0x1000
89
+#define MM_PMC_CFRAME10_REG 0xf12e4000
90
+#define MM_PMC_CFRAME10_REG_SIZE 0x1000
91
+#define MM_PMC_CFRAME10_FDRI 0xf12e5000
92
+#define MM_PMC_CFRAME10_FDRI_SIZE 0x1000
93
+#define MM_PMC_CFRAME11_REG 0xf12e6000
94
+#define MM_PMC_CFRAME11_REG_SIZE 0x1000
95
+#define MM_PMC_CFRAME11_FDRI 0xf12e7000
96
+#define MM_PMC_CFRAME11_FDRI_SIZE 0x1000
97
+#define MM_PMC_CFRAME12_REG 0xf12e8000
98
+#define MM_PMC_CFRAME12_REG_SIZE 0x1000
99
+#define MM_PMC_CFRAME12_FDRI 0xf12e9000
100
+#define MM_PMC_CFRAME12_FDRI_SIZE 0x1000
101
+#define MM_PMC_CFRAME13_REG 0xf12ea000
102
+#define MM_PMC_CFRAME13_REG_SIZE 0x1000
103
+#define MM_PMC_CFRAME13_FDRI 0xf12eb000
104
+#define MM_PMC_CFRAME13_FDRI_SIZE 0x1000
105
+#define MM_PMC_CFRAME14_REG 0xf12ec000
106
+#define MM_PMC_CFRAME14_REG_SIZE 0x1000
107
+#define MM_PMC_CFRAME14_FDRI 0xf12ed000
108
+#define MM_PMC_CFRAME14_FDRI_SIZE 0x1000
109
+#define MM_PMC_CFRAME_BCAST_REG 0xf12ee000
110
+#define MM_PMC_CFRAME_BCAST_REG_SIZE 0x1000
111
+#define MM_PMC_CFRAME_BCAST_FDRI 0xf12ef000
112
+#define MM_PMC_CFRAME_BCAST_FDRI_SIZE 0x1000
113
+
114
#define MM_PMC_CRP 0xf1260000U
115
#define MM_PMC_CRP_SIZE 0x10000
116
#define MM_PMC_RTC 0xf12a0000
117
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/arm/xlnx-versal.c
120
+++ b/hw/arm/xlnx-versal.c
121
@@ -XXX,XX +XXX,XX @@
122
#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
123
#define GEM_REVISION 0x40070106
124
125
-#define VERSAL_NUM_PMC_APB_IRQS 3
126
+#define VERSAL_NUM_PMC_APB_IRQS 18
127
#define NUM_OSPI_IRQ_LINES 3
128
129
static void versal_create_apu_cpus(Versal *s)
130
@@ -XXX,XX +XXX,XX @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic)
131
* - RTC
132
* - BBRAM
133
* - PMC SLCR
134
+ * - CFRAME regs (input 3 - 17 to the orgate)
135
*/
136
object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
137
&s->pmc.apb_irq_orgate, TYPE_OR_IRQ);
138
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
139
static void versal_create_cfu(Versal *s, qemu_irq *pic)
140
{
141
SysBusDevice *sbd;
142
+ DeviceState *dev;
143
+ int i;
144
+ const struct {
145
+ uint64_t reg_base;
146
+ uint64_t fdri_base;
147
+ } cframe_addr[] = {
148
+ { MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
149
+ { MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
150
+ { MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
151
+ { MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
152
+ { MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
153
+ { MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
154
+ { MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
155
+ { MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
156
+ { MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
157
+ { MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
158
+ { MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
159
+ { MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
160
+ { MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
161
+ { MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
162
+ { MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
163
+ };
164
+ const struct {
165
+ uint32_t blktype0_frames;
166
+ uint32_t blktype1_frames;
167
+ uint32_t blktype2_frames;
168
+ uint32_t blktype3_frames;
169
+ uint32_t blktype4_frames;
170
+ uint32_t blktype5_frames;
171
+ uint32_t blktype6_frames;
172
+ } cframe_cfg[] = {
173
+ [0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
174
+ [1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
175
+ [2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
176
+ [3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
177
+ };
178
179
/* CFU FDRO */
180
object_initialize_child(OBJECT(s), "cfu-fdro", &s->pmc.cfu_fdro,
181
@@ -XXX,XX +XXX,XX @@ static void versal_create_cfu(Versal *s, qemu_irq *pic)
182
memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_FDRO,
183
sysbus_mmio_get_region(sbd, 0));
184
185
+ /* CFRAME REG */
186
+ for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
187
+ g_autofree char *name = g_strdup_printf("cframe%d", i);
188
+
189
+ object_initialize_child(OBJECT(s), name, &s->pmc.cframe[i],
190
+ TYPE_XLNX_VERSAL_CFRAME_REG);
191
+
192
+ sbd = SYS_BUS_DEVICE(&s->pmc.cframe[i]);
193
+ dev = DEVICE(&s->pmc.cframe[i]);
194
+
195
+ if (i < ARRAY_SIZE(cframe_cfg)) {
196
+ object_property_set_int(OBJECT(dev), "blktype0-frames",
197
+ cframe_cfg[i].blktype0_frames,
198
+ &error_abort);
199
+ object_property_set_int(OBJECT(dev), "blktype1-frames",
200
+ cframe_cfg[i].blktype1_frames,
201
+ &error_abort);
202
+ object_property_set_int(OBJECT(dev), "blktype2-frames",
203
+ cframe_cfg[i].blktype2_frames,
204
+ &error_abort);
205
+ object_property_set_int(OBJECT(dev), "blktype3-frames",
206
+ cframe_cfg[i].blktype3_frames,
207
+ &error_abort);
208
+ object_property_set_int(OBJECT(dev), "blktype4-frames",
209
+ cframe_cfg[i].blktype4_frames,
210
+ &error_abort);
211
+ object_property_set_int(OBJECT(dev), "blktype5-frames",
212
+ cframe_cfg[i].blktype5_frames,
213
+ &error_abort);
214
+ object_property_set_int(OBJECT(dev), "blktype6-frames",
215
+ cframe_cfg[i].blktype6_frames,
216
+ &error_abort);
217
+ }
218
+ object_property_set_link(OBJECT(dev), "cfu-fdro",
219
+ OBJECT(&s->pmc.cfu_fdro), &error_fatal);
220
+
221
+ sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
222
+
223
+ memory_region_add_subregion(&s->mr_ps, cframe_addr[i].reg_base,
224
+ sysbus_mmio_get_region(sbd, 0));
225
+ memory_region_add_subregion(&s->mr_ps, cframe_addr[i].fdri_base,
226
+ sysbus_mmio_get_region(sbd, 1));
227
+ sysbus_connect_irq(sbd, 0,
228
+ qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate),
229
+ 3 + i));
230
+ }
231
+
232
+ /* CFRAME BCAST */
233
+ object_initialize_child(OBJECT(s), "cframe_bcast", &s->pmc.cframe_bcast,
234
+ TYPE_XLNX_VERSAL_CFRAME_BCAST_REG);
235
+
236
+ sbd = SYS_BUS_DEVICE(&s->pmc.cframe_bcast);
237
+ dev = DEVICE(&s->pmc.cframe_bcast);
238
+
239
+ for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
240
+ g_autofree char *propname = g_strdup_printf("cframe%d", i);
241
+ object_property_set_link(OBJECT(dev), propname,
242
+ OBJECT(&s->pmc.cframe[i]), &error_fatal);
243
+ }
244
+
245
+ sysbus_realize(sbd, &error_fatal);
246
+
247
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFRAME_BCAST_REG,
248
+ sysbus_mmio_get_region(sbd, 0));
249
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFRAME_BCAST_FDRI,
250
+ sysbus_mmio_get_region(sbd, 1));
251
+
252
/* CFU APB */
253
object_initialize_child(OBJECT(s), "cfu-apb", &s->pmc.cfu_apb,
254
TYPE_XLNX_VERSAL_CFU_APB);
255
sbd = SYS_BUS_DEVICE(&s->pmc.cfu_apb);
256
+ dev = DEVICE(&s->pmc.cfu_apb);
257
+
258
+ for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
259
+ g_autofree char *propname = g_strdup_printf("cframe%d", i);
260
+ object_property_set_link(OBJECT(dev), propname,
261
+ OBJECT(&s->pmc.cframe[i]), &error_fatal);
262
+ }
263
264
sysbus_realize(sbd, &error_fatal);
265
memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_APB,
266
--
267
2.34.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
STGP writes to tag memory, it does not check it.
4
This happened to work because we wrote tag memory first
5
so that the check always succeeded.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230901203103.136408-1-richard.henderson@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/tcg/translate-a64.c | 41 +++++++++++++---------------------
13
1 file changed, 15 insertions(+), 26 deletions(-)
14
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate-a64.c
18
+++ b/target/arm/tcg/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
20
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
21
}
22
23
- if (!s->ata) {
24
- /*
25
- * TODO: We could rely on the stores below, at least for
26
- * system mode, if we arrange to add MO_ALIGN_16.
27
- */
28
- gen_helper_stg_stub(cpu_env, dirty_addr);
29
- } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
30
- gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
31
- } else {
32
- gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
33
- }
34
-
35
- mop = finalize_memop(s, MO_64);
36
- clean_addr = gen_mte_checkN(s, dirty_addr, true, false, 2 << MO_64, mop);
37
-
38
+ clean_addr = clean_data_tbi(s, dirty_addr);
39
tcg_rt = cpu_reg(s, a->rt);
40
tcg_rt2 = cpu_reg(s, a->rt2);
41
42
/*
43
- * STGP is defined as two 8-byte memory operations and one tag operation.
44
- * We implement it as one single 16-byte memory operation for convenience.
45
- * Rebuild mop as for STP.
46
- * TODO: The atomicity with LSE2 is stronger than required.
47
- * Need a form of MO_ATOM_WITHIN16_PAIR that never requires
48
- * 16-byte atomicity.
49
+ * STGP is defined as two 8-byte memory operations, aligned to TAG_GRANULE,
50
+ * and one tag operation. We implement it as one single aligned 16-byte
51
+ * memory operation for convenience. Note that the alignment ensures
52
+ * MO_ATOM_IFALIGN_PAIR produces 8-byte atomicity for the memory store.
53
*/
54
- mop = MO_128;
55
- if (s->align_mem) {
56
- mop |= MO_ALIGN_8;
57
- }
58
- mop = finalize_memop_pair(s, mop);
59
+ mop = finalize_memop_atom(s, MO_128 | MO_ALIGN, MO_ATOM_IFALIGN_PAIR);
60
61
tmp = tcg_temp_new_i128();
62
if (s->be_data == MO_LE) {
63
@@ -XXX,XX +XXX,XX @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
64
}
65
tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
66
67
+ /* Perform the tag store, if tag access enabled. */
68
+ if (s->ata) {
69
+ if (tb_cflags(s->base.tb) & CF_PARALLEL) {
70
+ gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
71
+ } else {
72
+ gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
73
+ }
74
+ }
75
+
76
op_addr_ldstpair_post(s, a, dirty_addr, offset);
77
return true;
78
}
79
--
80
2.34.1
diff view generated by jsdifflib
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1
From: Colton Lewis <coltonlewis@google.com>
2
2
3
The 'vmstate_smmuv3_queue' is missing the end-of-list marker.
3
Due to recent KVM changes, QEMU is setting a ptimer offset resulting
4
in unintended trap and emulate access and a consequent performance
5
hit. Filter out the PTIMER_CNT register to restore trapless ptimer
6
access.
4
7
5
Fixes: 10a83cb9887
8
Quoting Andrew Jones:
6
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9
7
Message-id: 20180727135406.15132-1-dgilbert@redhat.com
10
Simply reading the CNT register and writing back the same value is
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
enough to set an offset, since the timer will have certainly moved
9
[PMM: dropped stray blank line]
12
past whatever value was read by the time it's written. QEMU
13
frequently saves and restores all registers in the get-reg-list array,
14
unless they've been explicitly filtered out (with Linux commit
15
680232a94c12, KVM_REG_ARM_PTIMER_CNT is now in the array). So, to
16
restore trapless ptimer accesses, we need a QEMU patch to filter out
17
the register.
18
19
See
20
https://lore.kernel.org/kvmarm/gsntttsonus5.fsf@coltonlewis-kvm.c.googlers.com/T/#m0770023762a821db2a3f0dd0a7dc6aa54e0d0da9
21
for additional context.
22
23
Cc: qemu-stable@nongnu.org
24
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
25
Signed-off-by: Colton Lewis <coltonlewis@google.com>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Tested-by: Colton Lewis <coltonlewis@google.com>
28
Message-id: 20230831190052.129045-1-coltonlewis@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
30
---
12
hw/arm/smmuv3.c | 1 +
31
target/arm/kvm64.c | 1 +
13
1 file changed, 1 insertion(+)
32
1 file changed, 1 insertion(+)
14
33
15
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
34
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
16
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/smmuv3.c
36
--- a/target/arm/kvm64.c
18
+++ b/hw/arm/smmuv3.c
37
+++ b/target/arm/kvm64.c
19
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_smmuv3_queue = {
38
@@ -XXX,XX +XXX,XX @@ typedef struct CPRegStateLevel {
20
VMSTATE_UINT32(prod, SMMUQueue),
39
*/
21
VMSTATE_UINT32(cons, SMMUQueue),
40
static const CPRegStateLevel non_runtime_cpregs[] = {
22
VMSTATE_UINT8(log2size, SMMUQueue),
41
{ KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
23
+ VMSTATE_END_OF_LIST(),
42
+ { KVM_REG_ARM_PTIMER_CNT, KVM_PUT_FULL_STATE },
24
},
25
};
43
};
26
44
45
int kvm_arm_cpreg_level(uint64_t regidx)
27
--
46
--
28
2.17.1
47
2.34.1
29
30
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Since 86f0a186d6f the TYPE_ARM_HOST_CPU is only compiled when CONFIG_KVM
3
Provide a stub implementation, as a write is a "request".
4
is enabled.
5
4
6
Remove the now redundant special-case introduced in a96c0514ab7, to avoid:
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
6
Message-id: 20230831232441.66020-2-richard.henderson@linaro.org
8
$ qemu-system-aarch64 -machine virt -cpu \? | fgrep host
9
host
10
host (only available in KVM mode)
11
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20180727132311.2777-1-f4bug@amsat.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
9
---
17
target/arm/helper.c | 6 ------
10
target/arm/helper.c | 64 +++++++++++++++++++++++++++++----------------
18
1 file changed, 6 deletions(-)
11
1 file changed, 41 insertions(+), 23 deletions(-)
19
12
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
15
--- a/target/arm/helper.c
23
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
17
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
25
(*cpu_fprintf)(f, "Available CPUs:\n");
18
};
26
g_slist_foreach(list, arm_cpu_list_entry, &s);
19
modify_arm_cp_regs(v8_idregs, v8_user_idregs);
27
g_slist_free(list);
20
#endif
28
-#ifdef CONFIG_KVM
21
- /* RVBAR_EL1 is only implemented if EL1 is the highest EL */
29
- /* The 'host' CPU type is dynamically registered only if KVM is
22
+ /*
30
- * enabled, so we have to special-case it here:
23
+ * RVBAR_EL1 and RMR_EL1 only implemented if EL1 is the highest EL.
31
- */
24
+ * TODO: For RMR, a write with bit 1 set should do something with
32
- (*cpu_fprintf)(f, " host (only available in KVM mode)\n");
25
+ * cpu_reset(). In the meantime, "the bit is strictly a request",
33
-#endif
26
+ * so we are in spec just ignoring writes.
34
}
27
+ */
35
28
if (!arm_feature(env, ARM_FEATURE_EL3) &&
36
static void arm_cpu_add_definition(gpointer data, gpointer user_data)
29
!arm_feature(env, ARM_FEATURE_EL2)) {
30
- ARMCPRegInfo rvbar = {
31
- .name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
32
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
33
- .access = PL1_R,
34
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
35
+ ARMCPRegInfo el1_reset_regs[] = {
36
+ { .name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
37
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
38
+ .access = PL1_R,
39
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
40
+ { .name = "RMR_EL1", .state = ARM_CP_STATE_BOTH,
41
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 2,
42
+ .access = PL1_RW, .type = ARM_CP_CONST,
43
+ .resetvalue = arm_feature(env, ARM_FEATURE_AARCH64) }
44
};
45
- define_one_arm_cp_reg(cpu, &rvbar);
46
+ define_arm_cp_regs(cpu, el1_reset_regs);
47
}
48
define_arm_cp_regs(cpu, v8_idregs);
49
define_arm_cp_regs(cpu, v8_cp_reginfo);
50
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
51
if (cpu_isar_feature(aa64_sel2, cpu)) {
52
define_arm_cp_regs(cpu, el2_sec_cp_reginfo);
53
}
54
- /* RVBAR_EL2 is only implemented if EL2 is the highest EL */
55
+ /*
56
+ * RVBAR_EL2 and RMR_EL2 only implemented if EL2 is the highest EL.
57
+ * See commentary near RMR_EL1.
58
+ */
59
if (!arm_feature(env, ARM_FEATURE_EL3)) {
60
- ARMCPRegInfo rvbar[] = {
61
- {
62
- .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
63
- .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
64
- .access = PL2_R,
65
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
66
- },
67
- { .name = "RVBAR", .type = ARM_CP_ALIAS,
68
- .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
69
- .access = PL2_R,
70
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
71
- },
72
+ static const ARMCPRegInfo el2_reset_regs[] = {
73
+ { .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
74
+ .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
75
+ .access = PL2_R,
76
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
77
+ { .name = "RVBAR", .type = ARM_CP_ALIAS,
78
+ .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
79
+ .access = PL2_R,
80
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
81
+ { .name = "RMR_EL2", .state = ARM_CP_STATE_AA64,
82
+ .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 2,
83
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 1 },
84
};
85
- define_arm_cp_regs(cpu, rvbar);
86
+ define_arm_cp_regs(cpu, el2_reset_regs);
87
}
88
}
89
90
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
91
{ .name = "RVBAR_EL3", .state = ARM_CP_STATE_AA64,
92
.opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 1,
93
.access = PL3_R,
94
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
95
- },
96
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar), },
97
+ { .name = "RMR_EL3", .state = ARM_CP_STATE_AA64,
98
+ .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 2,
99
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 1 },
100
+ { .name = "RMR", .state = ARM_CP_STATE_AA32,
101
+ .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 2,
102
+ .access = PL3_RW, .type = ARM_CP_CONST,
103
+ .resetvalue = arm_feature(env, ARM_FEATURE_AARCH64) },
104
{ .name = "SCTLR_EL3", .state = ARM_CP_STATE_AA64,
105
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 0,
106
.access = PL3_RW,
37
--
107
--
38
2.17.1
108
2.34.1
39
40
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The cortex-a710 is a first generation ARMv9.0-A processor.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230831232441.66020-3-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
docs/system/arm/virt.rst | 1 +
11
hw/arm/virt.c | 1 +
12
target/arm/tcg/cpu64.c | 212 +++++++++++++++++++++++++++++++++++++++
13
3 files changed, 214 insertions(+)
14
15
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/arm/virt.rst
18
+++ b/docs/system/arm/virt.rst
19
@@ -XXX,XX +XXX,XX @@ Supported guest CPU types:
20
- ``cortex-a57`` (64-bit)
21
- ``cortex-a72`` (64-bit)
22
- ``cortex-a76`` (64-bit)
23
+- ``cortex-a710`` (64-bit)
24
- ``a64fx`` (64-bit)
25
- ``host`` (with KVM only)
26
- ``neoverse-n1`` (64-bit)
27
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/virt.c
30
+++ b/hw/arm/virt.c
31
@@ -XXX,XX +XXX,XX @@ static const char *valid_cpus[] = {
32
ARM_CPU_TYPE_NAME("cortex-a55"),
33
ARM_CPU_TYPE_NAME("cortex-a72"),
34
ARM_CPU_TYPE_NAME("cortex-a76"),
35
+ ARM_CPU_TYPE_NAME("cortex-a710"),
36
ARM_CPU_TYPE_NAME("a64fx"),
37
ARM_CPU_TYPE_NAME("neoverse-n1"),
38
ARM_CPU_TYPE_NAME("neoverse-v1"),
39
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/tcg/cpu64.c
42
+++ b/target/arm/tcg/cpu64.c
43
@@ -XXX,XX +XXX,XX @@ static void aarch64_neoverse_v1_initfn(Object *obj)
44
aarch64_add_sve_properties(obj);
45
}
46
47
+static const ARMCPRegInfo cortex_a710_cp_reginfo[] = {
48
+ { .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
49
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 0,
50
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
51
+ .accessfn = access_actlr_w },
52
+ { .name = "CPUACTLR2_EL1", .state = ARM_CP_STATE_AA64,
53
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 1,
54
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
55
+ .accessfn = access_actlr_w },
56
+ { .name = "CPUACTLR3_EL1", .state = ARM_CP_STATE_AA64,
57
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 2,
58
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
59
+ .accessfn = access_actlr_w },
60
+ { .name = "CPUACTLR4_EL1", .state = ARM_CP_STATE_AA64,
61
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 3,
62
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
63
+ .accessfn = access_actlr_w },
64
+ { .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
65
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 4,
66
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
67
+ .accessfn = access_actlr_w },
68
+ { .name = "CPUECTLR2_EL1", .state = ARM_CP_STATE_AA64,
69
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 5,
70
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
71
+ .accessfn = access_actlr_w },
72
+ { .name = "CPUPPMCR_EL3", .state = ARM_CP_STATE_AA64,
73
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 4,
74
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
75
+ { .name = "CPUPWRCTLR_EL1", .state = ARM_CP_STATE_AA64,
76
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 7,
77
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
78
+ .accessfn = access_actlr_w },
79
+ { .name = "ATCR_EL1", .state = ARM_CP_STATE_AA64,
80
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 7, .opc2 = 0,
81
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
82
+ { .name = "CPUACTLR5_EL1", .state = ARM_CP_STATE_AA64,
83
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 0,
84
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
85
+ .accessfn = access_actlr_w },
86
+ { .name = "CPUACTLR6_EL1", .state = ARM_CP_STATE_AA64,
87
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 1,
88
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
89
+ .accessfn = access_actlr_w },
90
+ { .name = "CPUACTLR7_EL1", .state = ARM_CP_STATE_AA64,
91
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 2,
92
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
93
+ .accessfn = access_actlr_w },
94
+ { .name = "ATCR_EL2", .state = ARM_CP_STATE_AA64,
95
+ .opc0 = 3, .opc1 = 4, .crn = 15, .crm = 7, .opc2 = 0,
96
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
97
+ { .name = "AVTCR_EL2", .state = ARM_CP_STATE_AA64,
98
+ .opc0 = 3, .opc1 = 4, .crn = 15, .crm = 7, .opc2 = 1,
99
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
100
+ { .name = "CPUPPMCR_EL3", .state = ARM_CP_STATE_AA64,
101
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 0,
102
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
103
+ { .name = "CPUPPMCR2_EL3", .state = ARM_CP_STATE_AA64,
104
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 1,
105
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
106
+ { .name = "CPUPPMCR4_EL3", .state = ARM_CP_STATE_AA64,
107
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 4,
108
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
109
+ { .name = "CPUPPMCR5_EL3", .state = ARM_CP_STATE_AA64,
110
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 5,
111
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
112
+ { .name = "CPUPPMCR6_EL3", .state = ARM_CP_STATE_AA64,
113
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 6,
114
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
115
+ { .name = "CPUACTLR_EL3", .state = ARM_CP_STATE_AA64,
116
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 4, .opc2 = 0,
117
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
118
+ { .name = "ATCR_EL3", .state = ARM_CP_STATE_AA64,
119
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 7, .opc2 = 0,
120
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
121
+ { .name = "CPUPSELR_EL3", .state = ARM_CP_STATE_AA64,
122
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 0,
123
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
124
+ { .name = "CPUPCR_EL3", .state = ARM_CP_STATE_AA64,
125
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 1,
126
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
127
+ { .name = "CPUPOR_EL3", .state = ARM_CP_STATE_AA64,
128
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 2,
129
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
130
+ { .name = "CPUPMR_EL3", .state = ARM_CP_STATE_AA64,
131
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 3,
132
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
133
+ { .name = "CPUPOR2_EL3", .state = ARM_CP_STATE_AA64,
134
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 4,
135
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
136
+ { .name = "CPUPMR2_EL3", .state = ARM_CP_STATE_AA64,
137
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 5,
138
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
139
+ { .name = "CPUPFR_EL3", .state = ARM_CP_STATE_AA64,
140
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 6,
141
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
142
+
143
+ /*
144
+ * Stub RAMINDEX, as we don't actually implement caches, BTB,
145
+ * or anything else with cpu internal memory.
146
+ * "Read" zeros into the IDATA* and DDATA* output registers.
147
+ */
148
+ { .name = "RAMINDEX_EL3", .state = ARM_CP_STATE_AA64,
149
+ .opc0 = 1, .opc1 = 6, .crn = 15, .crm = 0, .opc2 = 0,
150
+ .access = PL3_W, .type = ARM_CP_CONST, .resetvalue = 0 },
151
+ { .name = "IDATA0_EL3", .state = ARM_CP_STATE_AA64,
152
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 0, .opc2 = 0,
153
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
154
+ { .name = "IDATA1_EL3", .state = ARM_CP_STATE_AA64,
155
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 0, .opc2 = 1,
156
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
157
+ { .name = "IDATA2_EL3", .state = ARM_CP_STATE_AA64,
158
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 0, .opc2 = 2,
159
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
160
+ { .name = "DDATA0_EL3", .state = ARM_CP_STATE_AA64,
161
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 1, .opc2 = 0,
162
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
163
+ { .name = "DDATA1_EL3", .state = ARM_CP_STATE_AA64,
164
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 1, .opc2 = 1,
165
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
166
+ { .name = "DDATA2_EL3", .state = ARM_CP_STATE_AA64,
167
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 1, .opc2 = 2,
168
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
169
+};
170
+
171
+static void aarch64_a710_initfn(Object *obj)
172
+{
173
+ ARMCPU *cpu = ARM_CPU(obj);
174
+
175
+ cpu->dtb_compatible = "arm,cortex-a710";
176
+ set_feature(&cpu->env, ARM_FEATURE_V8);
177
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
178
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
179
+ set_feature(&cpu->env, ARM_FEATURE_AARCH64);
180
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
181
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
182
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
183
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
184
+
185
+ /* Ordered by Section B.4: AArch64 registers */
186
+ cpu->midr = 0x412FD471; /* r2p1 */
187
+ cpu->revidr = 0;
188
+ cpu->isar.id_pfr0 = 0x21110131;
189
+ cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */
190
+ cpu->isar.id_dfr0 = 0x16011099;
191
+ cpu->id_afr0 = 0;
192
+ cpu->isar.id_mmfr0 = 0x10201105;
193
+ cpu->isar.id_mmfr1 = 0x40000000;
194
+ cpu->isar.id_mmfr2 = 0x01260000;
195
+ cpu->isar.id_mmfr3 = 0x02122211;
196
+ cpu->isar.id_isar0 = 0x02101110;
197
+ cpu->isar.id_isar1 = 0x13112111;
198
+ cpu->isar.id_isar2 = 0x21232042;
199
+ cpu->isar.id_isar3 = 0x01112131;
200
+ cpu->isar.id_isar4 = 0x00010142;
201
+ cpu->isar.id_isar5 = 0x11011121; /* with Crypto */
202
+ cpu->isar.id_mmfr4 = 0x21021110;
203
+ cpu->isar.id_isar6 = 0x01111111;
204
+ cpu->isar.mvfr0 = 0x10110222;
205
+ cpu->isar.mvfr1 = 0x13211111;
206
+ cpu->isar.mvfr2 = 0x00000043;
207
+ cpu->isar.id_pfr2 = 0x00000011;
208
+ cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */
209
+ cpu->isar.id_aa64pfr1 = 0x0000000000000221ull;
210
+ cpu->isar.id_aa64zfr0 = 0x0000110100110021ull; /* with Crypto */
211
+ cpu->isar.id_aa64dfr0 = 0x000011f010305611ull;
212
+ cpu->isar.id_aa64dfr1 = 0;
213
+ cpu->id_aa64afr0 = 0;
214
+ cpu->id_aa64afr1 = 0;
215
+ cpu->isar.id_aa64isar0 = 0x0221111110212120ull; /* with Crypto */
216
+ cpu->isar.id_aa64isar1 = 0x0010111101211032ull;
217
+ cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull;
218
+ cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
219
+ cpu->isar.id_aa64mmfr2 = 0x1221011110101011ull;
220
+ cpu->clidr = 0x0000001482000023ull;
221
+ cpu->gm_blocksize = 4;
222
+ cpu->ctr = 0x000000049444c004ull;
223
+ cpu->dcz_blocksize = 4;
224
+ /* TODO FEAT_MPAM: mpamidr_el1 = 0x0000_0001_0006_003f */
225
+
226
+ /* Section B.5.2: PMCR_EL0 */
227
+ cpu->isar.reset_pmcr_el0 = 0xa000; /* with 20 counters */
228
+
229
+ /* Section B.6.7: ICH_VTR_EL2 */
230
+ cpu->gic_num_lrs = 4;
231
+ cpu->gic_vpribits = 5;
232
+ cpu->gic_vprebits = 5;
233
+ cpu->gic_pribits = 5;
234
+
235
+ /* Section 14: Scalable Vector Extensions support */
236
+ cpu->sve_vq.supported = 1 << 0; /* 128bit */
237
+
238
+ /*
239
+ * The cortex-a710 TRM does not list CCSIDR values. The layout of
240
+ * the caches are in text in Table 7-1, Table 8-1, and Table 9-1.
241
+ *
242
+ * L1: 4-way set associative 64-byte line size, total either 32K or 64K.
243
+ * L2: 8-way set associative 64 byte line size, total either 256K or 512K.
244
+ */
245
+ cpu->ccsidr[0] = make_ccsidr64(4, 64, 64 * KiB); /* L1 dcache */
246
+ cpu->ccsidr[1] = cpu->ccsidr[0]; /* L1 icache */
247
+ cpu->ccsidr[2] = make_ccsidr64(8, 64, 512 * KiB); /* L2 cache */
248
+
249
+ /* FIXME: Not documented -- copied from neoverse-v1 */
250
+ cpu->reset_sctlr = 0x30c50838;
251
+
252
+ define_arm_cp_regs(cpu, cortex_a710_cp_reginfo);
253
+
254
+ aarch64_add_pauth_properties(obj);
255
+ aarch64_add_sve_properties(obj);
256
+}
257
+
258
/*
259
* -cpu max: a CPU with as many features enabled as our emulation supports.
260
* The version of '-cpu max' for qemu-system-arm is defined in cpu32.c;
261
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo aarch64_cpus[] = {
262
{ .name = "cortex-a55", .initfn = aarch64_a55_initfn },
263
{ .name = "cortex-a72", .initfn = aarch64_a72_initfn },
264
{ .name = "cortex-a76", .initfn = aarch64_a76_initfn },
265
+ { .name = "cortex-a710", .initfn = aarch64_a710_initfn },
266
{ .name = "a64fx", .initfn = aarch64_a64fx_initfn },
267
{ .name = "neoverse-n1", .initfn = aarch64_neoverse_n1_initfn },
268
{ .name = "neoverse-v1", .initfn = aarch64_neoverse_v1_initfn },
269
--
270
2.34.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Perform the check for EL2 enabled in the security space and the
4
TIDCP bit in an out-of-line helper.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230831232441.66020-4-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.h | 1 +
12
target/arm/tcg/op_helper.c | 13 +++++++++++++
13
target/arm/tcg/translate-a64.c | 16 ++++++++++++++--
14
target/arm/tcg/translate.c | 27 +++++++++++++++++++++++++++
15
4 files changed, 55 insertions(+), 2 deletions(-)
16
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
20
+++ b/target/arm/helper.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, i32)
22
23
DEF_HELPER_4(access_check_cp_reg, cptr, env, i32, i32, i32)
24
DEF_HELPER_FLAGS_2(lookup_cp_reg, TCG_CALL_NO_RWG_SE, cptr, env, i32)
25
+DEF_HELPER_FLAGS_2(tidcp_el1, TCG_CALL_NO_WG, void, env, i32)
26
DEF_HELPER_3(set_cp_reg, void, env, cptr, i32)
27
DEF_HELPER_2(get_cp_reg, i32, env, cptr)
28
DEF_HELPER_3(set_cp_reg64, void, env, cptr, i64)
29
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/tcg/op_helper.c
32
+++ b/target/arm/tcg/op_helper.c
33
@@ -XXX,XX +XXX,XX @@ const void *HELPER(lookup_cp_reg)(CPUARMState *env, uint32_t key)
34
return ri;
35
}
36
37
+/*
38
+ * Test for HCR_EL2.TIDCP at EL1.
39
+ * Since implementation defined registers are rare, and within QEMU
40
+ * most of them are no-op, do not waste HFLAGS space for this and
41
+ * always use a helper.
42
+ */
43
+void HELPER(tidcp_el1)(CPUARMState *env, uint32_t syndrome)
44
+{
45
+ if (arm_hcr_el2_eff(env) & HCR_TIDCP) {
46
+ raise_exception_ra(env, EXCP_UDEF, syndrome, 2, GETPC());
47
+ }
48
+}
49
+
50
void HELPER(set_cp_reg)(CPUARMState *env, const void *rip, uint32_t value)
51
{
52
const ARMCPRegInfo *ri = rip;
53
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/tcg/translate-a64.c
56
+++ b/target/arm/tcg/translate-a64.c
57
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, bool isread,
58
bool need_exit_tb = false;
59
TCGv_ptr tcg_ri = NULL;
60
TCGv_i64 tcg_rt;
61
+ uint32_t syndrome;
62
+
63
+ if (crn == 11 || crn == 15) {
64
+ /*
65
+ * Check for TIDCP trap, which must take precedence over
66
+ * the UNDEF for "no such register" etc.
67
+ */
68
+ syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
69
+ switch (s->current_el) {
70
+ case 1:
71
+ gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
72
+ break;
73
+ }
74
+ }
75
76
if (!ri) {
77
/* Unknown register; this might be a guest error or a QEMU
78
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, bool isread,
79
/* Emit code to perform further access permissions checks at
80
* runtime; this may result in an exception.
81
*/
82
- uint32_t syndrome;
83
-
84
syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
85
gen_a64_update_pc(s, 0);
86
tcg_ri = tcg_temp_new_ptr();
87
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/tcg/translate.c
90
+++ b/target/arm/tcg/translate.c
91
@@ -XXX,XX +XXX,XX @@ void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
92
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
93
}
94
95
+static bool aa32_cpreg_encoding_in_impdef_space(uint8_t crn, uint8_t crm)
96
+{
97
+ static const uint16_t mask[3] = {
98
+ 0b0000000111100111, /* crn == 9, crm == {c0-c2, c5-c8} */
99
+ 0b0000000100010011, /* crn == 10, crm == {c0, c1, c4, c8} */
100
+ 0b1000000111111111, /* crn == 11, crm == {c0-c8, c15} */
101
+ };
102
+
103
+ if (crn >= 9 && crn <= 11) {
104
+ return (mask[crn - 9] >> crm) & 1;
105
+ }
106
+ return false;
107
+}
108
+
109
static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
110
int opc1, int crn, int crm, int opc2,
111
bool isread, int rt, int rt2)
112
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
113
}
114
}
115
116
+ if (cpnum == 15 && aa32_cpreg_encoding_in_impdef_space(crn, crm)) {
117
+ /*
118
+ * Check for TIDCP trap, which must take precedence over the UNDEF
119
+ * for "no such register" etc. It shares precedence with HSTR,
120
+ * but raises the same exception, so order doesn't matter.
121
+ */
122
+ switch (s->current_el) {
123
+ case 1:
124
+ gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
125
+ break;
126
+ }
127
+ }
128
+
129
if (!ri) {
130
/*
131
* Unknown register; this might be a guest error or a QEMU
132
--
133
2.34.1
diff view generated by jsdifflib
1
From: Geert Uytterhoeven <geert+renesas@glider.be>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
When copy_properties_from_host() ignores the error for an optional
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
property, it frees the error, but fails to reset it.
4
Message-id: 20230831232441.66020-5-richard.henderson@linaro.org
5
6
Hence if two or more optional properties are missing, an assertion is
7
triggered:
8
9
util/error.c:57: error_setv: Assertion `*errp == NULL' failed.
10
11
Fis this by resetting err to NULL after ignoring the error.
12
13
Fixes: 9481cf2e5f2f2bb6 ("hw/arm/sysbus-fdt: helpers for clock node generation")
14
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
15
Message-id: 20180725113000.11014-1-geert+renesas@glider.be
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
7
---
19
hw/arm/sysbus-fdt.c | 1 +
8
docs/system/arm/emulation.rst | 1 +
20
1 file changed, 1 insertion(+)
9
target/arm/cpu.h | 5 +++++
10
target/arm/helper.h | 1 +
11
target/arm/tcg/cpu64.c | 1 +
12
target/arm/tcg/op_helper.c | 20 ++++++++++++++++++++
13
target/arm/tcg/translate-a64.c | 5 +++++
14
target/arm/tcg/translate.c | 6 ++++++
15
7 files changed, 39 insertions(+)
21
16
22
diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
23
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/arm/sysbus-fdt.c
19
--- a/docs/system/arm/emulation.rst
25
+++ b/hw/arm/sysbus-fdt.c
20
+++ b/docs/system/arm/emulation.rst
26
@@ -XXX,XX +XXX,XX @@ static void copy_properties_from_host(HostProperty *props, int nb_props,
21
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
27
/* mandatory property not found: bail out */
22
- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
28
exit(1);
23
- FEAT_SPECRES (Speculation restriction instructions)
29
}
24
- FEAT_SSBS (Speculative Store Bypass Safe)
30
+ err = NULL;
25
+- FEAT_TIDCP1 (EL0 use of IMPLEMENTATION DEFINED functionality)
31
}
26
- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
27
- FEAT_TLBIRANGE (TLB invalidate range instructions)
28
- FEAT_TTCNP (Translation table Common not private translations)
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.h
32
+++ b/target/arm/cpu.h
33
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
35
}
36
37
+static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
38
+{
39
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0;
40
+}
41
+
42
static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
43
{
44
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
45
diff --git a/target/arm/helper.h b/target/arm/helper.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/helper.h
48
+++ b/target/arm/helper.h
49
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, i32)
50
51
DEF_HELPER_4(access_check_cp_reg, cptr, env, i32, i32, i32)
52
DEF_HELPER_FLAGS_2(lookup_cp_reg, TCG_CALL_NO_RWG_SE, cptr, env, i32)
53
+DEF_HELPER_FLAGS_2(tidcp_el0, TCG_CALL_NO_WG, void, env, i32)
54
DEF_HELPER_FLAGS_2(tidcp_el1, TCG_CALL_NO_WG, void, env, i32)
55
DEF_HELPER_3(set_cp_reg, void, env, cptr, i32)
56
DEF_HELPER_2(get_cp_reg, i32, env, cptr)
57
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/tcg/cpu64.c
60
+++ b/target/arm/tcg/cpu64.c
61
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
62
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
63
t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */
64
t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */
65
+ t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1); /* FEAT_TIDCP1 */
66
cpu->isar.id_aa64mmfr1 = t;
67
68
t = cpu->isar.id_aa64mmfr2;
69
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/tcg/op_helper.c
72
+++ b/target/arm/tcg/op_helper.c
73
@@ -XXX,XX +XXX,XX @@ void HELPER(tidcp_el1)(CPUARMState *env, uint32_t syndrome)
32
}
74
}
33
}
75
}
76
77
+/*
78
+ * Similarly, for FEAT_TIDCP1 at EL0.
79
+ * We have already checked for the presence of the feature.
80
+ */
81
+void HELPER(tidcp_el0)(CPUARMState *env, uint32_t syndrome)
82
+{
83
+ /* See arm_sctlr(), but we also need the sctlr el. */
84
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
85
+ int target_el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
86
+
87
+ /*
88
+ * The bit is not valid unless the target el is aa64, but since the
89
+ * bit test is simpler perform that first and check validity after.
90
+ */
91
+ if ((env->cp15.sctlr_el[target_el] & SCTLR_TIDCP)
92
+ && arm_el_is_aa64(env, target_el)) {
93
+ raise_exception_ra(env, EXCP_UDEF, syndrome, target_el, GETPC());
94
+ }
95
+}
96
+
97
void HELPER(set_cp_reg)(CPUARMState *env, const void *rip, uint32_t value)
98
{
99
const ARMCPRegInfo *ri = rip;
100
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/target/arm/tcg/translate-a64.c
103
+++ b/target/arm/tcg/translate-a64.c
104
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, bool isread,
105
*/
106
syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
107
switch (s->current_el) {
108
+ case 0:
109
+ if (dc_isar_feature(aa64_tidcp1, s)) {
110
+ gen_helper_tidcp_el0(cpu_env, tcg_constant_i32(syndrome));
111
+ }
112
+ break;
113
case 1:
114
gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
115
break;
116
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/target/arm/tcg/translate.c
119
+++ b/target/arm/tcg/translate.c
120
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
121
* but raises the same exception, so order doesn't matter.
122
*/
123
switch (s->current_el) {
124
+ case 0:
125
+ if (arm_dc_feature(s, ARM_FEATURE_AARCH64)
126
+ && dc_isar_feature(aa64_tidcp1, s)) {
127
+ gen_helper_tidcp_el0(cpu_env, tcg_constant_i32(syndrome));
128
+ }
129
+ break;
130
case 1:
131
gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
132
break;
34
--
133
--
35
2.17.1
134
2.34.1
36
37
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The linux kernel detects and enables this bit. Once trapped,
4
EC_SYSTEMREGISTERTRAP is treated like EC_UNCATEGORIZED, so
5
no changes required within linux-user/aarch64/cpu_loop.c.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230831232441.66020-6-richard.henderson@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.c | 4 ++++
13
1 file changed, 4 insertions(+)
14
15
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.c
18
+++ b/target/arm/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset_hold(Object *obj)
20
SCTLR_EnDA | SCTLR_EnDB);
21
/* Trap on btype=3 for PACIxSP. */
22
env->cp15.sctlr_el[1] |= SCTLR_BT0;
23
+ /* Trap on implementation defined registers. */
24
+ if (cpu_isar_feature(aa64_tidcp1, cpu)) {
25
+ env->cp15.sctlr_el[1] |= SCTLR_TIDCP;
26
+ }
27
/* and to the FP/Neon instructions */
28
env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
29
CPACR_EL1, FPEN, 3);
30
--
31
2.34.1
diff view generated by jsdifflib
New patch
1
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
1
2
3
Now that we have Eager Page Split support added for ARM in the kernel,
4
enable it in Qemu. This adds,
5
-eager-split-size to -accel sub-options to set the eager page split chunk size.
6
-enable KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE.
7
8
The chunk size specifies how many pages to break at a time, using a
9
single allocation. Bigger the chunk size, more pages need to be
10
allocated ahead of time.
11
12
Reviewed-by: Gavin Shan <gshan@redhat.com>
13
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
14
Message-id: 20230905091246.1931-1-shameerali.kolothum.thodi@huawei.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
include/sysemu/kvm_int.h | 1 +
18
accel/kvm/kvm-all.c | 1 +
19
target/arm/kvm.c | 61 ++++++++++++++++++++++++++++++++++++++++
20
qemu-options.hx | 15 ++++++++++
21
4 files changed, 78 insertions(+)
22
23
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/sysemu/kvm_int.h
26
+++ b/include/sysemu/kvm_int.h
27
@@ -XXX,XX +XXX,XX @@ struct KVMState
28
uint64_t kvm_dirty_ring_bytes; /* Size of the per-vcpu dirty ring */
29
uint32_t kvm_dirty_ring_size; /* Number of dirty GFNs per ring */
30
bool kvm_dirty_ring_with_bitmap;
31
+ uint64_t kvm_eager_split_size; /* Eager Page Splitting chunk size */
32
struct KVMDirtyRingReaper reaper;
33
NotifyVmexitOption notify_vmexit;
34
uint32_t notify_window;
35
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/accel/kvm/kvm-all.c
38
+++ b/accel/kvm/kvm-all.c
39
@@ -XXX,XX +XXX,XX @@ static void kvm_accel_instance_init(Object *obj)
40
/* KVM dirty ring is by default off */
41
s->kvm_dirty_ring_size = 0;
42
s->kvm_dirty_ring_with_bitmap = false;
43
+ s->kvm_eager_split_size = 0;
44
s->notify_vmexit = NOTIFY_VMEXIT_OPTION_RUN;
45
s->notify_window = 0;
46
s->xen_version = 0;
47
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/kvm.c
50
+++ b/target/arm/kvm.c
51
@@ -XXX,XX +XXX,XX @@
52
#include "exec/address-spaces.h"
53
#include "hw/boards.h"
54
#include "hw/irq.h"
55
+#include "qapi/visitor.h"
56
#include "qemu/log.h"
57
58
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
59
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init(MachineState *ms, KVMState *s)
60
}
61
}
62
63
+ if (s->kvm_eager_split_size) {
64
+ uint32_t sizes;
65
+
66
+ sizes = kvm_vm_check_extension(s, KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES);
67
+ if (!sizes) {
68
+ s->kvm_eager_split_size = 0;
69
+ warn_report("Eager Page Split support not available");
70
+ } else if (!(s->kvm_eager_split_size & sizes)) {
71
+ error_report("Eager Page Split requested chunk size not valid");
72
+ ret = -EINVAL;
73
+ } else {
74
+ ret = kvm_vm_enable_cap(s, KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE, 0,
75
+ s->kvm_eager_split_size);
76
+ if (ret < 0) {
77
+ error_report("Enabling of Eager Page Split failed: %s",
78
+ strerror(-ret));
79
+ }
80
+ }
81
+ }
82
+
83
kvm_arm_init_debug(s);
84
85
return ret;
86
@@ -XXX,XX +XXX,XX @@ bool kvm_arch_cpu_check_are_resettable(void)
87
return true;
88
}
89
90
+static void kvm_arch_get_eager_split_size(Object *obj, Visitor *v,
91
+ const char *name, void *opaque,
92
+ Error **errp)
93
+{
94
+ KVMState *s = KVM_STATE(obj);
95
+ uint64_t value = s->kvm_eager_split_size;
96
+
97
+ visit_type_size(v, name, &value, errp);
98
+}
99
+
100
+static void kvm_arch_set_eager_split_size(Object *obj, Visitor *v,
101
+ const char *name, void *opaque,
102
+ Error **errp)
103
+{
104
+ KVMState *s = KVM_STATE(obj);
105
+ uint64_t value;
106
+
107
+ if (s->fd != -1) {
108
+ error_setg(errp, "Unable to set early-split-size after KVM has been initialized");
109
+ return;
110
+ }
111
+
112
+ if (!visit_type_size(v, name, &value, errp)) {
113
+ return;
114
+ }
115
+
116
+ if (value && !is_power_of_2(value)) {
117
+ error_setg(errp, "early-split-size must be a power of two");
118
+ return;
119
+ }
120
+
121
+ s->kvm_eager_split_size = value;
122
+}
123
+
124
void kvm_arch_accel_class_init(ObjectClass *oc)
125
{
126
+ object_class_property_add(oc, "eager-split-size", "size",
127
+ kvm_arch_get_eager_split_size,
128
+ kvm_arch_set_eager_split_size, NULL, NULL);
129
+
130
+ object_class_property_set_description(oc, "eager-split-size",
131
+ "Eager Page Split chunk size for hugepages. (default: 0, disabled)");
132
}
133
diff --git a/qemu-options.hx b/qemu-options.hx
134
index XXXXXXX..XXXXXXX 100644
135
--- a/qemu-options.hx
136
+++ b/qemu-options.hx
137
@@ -XXX,XX +XXX,XX @@ DEF("accel", HAS_ARG, QEMU_OPTION_accel,
138
" split-wx=on|off (enable TCG split w^x mapping)\n"
139
" tb-size=n (TCG translation block cache size)\n"
140
" dirty-ring-size=n (KVM dirty ring GFN count, default 0)\n"
141
+ " eager-split-size=n (KVM Eager Page Split chunk size, default 0, disabled. ARM only)\n"
142
" notify-vmexit=run|internal-error|disable,notify-window=n (enable notify VM exit and set notify window, x86 only)\n"
143
" thread=single|multi (enable multi-threaded TCG)\n", QEMU_ARCH_ALL)
144
SRST
145
@@ -XXX,XX +XXX,XX @@ SRST
146
is disabled (dirty-ring-size=0). When enabled, KVM will instead
147
record dirty pages in a bitmap.
148
149
+ ``eager-split-size=n``
150
+ KVM implements dirty page logging at the PAGE_SIZE granularity and
151
+ enabling dirty-logging on a huge-page requires breaking it into
152
+ PAGE_SIZE pages in the first place. KVM on ARM does this splitting
153
+ lazily by default. There are performance benefits in doing huge-page
154
+ split eagerly, especially in situations where TLBI costs associated
155
+ with break-before-make sequences are considerable and also if guest
156
+ workloads are read intensive. The size here specifies how many pages
157
+ to break at a time and needs to be a valid block size which is
158
+ 1GB/2MB/4KB, 32MB/16KB and 512MB/64KB for 4KB/16KB/64KB PAGE_SIZE
159
+ respectively. Be wary of specifying a higher size as it will have an
160
+ impact on the memory. By default, this feature is disabled
161
+ (eager-split-size=0).
162
+
163
``notify-vmexit=run|internal-error|disable,notify-window=n``
164
Enables or disables notify VM exit support on x86 host and specify
165
the corresponding notify window to trigger the VM exit if enabled.
166
--
167
2.34.1
diff view generated by jsdifflib