1
The following changes since commit 64ada298b98a51eb2512607f6e6180cb330c47b1:
1
Hi; here's the latest arm pullreq...
2
2
3
Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220302' into staging (2022-03-02 12:38:46 +0000)
3
-- PMM
4
5
The following changes since commit 03a3a62fbd0aa5227e978eef3c67d3978aec9e5f:
6
7
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2023-09-07 10:29:06 -0400)
4
8
5
are available in the Git repository at:
9
are available in the Git repository at:
6
10
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220302
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230908
8
12
9
for you to fetch changes up to 268c11984e67867c22f53beb3c7f8b98900d66b2:
13
for you to fetch changes up to c8f2eb5d414b788420b938f2ffdde891aa6c3ae8:
10
14
11
ui/cocoa.m: Remove unnecessary NSAutoreleasePools (2022-03-02 19:27:37 +0000)
15
arm/kvm: Enable support for KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE (2023-09-08 16:41:36 +0100)
12
16
13
----------------------------------------------------------------
17
----------------------------------------------------------------
14
target-arm queue:
18
target-arm queue:
15
* mps3-an547: Add missing user ahb interfaces
19
* New CPU type: cortex-a710
16
* hw/arm/mps2-tz.c: Update AN547 documentation URL
20
* Implement new architectural features:
17
* hw/input/tsc210x: Don't abort on bad SPI word widths
21
- FEAT_PACQARMA3
18
* hw/i2c: flatten pca954x mux device
22
- FEAT_EPAC
19
* target/arm: Support PSCI 1.1 and SMCCC 1.0
23
- FEAT_Pauth2
20
* target/arm: Fix early free of TCG temp in handle_simd_shift_fpint_conv()
24
- FEAT_FPAC
21
* tests/qtest: add qtests for npcm7xx sdhci
25
- FEAT_FPACCOMBINE
22
* Implement FEAT_LVA
26
- FEAT_TIDCP1
23
* Implement FEAT_LPA
27
* Xilinx Versal: Model the CFU/CFI
24
* Implement FEAT_LPA2 (but do not enable it yet)
28
* Implement RMR_ELx registers
25
* Report KVM's actual PSCI version to guest in dtb
29
* Implement handling of HCR_EL2.TIDCP trap bit
26
* ui/cocoa.m: Fix updateUIInfo threading issues
30
* arm/kvm: Enable support for KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE
27
* ui/cocoa.m: Remove unnecessary NSAutoreleasePools
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
Akihiko Odaki (1):
36
Aaron Lindsay (6):
31
target/arm: Support PSCI 1.1 and SMCCC 1.0
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
Jimmy Brisson (1):
44
Colton Lewis (1):
34
mps3-an547: Add missing user ahb interfaces
45
arm64: Restore trapless ptimer access
35
46
36
Patrick Venture (1):
47
Francisco Iglesias (8):
37
hw/i2c: flatten pca954x mux device
48
hw/misc: Introduce the Xilinx CFI interface
49
hw/misc: Introduce a model of Xilinx Versal's CFU_APB
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
38
56
39
Peter Maydell (5):
57
Philippe Mathieu-Daudé (1):
40
hw/arm/mps2-tz.c: Update AN547 documentation URL
58
hw/intc/arm_gicv3_its: Avoid maybe-uninitialized error in get_vte()
41
hw/input/tsc210x: Don't abort on bad SPI word widths
42
target/arm: Report KVM's actual PSCI version to guest in dtb
43
ui/cocoa.m: Fix updateUIInfo threading issues
44
ui/cocoa.m: Remove unnecessary NSAutoreleasePools
45
59
46
Richard Henderson (16):
60
Richard Henderson (9):
47
hw/registerfields: Add FIELD_SEX<N> and FIELD_SDP<N>
61
tests/tcg/aarch64: Adjust pauth tests for FEAT_FPAC
48
target/arm: Set TCR_EL1.TSZ for user-only
62
target/arm: Don't change pauth features when changing algorithm
49
target/arm: Fault on invalid TCR_ELx.TxSZ
63
target/arm: Implement FEAT_PACQARMA3
50
target/arm: Move arm_pamax out of line
64
target/arm: Do not use gen_mte_checkN in trans_STGP
51
target/arm: Pass outputsize down to check_s2_mmu_setup
65
target/arm: Implement RMR_ELx
52
target/arm: Use MAKE_64BIT_MASK to compute indexmask
66
target/arm: Implement cortex-a710
53
target/arm: Honor TCR_ELx.{I}PS
67
target/arm: Implement HCR_EL2.TIDCP
54
target/arm: Prepare DBGBVR and DBGWVR for FEAT_LVA
68
target/arm: Implement FEAT_TIDCP1
55
target/arm: Implement FEAT_LVA
69
target/arm: Enable SCTLR_EL1.TIDCP for user-only
56
target/arm: Implement FEAT_LPA
57
target/arm: Extend arm_fi_to_lfsc to level -1
58
target/arm: Introduce tlbi_aa64_get_range
59
target/arm: Fix TLBIRange.base for 16k and 64k pages
60
target/arm: Validate tlbi TG matches translation granule in use
61
target/arm: Advertise all page sizes for -cpu max
62
target/arm: Implement FEAT_LPA2
63
70
64
Shengtan Mao (1):
71
Shameer Kolothum (1):
65
tests/qtest: add qtests for npcm7xx sdhci
72
arm/kvm: Enable support for KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE
66
73
67
Wentao_Liang (1):
74
MAINTAINERS | 10 +
68
target/arm: Fix early free of TCG temp in handle_simd_shift_fpint_conv()
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
69
122
70
docs/system/arm/emulation.rst | 3 +
71
include/hw/registerfields.h | 48 +++++-
72
target/arm/cpu-param.h | 4 +-
73
target/arm/cpu.h | 27 ++++
74
target/arm/internals.h | 58 ++++---
75
target/arm/kvm-consts.h | 14 +-
76
hw/arm/boot.c | 11 +-
77
hw/arm/mps2-tz.c | 6 +-
78
hw/i2c/i2c_mux_pca954x.c | 77 ++-------
79
hw/input/tsc210x.c | 8 +-
80
target/arm/cpu.c | 8 +-
81
target/arm/cpu64.c | 7 +-
82
target/arm/helper.c | 332 ++++++++++++++++++++++++++++++---------
83
target/arm/hvf/hvf.c | 27 +++-
84
target/arm/kvm64.c | 14 +-
85
target/arm/psci.c | 35 ++++-
86
target/arm/translate-a64.c | 2 +-
87
tests/qtest/npcm7xx_sdhci-test.c | 215 +++++++++++++++++++++++++
88
tests/qtest/meson.build | 1 +
89
ui/cocoa.m | 31 ++--
90
20 files changed, 736 insertions(+), 192 deletions(-)
91
create mode 100644 tests/qtest/npcm7xx_sdhci-test.c
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Pass down the width of the output address from translation.
3
With FEAT_FPAC, AUT* instructions that fail authentication
4
For now this is still just PAMax, but a subsequent patch will
4
do not produce an error value but instead fault.
5
compute the correct value from TCR_ELx.{I}PS.
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.
6
12
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220301215958.157011-6-richard.henderson@linaro.org
15
Message-id: 20230829232335.965414-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
17
---
12
target/arm/helper.c | 21 ++++++++++-----------
18
tests/tcg/aarch64/pauth.h | 23 +++++++++++++
13
1 file changed, 10 insertions(+), 11 deletions(-)
19
tests/tcg/aarch64/pauth-2.c | 54 ++++++++++++++++++++++++++-----
14
20
tests/tcg/aarch64/pauth-4.c | 18 ++++++++---
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
tests/tcg/aarch64/pauth-5.c | 10 ++++++
16
index XXXXXXX..XXXXXXX 100644
22
tests/tcg/aarch64/Makefile.target | 6 +++-
17
--- a/target/arm/helper.c
23
5 files changed, 98 insertions(+), 13 deletions(-)
18
+++ b/target/arm/helper.c
24
create mode 100644 tests/tcg/aarch64/pauth.h
19
@@ -XXX,XX +XXX,XX @@ do_fault:
25
20
* false otherwise.
26
diff --git a/tests/tcg/aarch64/pauth.h b/tests/tcg/aarch64/pauth.h
21
*/
27
new file mode 100644
22
static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
28
index XXXXXXX..XXXXXXX
23
- int inputsize, int stride)
29
--- /dev/null
24
+ int inputsize, int stride, int outputsize)
30
+++ b/tests/tcg/aarch64/pauth.h
25
{
31
@@ -XXX,XX +XXX,XX @@
26
const int grainsize = stride + 3;
32
+/*
27
int startsizecheck;
33
+ * Helper for pauth test case
28
@@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
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
}
29
}
96
}
30
97
31
if (is_aa64) {
98
+ assert(pac_feature < 4); /* No FEAT_FPAC */
32
- CPUARMState *env = &cpu->env;
99
+
33
- unsigned int pamax = arm_pamax(cpu);
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
}
34
-
186
-
35
switch (stride) {
36
case 13: /* 64KB Pages. */
37
- if (level == 0 || (level == 1 && pamax <= 42)) {
38
+ if (level == 0 || (level == 1 && outputsize <= 42)) {
39
return false;
40
}
41
break;
42
case 11: /* 16KB Pages. */
43
- if (level == 0 || (level == 1 && pamax <= 40)) {
44
+ if (level == 0 || (level == 1 && outputsize <= 40)) {
45
return false;
46
}
47
break;
48
case 9: /* 4KB Pages. */
49
- if (level == 0 && pamax <= 42) {
50
+ if (level == 0 && outputsize <= 42) {
51
return false;
52
}
53
break;
54
@@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
55
}
56
57
/* Inputsize checks. */
58
- if (inputsize > pamax &&
59
- (arm_el_is_aa64(env, 1) || inputsize > 40)) {
60
+ if (inputsize > outputsize &&
61
+ (arm_el_is_aa64(&cpu->env, 1) || inputsize > 40)) {
62
/* This is CONSTRAINED UNPREDICTABLE and we choose to fault. */
63
return false;
64
}
65
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
66
target_ulong page_size;
67
uint32_t attrs;
68
int32_t stride;
69
- int addrsize, inputsize;
70
+ int addrsize, inputsize, outputsize;
71
TCR *tcr = regime_tcr(env, mmu_idx);
72
int ap, ns, xn, pxn;
73
uint32_t el = regime_el(env, mmu_idx);
74
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
75
76
addrsize = 64 - 8 * param.tbi;
77
inputsize = 64 - param.tsz;
78
+ outputsize = arm_pamax(cpu);
79
} else {
80
param = aa32_va_parameters(env, address, mmu_idx);
81
level = 1;
82
addrsize = (mmu_idx == ARMMMUIdx_Stage2 ? 40 : 32);
83
inputsize = addrsize - param.tsz;
84
+ outputsize = 40;
85
}
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
+ }
86
218
87
/*
219
/*
88
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
220
* With TBI enabled and a 48-bit VA, there are 7 bits of auth, and so
89
221
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
90
/* Check that the starting level is valid. */
222
index XXXXXXX..XXXXXXX 100644
91
ok = check_s2_mmu_setup(cpu, aarch64, startlevel,
223
--- a/tests/tcg/aarch64/Makefile.target
92
- inputsize, stride);
224
+++ b/tests/tcg/aarch64/Makefile.target
93
+ inputsize, stride, outputsize);
225
@@ -XXX,XX +XXX,XX @@ endif
94
if (!ok) {
226
ifneq ($(CROSS_CC_HAS_ARMV8_3),)
95
fault_type = ARMFault_Translation;
227
AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5
96
goto do_fault;
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
97
--
238
--
98
2.25.1
239
2.34.1
diff view generated by jsdifflib
1
From: Akihiko Odaki <akihiko.odaki@gmail.com>
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
2
3
Support the latest PSCI on TCG and HVF. A 64-bit function called from
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
AArch32 now returns NOT_SUPPORTED, which is necessary to adhere to SMC
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Calling Convention 1.0. It is still not compliant with SMCCC 1.3 since
5
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
6
they do not implement mandatory functions.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
8
Message-id: 20230829232335.965414-3-richard.henderson@linaro.org
9
Message-id: 20220213035753.34577-1-akihiko.odaki@gmail.com
9
[PMM: drop the HVF part of the patch and just comment that
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
we need to do something when the register appears in that API]
11
[PMM: update MISMATCH_CHECK checks on PSCI_VERSION macros to match]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
---
14
target/arm/kvm-consts.h | 13 +++++++++----
15
target/arm/cpu.h | 1 +
15
hw/arm/boot.c | 12 +++++++++---
16
target/arm/helper.c | 4 ++--
16
target/arm/cpu.c | 5 +++--
17
target/arm/hvf/hvf.c | 1 +
17
target/arm/hvf/hvf.c | 27 ++++++++++++++++++++++++++-
18
target/arm/kvm64.c | 2 ++
18
target/arm/kvm64.c | 2 +-
19
4 files changed, 6 insertions(+), 2 deletions(-)
19
target/arm/psci.c | 35 ++++++++++++++++++++++++++++++++---
20
6 files changed, 80 insertions(+), 14 deletions(-)
21
20
22
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/kvm-consts.h
23
--- a/target/arm/cpu.h
25
+++ b/target/arm/kvm-consts.h
24
+++ b/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_0_1_FN_MIGRATE, KVM_PSCI_FN_MIGRATE);
25
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
27
#define QEMU_PSCI_0_2_FN64_AFFINITY_INFO QEMU_PSCI_0_2_FN64(4)
26
uint32_t dbgdevid1;
28
#define QEMU_PSCI_0_2_FN64_MIGRATE QEMU_PSCI_0_2_FN64(5)
27
uint64_t id_aa64isar0;
29
28
uint64_t id_aa64isar1;
30
+#define QEMU_PSCI_1_0_FN_PSCI_FEATURES QEMU_PSCI_0_2_FN(10)
29
+ uint64_t id_aa64isar2;
31
+
30
uint64_t id_aa64pfr0;
32
MISMATCH_CHECK(QEMU_PSCI_0_2_FN_CPU_SUSPEND, PSCI_0_2_FN_CPU_SUSPEND);
31
uint64_t id_aa64pfr1;
33
MISMATCH_CHECK(QEMU_PSCI_0_2_FN_CPU_OFF, PSCI_0_2_FN_CPU_OFF);
32
uint64_t id_aa64mmfr0;
34
MISMATCH_CHECK(QEMU_PSCI_0_2_FN_CPU_ON, PSCI_0_2_FN_CPU_ON);
33
diff --git a/target/arm/helper.c b/target/arm/helper.c
35
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_0_2_FN_MIGRATE, PSCI_0_2_FN_MIGRATE);
36
MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_CPU_SUSPEND, PSCI_0_2_FN64_CPU_SUSPEND);
37
MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_CPU_ON, PSCI_0_2_FN64_CPU_ON);
38
MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_MIGRATE, PSCI_0_2_FN64_MIGRATE);
39
+MISMATCH_CHECK(QEMU_PSCI_1_0_FN_PSCI_FEATURES, PSCI_1_0_FN_PSCI_FEATURES);
40
41
/* PSCI v0.2 return values used by TCG emulation of PSCI */
42
43
/* No Trusted OS migration to worry about when offlining CPUs */
44
#define QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED 2
45
46
-/* We implement version 0.2 only */
47
-#define QEMU_PSCI_0_2_RET_VERSION_0_2 2
48
+#define QEMU_PSCI_VERSION_0_1 0x00001
49
+#define QEMU_PSCI_VERSION_0_2 0x00002
50
+#define QEMU_PSCI_VERSION_1_1 0x10001
51
52
MISMATCH_CHECK(QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED, PSCI_0_2_TOS_MP);
53
-MISMATCH_CHECK(QEMU_PSCI_0_2_RET_VERSION_0_2,
54
- (PSCI_VERSION_MAJOR(0) | PSCI_VERSION_MINOR(2)));
55
+/* We don't bother to check every possible version value */
56
+MISMATCH_CHECK(QEMU_PSCI_VERSION_0_2, PSCI_VERSION(0, 2));
57
+MISMATCH_CHECK(QEMU_PSCI_VERSION_1_1, PSCI_VERSION(1, 1));
58
59
/* PSCI return values (inclusive of all PSCI versions) */
60
#define QEMU_PSCI_RET_SUCCESS 0
61
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
62
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/boot.c
35
--- a/target/arm/helper.c
64
+++ b/hw/arm/boot.c
36
+++ b/target/arm/helper.c
65
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
37
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
66
}
38
.access = PL1_R, .type = ARM_CP_CONST,
67
39
.accessfn = access_aa64_tid3,
68
qemu_fdt_add_subnode(fdt, "/psci");
40
.resetvalue = cpu->isar.id_aa64isar1 },
69
- if (armcpu->psci_version == 2) {
41
- { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
70
- const char comp[] = "arm,psci-0.2\0arm,psci";
42
+ { .name = "ID_AA64ISAR2_EL1", .state = ARM_CP_STATE_AA64,
71
- qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
43
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,
72
+ if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2 ||
44
.access = PL1_R, .type = ARM_CP_CONST,
73
+ armcpu->psci_version == QEMU_PSCI_VERSION_1_1) {
45
.accessfn = access_aa64_tid3,
74
+ if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2) {
46
- .resetvalue = 0 },
75
+ const char comp[] = "arm,psci-0.2\0arm,psci";
47
+ .resetvalue = cpu->isar.id_aa64isar2 },
76
+ qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
48
{ .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
77
+ } else {
49
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3,
78
+ const char comp[] = "arm,psci-1.0\0arm,psci-0.2\0arm,psci";
50
.access = PL1_R, .type = ARM_CP_CONST,
79
+ qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
80
+ }
81
82
cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
83
if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
84
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/cpu.c
87
+++ b/target/arm/cpu.c
88
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
89
* picky DTB consumer will also provide a helpful error message.
90
*/
91
cpu->dtb_compatible = "qemu,unknown";
92
- cpu->psci_version = 1; /* By default assume PSCI v0.1 */
93
+ cpu->psci_version = QEMU_PSCI_VERSION_0_1; /* By default assume PSCI v0.1 */
94
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
95
96
if (tcg_enabled() || hvf_enabled()) {
97
- cpu->psci_version = 2; /* TCG and HVF implement PSCI 0.2 */
98
+ /* TCG and HVF implement PSCI 1.1 */
99
+ cpu->psci_version = QEMU_PSCI_VERSION_1_1;
100
}
101
}
102
103
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
51
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
104
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
105
--- a/target/arm/hvf/hvf.c
53
--- a/target/arm/hvf/hvf.c
106
+++ b/target/arm/hvf/hvf.c
54
+++ b/target/arm/hvf/hvf.c
107
@@ -XXX,XX +XXX,XX @@ static bool hvf_handle_psci_call(CPUState *cpu)
55
@@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
108
56
{ HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 },
109
switch (param[0]) {
57
{ HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 },
110
case QEMU_PSCI_0_2_FN_PSCI_VERSION:
58
{ HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 },
111
- ret = QEMU_PSCI_0_2_RET_VERSION_0_2;
59
+ /* Add ID_AA64ISAR2_EL1 here when HVF supports it */
112
+ ret = QEMU_PSCI_VERSION_1_1;
60
{ HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 },
113
break;
61
{ HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 },
114
case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
62
{ HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 },
115
ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */
116
@@ -XXX,XX +XXX,XX @@ static bool hvf_handle_psci_call(CPUState *cpu)
117
case QEMU_PSCI_0_2_FN_MIGRATE:
118
ret = QEMU_PSCI_RET_NOT_SUPPORTED;
119
break;
120
+ case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
121
+ switch (param[1]) {
122
+ case QEMU_PSCI_0_2_FN_PSCI_VERSION:
123
+ case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
124
+ case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
125
+ case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
126
+ case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
127
+ case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
128
+ case QEMU_PSCI_0_1_FN_CPU_ON:
129
+ case QEMU_PSCI_0_2_FN_CPU_ON:
130
+ case QEMU_PSCI_0_2_FN64_CPU_ON:
131
+ case QEMU_PSCI_0_1_FN_CPU_OFF:
132
+ case QEMU_PSCI_0_2_FN_CPU_OFF:
133
+ case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
134
+ case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
135
+ case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
136
+ case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
137
+ ret = 0;
138
+ break;
139
+ case QEMU_PSCI_0_1_FN_MIGRATE:
140
+ case QEMU_PSCI_0_2_FN_MIGRATE:
141
+ default:
142
+ ret = QEMU_PSCI_RET_NOT_SUPPORTED;
143
+ }
144
+ break;
145
default:
146
return false;
147
}
148
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
63
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
149
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/kvm64.c
65
--- a/target/arm/kvm64.c
151
+++ b/target/arm/kvm64.c
66
+++ b/target/arm/kvm64.c
152
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
67
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
153
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF;
68
ARM64_SYS_REG(3, 0, 0, 6, 0));
154
}
69
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1,
155
if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) {
70
ARM64_SYS_REG(3, 0, 0, 6, 1));
156
- cpu->psci_version = 2;
71
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2,
157
+ cpu->psci_version = QEMU_PSCI_VERSION_0_2;
72
+ ARM64_SYS_REG(3, 0, 0, 6, 2));
158
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2;
73
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0,
159
}
74
ARM64_SYS_REG(3, 0, 0, 7, 0));
160
if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
75
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
161
diff --git a/target/arm/psci.c b/target/arm/psci.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/target/arm/psci.c
164
+++ b/target/arm/psci.c
165
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu)
166
{
167
/*
168
* This function partially implements the logic for dispatching Power State
169
- * Coordination Interface (PSCI) calls (as described in ARM DEN 0022B.b),
170
+ * Coordination Interface (PSCI) calls (as described in ARM DEN 0022D.b),
171
* to the extent required for bringing up and taking down secondary cores,
172
* and for handling reset and poweroff requests.
173
* Additional information about the calling convention used is available in
174
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu)
175
}
176
177
if ((param[0] & QEMU_PSCI_0_2_64BIT) && !is_a64(env)) {
178
- ret = QEMU_PSCI_RET_INVALID_PARAMS;
179
+ ret = QEMU_PSCI_RET_NOT_SUPPORTED;
180
goto err;
181
}
182
183
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu)
184
ARMCPU *target_cpu;
185
186
case QEMU_PSCI_0_2_FN_PSCI_VERSION:
187
- ret = QEMU_PSCI_0_2_RET_VERSION_0_2;
188
+ ret = QEMU_PSCI_VERSION_1_1;
189
break;
190
case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
191
ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */
192
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu)
193
}
194
helper_wfi(env, 4);
195
break;
196
+ case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
197
+ switch (param[1]) {
198
+ case QEMU_PSCI_0_2_FN_PSCI_VERSION:
199
+ case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
200
+ case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
201
+ case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
202
+ case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
203
+ case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
204
+ case QEMU_PSCI_0_1_FN_CPU_ON:
205
+ case QEMU_PSCI_0_2_FN_CPU_ON:
206
+ case QEMU_PSCI_0_2_FN64_CPU_ON:
207
+ case QEMU_PSCI_0_1_FN_CPU_OFF:
208
+ case QEMU_PSCI_0_2_FN_CPU_OFF:
209
+ case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
210
+ case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
211
+ case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
212
+ case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
213
+ if (!(param[1] & QEMU_PSCI_0_2_64BIT) || is_a64(env)) {
214
+ ret = 0;
215
+ break;
216
+ }
217
+ /* fallthrough */
218
+ case QEMU_PSCI_0_1_FN_MIGRATE:
219
+ case QEMU_PSCI_0_2_FN_MIGRATE:
220
+ default:
221
+ ret = QEMU_PSCI_RET_NOT_SUPPORTED;
222
+ break;
223
+ }
224
+ break;
225
case QEMU_PSCI_0_1_FN_MIGRATE:
226
case QEMU_PSCI_0_2_FN_MIGRATE:
227
default:
228
--
76
--
229
2.25.1
77
2.34.1
78
79
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
2
3
For FEAT_LPA2, we will need other ARMVAParameters, which themselves
3
Rename isar_feature_aa64_pauth_arch to isar_feature_aa64_pauth_qarma5
4
depend on the translation granule in use. We might as well validate
4
to distinguish the other architectural algorithm qarma3.
5
that the given TG matches; the architecture "does not require that
5
6
the instruction invalidates any entries" if this is not true.
6
Add ARMPauthFeature and isar_feature_pauth_feature to cover the
7
other pauth conditions.
7
8
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220301215958.157011-15-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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
17
---
13
target/arm/helper.c | 10 +++++++---
18
target/arm/cpu.h | 47 +++++++++++++++++++++++++++++------
14
1 file changed, 7 insertions(+), 3 deletions(-)
19
target/arm/tcg/pauth_helper.c | 2 +-
20
2 files changed, 40 insertions(+), 9 deletions(-)
15
21
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
24
--- a/target/arm/cpu.h
19
+++ b/target/arm/helper.c
25
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
26
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
21
uint64_t value)
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)
22
{
57
{
23
unsigned int page_size_granule, page_shift, num, scale, exponent;
58
/*
24
+ /* Extract one bit to represent the va selector in use. */
59
* Return true if any form of pauth is enabled, as this
25
+ uint64_t select = sextract64(value, 36, 1);
60
* predicate controls migration of the 128-bit keys.
26
+ ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true);
61
*/
27
TLBIRange ret = { };
62
- return (id->id_aa64isar1 &
28
63
- (FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) |
29
page_size_granule = extract64(value, 46, 2);
64
- FIELD_DP64(0, ID_AA64ISAR1, API, 0xf) |
30
65
- FIELD_DP64(0, ID_AA64ISAR1, GPA, 0xf) |
31
- if (page_size_granule == 0) {
66
- FIELD_DP64(0, ID_AA64ISAR1, GPI, 0xf))) != 0;
32
- qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n",
67
+ return isar_feature_pauth_feature(id) != PauthFeat_None;
33
+ /* The granule encoded in value must match the granule in use. */
68
}
34
+ if (page_size_granule != (param.using64k ? 3 : param.using16k ? 2 : 1)) {
69
35
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\n",
70
-static inline bool isar_feature_aa64_pauth_arch(const ARMISARegisters *id)
36
page_size_granule);
71
+static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id)
37
return ret;
72
{
38
}
73
/*
39
@@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
74
- * Return true if pauth is enabled with the architected QARMA algorithm.
40
75
- * QEMU will always set APA+GPA to the same value.
41
ret.length = (num + 1) << (exponent + page_shift);
76
+ * Return true if pauth is enabled with the architected QARMA5 algorithm.
42
77
+ * QEMU will always enable or disable both APA and GPA.
43
- if (regime_has_2_ranges(mmuidx)) {
78
*/
44
+ if (param.select) {
79
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0;
45
ret.base = sextract64(value, 0, 37);
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);
46
} else {
105
} else {
47
ret.base = extract64(value, 0, 37);
106
return pauth_computepac_impdef(data, modifier, key);
48
--
107
--
49
2.25.1
108
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We support 16k pages, but do not advertize that in ID_AA64MMFR0.
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.
4
6
5
The value 0 in the TGRAN*_2 fields indicates that stage2 lookups defer
7
This already affects the neoverse-v1 cpu, which has FEAT_EPAC.
6
to the same support as stage1 lookups. This setting is deprecated, so
7
indicate support for all stage2 page sizes directly.
8
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20230829232335.965414-5-richard.henderson@linaro.org
11
Message-id: 20220301215958.157011-16-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
target/arm/cpu64.c | 4 ++++
14
target/arm/cpu64.c | 70 +++++++++++++++++++++++++++---------------
15
1 file changed, 4 insertions(+)
15
target/arm/tcg/cpu64.c | 2 ++
16
2 files changed, 47 insertions(+), 25 deletions(-)
16
17
17
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
18
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu64.c
20
--- a/target/arm/cpu64.c
20
+++ b/target/arm/cpu64.c
21
+++ b/target/arm/cpu64.c
21
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
22
@@ -XXX,XX +XXX,XX @@ void aarch64_add_sme_properties(Object *obj)
22
23
23
t = cpu->isar.id_aa64mmfr0;
24
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
24
t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */
25
{
25
+ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 1); /* 16k pages supported */
26
- int arch_val = 0, impdef_val = 0;
26
+ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 2); /* 16k stage2 supported */
27
- uint64_t t;
27
+ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
28
+ ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu);
28
+ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
29
+ uint64_t isar1;
29
cpu->isar.id_aa64mmfr0 = t;
30
30
31
- /* Exit early if PAuth is enabled, and fall through to disable it */
31
t = cpu->isar.id_aa64mmfr1;
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 */
32
--
118
--
33
2.25.1
119
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This feature is relatively small, as it applies only to
3
Implement the QARMA3 cryptographic algorithm for PAC calculation.
4
64k pages and thus requires no additional changes to the
4
Implement a cpu feature to select the algorithm and document it.
5
table descriptor walking algorithm, only a change to the
6
minimum TSZ (which is the inverse of the maximum virtual
7
address space size).
8
5
9
Note that this feature widens VBAR_ELx, but we already
6
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
10
treat the register as being 64 bits wide.
11
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220301215958.157011-10-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>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
15
---
17
docs/system/arm/emulation.rst | 1 +
16
docs/system/arm/cpu-features.rst | 21 ++++++++-----
18
target/arm/cpu-param.h | 2 +-
17
docs/system/arm/emulation.rst | 3 ++
19
target/arm/cpu.h | 5 +++++
18
target/arm/cpu.h | 1 +
20
target/arm/cpu64.c | 1 +
19
target/arm/arm-qmp-cmds.c | 2 +-
21
target/arm/helper.c | 9 ++++++++-
20
target/arm/cpu64.c | 24 ++++++++++++--
22
5 files changed, 16 insertions(+), 2 deletions(-)
21
target/arm/tcg/pauth_helper.c | 54 ++++++++++++++++++++++++++------
22
tests/qtest/arm-cpu-features.c | 12 ++++++-
23
7 files changed, 94 insertions(+), 23 deletions(-)
23
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
==================
24
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
58
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
25
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
26
--- a/docs/system/arm/emulation.rst
60
--- a/docs/system/arm/emulation.rst
27
+++ b/docs/system/arm/emulation.rst
61
+++ b/docs/system/arm/emulation.rst
28
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
62
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
29
- FEAT_LRCPC (Load-acquire RCpc instructions)
30
- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
31
- FEAT_LSE (Large System Extensions)
32
+- FEAT_LVA (Large Virtual Address space)
33
- FEAT_MTE (Memory Tagging Extension)
63
- FEAT_MTE (Memory Tagging Extension)
34
- FEAT_MTE2 (Memory Tagging Extension)
64
- FEAT_MTE2 (Memory Tagging Extension)
35
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
65
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
36
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
66
+- FEAT_PACIMP (Pointer authentication - IMPLEMENTATION DEFINED algorithm)
37
index XXXXXXX..XXXXXXX 100644
67
+- FEAT_PACQARMA3 (Pointer authentication - QARMA3 algorithm)
38
--- a/target/arm/cpu-param.h
68
+- FEAT_PACQARMA5 (Pointer authentication - QARMA5 algorithm)
39
+++ b/target/arm/cpu-param.h
69
- FEAT_PAN (Privileged access never)
40
@@ -XXX,XX +XXX,XX @@
70
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
41
#ifdef TARGET_AARCH64
71
- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
42
# define TARGET_LONG_BITS 64
43
# define TARGET_PHYS_ADDR_SPACE_BITS 48
44
-# define TARGET_VIRT_ADDR_SPACE_BITS 48
45
+# define TARGET_VIRT_ADDR_SPACE_BITS 52
46
#else
47
# define TARGET_LONG_BITS 32
48
# define TARGET_PHYS_ADDR_SPACE_BITS 40
49
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
72
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
50
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/cpu.h
74
--- a/target/arm/cpu.h
52
+++ b/target/arm/cpu.h
75
+++ b/target/arm/cpu.h
53
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
76
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
54
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
77
*/
55
}
78
bool prop_pauth;
56
79
bool prop_pauth_impdef;
57
+static inline bool isar_feature_aa64_lva(const ARMISARegisters *id)
80
+ bool prop_pauth_qarma3;
58
+{
81
bool prop_lpa2;
59
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0;
82
60
+}
83
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
61
+
84
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
62
static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
85
index XXXXXXX..XXXXXXX 100644
63
{
86
--- a/target/arm/arm-qmp-cmds.c
64
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
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
65
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
97
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
66
index XXXXXXX..XXXXXXX 100644
98
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/cpu64.c
99
--- a/target/arm/cpu64.c
68
+++ b/target/arm/cpu64.c
100
+++ b/target/arm/cpu64.c
69
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
101
@@ -XXX,XX +XXX,XX @@ void aarch64_add_sme_properties(Object *obj)
70
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
102
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
71
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
103
{
72
t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
104
ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu);
73
+ t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */
105
- uint64_t isar1;
74
cpu->isar.id_aa64mmfr2 = t;
106
+ uint64_t isar1, isar2;
75
107
76
t = cpu->isar.id_aa64zfr0;
108
/*
77
diff --git a/target/arm/helper.c b/target/arm/helper.c
109
* These properties enable or disable Pauth as a whole, or change
78
index XXXXXXX..XXXXXXX 100644
110
@@ -XXX,XX +XXX,XX @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
79
--- a/target/arm/helper.c
111
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, 0);
80
+++ b/target/arm/helper.c
112
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 0);
81
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
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);
82
} else {
165
} else {
83
max_tsz = 39;
166
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property);
84
}
167
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma3_property);
85
- min_tsz = 16; /* TODO: ARMv8.2-LVA */
168
}
86
+
169
}
87
+ min_tsz = 16;
170
88
+ if (using64k) {
171
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
89
+ if (cpu_isar_feature(aa64_lva, env_archcpu(env))) {
172
index XXXXXXX..XXXXXXX 100644
90
+ min_tsz = 12;
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);
91
+ }
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);
92
+ }
244
+ }
93
+ /* TODO: FEAT_LPA2 */
245
workingval = pac_cell_shuffle(workingval);
94
246
workingval = pac_mult(workingval);
95
if (tsz > max_tsz) {
247
workingval ^= key1;
96
tsz = max_tsz;
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)
97
--
318
--
98
2.25.1
319
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
2
3
This feature widens physical addresses (and intermediate physical
3
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
4
addresses for 2-stage translation) from 48 to 52 bits, when using
5
64k pages. The only thing left at this point is to handle the
6
extra bits in the TTBR and in the table descriptors.
7
8
Note that PAR_EL1 and HPFAR_EL2 are nominally extended, but we don't
9
mask out the high bits when writing to those registers, so no changes
10
are required there.
11
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220301215958.157011-11-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>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
11
---
17
docs/system/arm/emulation.rst | 1 +
12
docs/system/arm/emulation.rst | 1 +
18
target/arm/cpu-param.h | 2 +-
13
target/arm/tcg/cpu64.c | 2 +-
19
target/arm/cpu64.c | 2 +-
14
target/arm/tcg/pauth_helper.c | 16 +++++++++++-----
20
target/arm/helper.c | 19 ++++++++++++++++---
15
3 files changed, 13 insertions(+), 6 deletions(-)
21
4 files changed, 19 insertions(+), 5 deletions(-)
22
16
23
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/system/arm/emulation.rst
19
--- a/docs/system/arm/emulation.rst
26
+++ b/docs/system/arm/emulation.rst
20
+++ b/docs/system/arm/emulation.rst
27
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
21
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
28
- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
22
- FEAT_DotProd (Advanced SIMD dot product instructions)
29
- FEAT_JSCVT (JavaScript conversion instructions)
23
- FEAT_DoubleFault (Double Fault Extension)
30
- FEAT_LOR (Limited ordering regions)
24
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
31
+- FEAT_LPA (Large Physical Address space)
25
+- FEAT_EPAC (Enhanced pointer authentication)
32
- FEAT_LRCPC (Load-acquire RCpc instructions)
26
- FEAT_ETS (Enhanced Translation Synchronization)
33
- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
27
- FEAT_EVT (Enhanced Virtualization Traps)
34
- FEAT_LSE (Large System Extensions)
28
- FEAT_FCMA (Floating-point complex number instructions)
35
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
29
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
36
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu-param.h
31
--- a/target/arm/tcg/cpu64.c
38
+++ b/target/arm/cpu-param.h
32
+++ b/target/arm/tcg/cpu64.c
39
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
40
34
41
#ifdef TARGET_AARCH64
35
t = cpu->isar.id_aa64isar1;
42
# define TARGET_LONG_BITS 64
36
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */
43
-# define TARGET_PHYS_ADDR_SPACE_BITS 48
37
- t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_1);
44
+# define TARGET_PHYS_ADDR_SPACE_BITS 52
38
+ t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_EPAC);
45
# define TARGET_VIRT_ADDR_SPACE_BITS 52
39
t = FIELD_DP64(t, ID_AA64ISAR1, API, 1);
46
#else
40
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); /* FEAT_JSCVT */
47
# define TARGET_LONG_BITS 32
41
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); /* FEAT_FCMA */
48
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
42
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
49
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/cpu64.c
44
--- a/target/arm/tcg/pauth_helper.c
51
+++ b/target/arm/cpu64.c
45
+++ b/target/arm/tcg/pauth_helper.c
52
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
46
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_computepac(CPUARMState *env, uint64_t data,
53
cpu->isar.id_aa64pfr1 = t;
47
static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
54
48
ARMPACKey *key, bool data)
55
t = cpu->isar.id_aa64mmfr0;
49
{
56
- t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 5); /* PARange: 48 bits */
50
+ ARMCPU *cpu = env_archcpu(env);
57
+ t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */
51
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
58
cpu->isar.id_aa64mmfr0 = t;
52
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
59
53
+ ARMPauthFeature pauth_feature = cpu_isar_feature(pauth_feature, cpu);
60
t = cpu->isar.id_aa64mmfr1;
54
uint64_t pac, ext_ptr, ext, test;
61
diff --git a/target/arm/helper.c b/target/arm/helper.c
55
int bot_bit, top_bit;
62
index XXXXXXX..XXXXXXX 100644
56
63
--- a/target/arm/helper.c
57
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
64
+++ b/target/arm/helper.c
58
*/
65
@@ -XXX,XX +XXX,XX @@ static const uint8_t pamax_map[] = {
59
test = sextract64(ptr, bot_bit, top_bit - bot_bit);
66
[3] = 42,
60
if (test != 0 && test != -1) {
67
[4] = 44,
61
- /*
68
[5] = 48,
62
- * Note that our top_bit is one greater than the pseudocode's
69
+ [6] = 52,
63
- * version, hence "- 2" here.
70
};
64
- */
71
65
- pac ^= MAKE_64BIT_MASK(top_bit - 2, 1);
72
/* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */
66
+ if (pauth_feature == PauthFeat_EPAC) {
73
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
67
+ pac = 0;
74
descaddr = extract64(ttbr, 0, 48);
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
}
75
76
76
/*
77
/*
77
- * If the base address is out of range, raise AddressSizeFault.
78
+ * For FEAT_LPA and PS=6, bits [51:48] of descaddr are in [5:2] of TTBR.
79
+ *
80
+ * Otherwise, if the base address is out of range, raise AddressSizeFault.
81
* In the pseudocode, this is !IsZero(baseregister<47:outputsize>),
82
* but we've just cleared the bits above 47, so simplify the test.
83
*/
84
- if (descaddr >> outputsize) {
85
+ if (outputsize > 48) {
86
+ descaddr |= extract64(ttbr, 2, 4) << 48;
87
+ } else if (descaddr >> outputsize) {
88
level = 0;
89
fault_type = ARMFault_AddressSize;
90
goto do_fault;
91
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
92
}
93
94
descaddr = descriptor & descaddrmask;
95
- if (descaddr >> outputsize) {
96
+
97
+ /*
98
+ * For FEAT_LPA and PS=6, bits [51:48] of descaddr are in [15:12]
99
+ * of descriptor. Otherwise, if descaddr is out of range, raise
100
+ * AddressSizeFault.
101
+ */
102
+ if (outputsize > 48) {
103
+ descaddr |= extract64(descriptor, 12, 4) << 48;
104
+ } else if (descaddr >> outputsize) {
105
fault_type = ARMFault_AddressSize;
106
goto do_fault;
107
}
108
--
78
--
109
2.25.1
79
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
2
3
Add new macros to manipulate signed fields within the register.
3
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
4
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220301215958.157011-2-richard.henderson@linaro.org
7
Message-id: 20230829232335.965414-8-richard.henderson@linaro.org
8
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-Id: <20230609172324.982888-6-aaron@os.amperecomputing.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
include/hw/registerfields.h | 48 ++++++++++++++++++++++++++++++++++++-
12
docs/system/arm/emulation.rst | 1 +
13
1 file changed, 47 insertions(+), 1 deletion(-)
13
target/arm/tcg/cpu64.c | 2 +-
14
target/arm/tcg/pauth_helper.c | 21 +++++++++++++++++----
15
3 files changed, 19 insertions(+), 5 deletions(-)
14
16
15
diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/registerfields.h
19
--- a/docs/system/arm/emulation.rst
18
+++ b/include/hw/registerfields.h
20
+++ b/docs/system/arm/emulation.rst
19
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
20
extract64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
22
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
21
R_ ## reg ## _ ## field ## _LENGTH)
23
- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
22
24
- FEAT_PAuth (Pointer authentication)
23
+#define FIELD_SEX8(storage, reg, field) \
25
+- FEAT_PAuth2 (Enhacements to pointer authentication)
24
+ sextract8((storage), R_ ## reg ## _ ## field ## _SHIFT, \
26
- FEAT_PMULL (PMULL, PMULL2 instructions)
25
+ R_ ## reg ## _ ## field ## _LENGTH)
27
- FEAT_PMUv3p1 (PMU Extensions v3.1)
26
+#define FIELD_SEX16(storage, reg, field) \
28
- FEAT_PMUv3p4 (PMU Extensions v3.4)
27
+ sextract16((storage), R_ ## reg ## _ ## field ## _SHIFT, \
29
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
28
+ R_ ## reg ## _ ## field ## _LENGTH)
30
index XXXXXXX..XXXXXXX 100644
29
+#define FIELD_SEX32(storage, reg, field) \
31
--- a/target/arm/tcg/cpu64.c
30
+ sextract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
32
+++ b/target/arm/tcg/cpu64.c
31
+ R_ ## reg ## _ ## field ## _LENGTH)
33
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
32
+#define FIELD_SEX64(storage, reg, field) \
34
33
+ sextract64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
35
t = cpu->isar.id_aa64isar1;
34
+ R_ ## reg ## _ ## field ## _LENGTH)
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);
35
+
88
+
36
/* Extract a field from an array of registers */
89
+ if (pauth_feature >= PauthFeat_2) {
37
#define ARRAY_FIELD_EX32(regs, reg, field) \
90
+ return ptr ^ (pac & cmp_mask);
38
FIELD_EX32((regs)[R_ ## reg], reg, field)
91
+ }
39
@@ -XXX,XX +XXX,XX @@
40
_d; })
41
#define FIELD_DP64(storage, reg, field, val) ({ \
42
struct { \
43
- uint64_t v:R_ ## reg ## _ ## field ## _LENGTH; \
44
+ uint64_t v:R_ ## reg ## _ ## field ## _LENGTH; \
45
+ } _v = { .v = val }; \
46
+ uint64_t _d; \
47
+ _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
48
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
49
+ _d; })
50
+
92
+
51
+#define FIELD_SDP8(storage, reg, field, val) ({ \
93
+ if ((pac ^ ptr) & cmp_mask) {
52
+ struct { \
94
int error_code = (keynumber << 1) | (keynumber ^ 1);
53
+ signed int v:R_ ## reg ## _ ## field ## _LENGTH; \
95
if (param.tbi) {
54
+ } _v = { .v = val }; \
96
return deposit64(orig_ptr, 53, 2, error_code);
55
+ uint8_t _d; \
56
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
57
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
58
+ _d; })
59
+#define FIELD_SDP16(storage, reg, field, val) ({ \
60
+ struct { \
61
+ signed int v:R_ ## reg ## _ ## field ## _LENGTH; \
62
+ } _v = { .v = val }; \
63
+ uint16_t _d; \
64
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
65
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
66
+ _d; })
67
+#define FIELD_SDP32(storage, reg, field, val) ({ \
68
+ struct { \
69
+ signed int v:R_ ## reg ## _ ## field ## _LENGTH; \
70
+ } _v = { .v = val }; \
71
+ uint32_t _d; \
72
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
73
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
74
+ _d; })
75
+#define FIELD_SDP64(storage, reg, field, val) ({ \
76
+ struct { \
77
+ int64_t v:R_ ## reg ## _ ## field ## _LENGTH; \
78
} _v = { .v = val }; \
79
uint64_t _d; \
80
_d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
81
--
97
--
82
2.25.1
98
2.34.1
83
84
diff view generated by jsdifflib
1
From: Shengtan Mao <stmao@google.com>
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
2
3
Reviewed-by: Hao Wu <wuhaotsh@google.com>
3
An instruction is a 'combined' Pointer Authentication instruction
4
Reviewed-by: Chris Rauer <crauer@google.com>
4
if it does something in addition to PAC -- for instance, branching
5
Signed-off-by: Shengtan Mao <stmao@google.com>
5
to or loading an address from the authenticated pointer.
6
Signed-off-by: Patrick Venture <venture@google.com>
6
7
Message-id: 20220225174451.192304-1-wuhaotsh@google.com
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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
18
---
10
tests/qtest/npcm7xx_sdhci-test.c | 215 +++++++++++++++++++++++++++++++
19
target/arm/tcg/helper-a64.h | 4 ++
11
tests/qtest/meson.build | 1 +
20
target/arm/tcg/pauth_helper.c | 71 +++++++++++++++++++++++++++-------
12
2 files changed, 216 insertions(+)
21
target/arm/tcg/translate-a64.c | 12 +++---
13
create mode 100644 tests/qtest/npcm7xx_sdhci-test.c
22
3 files changed, 68 insertions(+), 19 deletions(-)
14
23
15
diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c
24
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
16
new file mode 100644
25
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX
26
--- a/target/arm/tcg/helper-a64.h
18
--- /dev/null
27
+++ b/target/arm/tcg/helper-a64.h
19
+++ b/tests/qtest/npcm7xx_sdhci-test.c
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(pacda, TCG_CALL_NO_WG, i64, env, i64, i64)
20
@@ -XXX,XX +XXX,XX @@
29
DEF_HELPER_FLAGS_3(pacdb, TCG_CALL_NO_WG, i64, env, i64, i64)
21
+/*
30
DEF_HELPER_FLAGS_3(pacga, TCG_CALL_NO_WG, i64, env, i64, i64)
22
+ * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller
31
DEF_HELPER_FLAGS_3(autia, TCG_CALL_NO_WG, i64, env, i64, i64)
23
+ *
32
+DEF_HELPER_FLAGS_3(autia_combined, TCG_CALL_NO_WG, i64, env, i64, i64)
24
+ * Copyright (c) 2022 Google LLC
33
DEF_HELPER_FLAGS_3(autib, TCG_CALL_NO_WG, i64, env, i64, i64)
25
+ *
34
+DEF_HELPER_FLAGS_3(autib_combined, TCG_CALL_NO_WG, i64, env, i64, i64)
26
+ * This program is free software; you can redistribute it and/or modify it
35
DEF_HELPER_FLAGS_3(autda, TCG_CALL_NO_WG, i64, env, i64, i64)
27
+ * under the terms of the GNU General Public License as published by the
36
+DEF_HELPER_FLAGS_3(autda_combined, TCG_CALL_NO_WG, i64, env, i64, i64)
28
+ * Free Software Foundation; either version 2 of the License, or
37
DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64)
29
+ * (at your option) any later version.
38
+DEF_HELPER_FLAGS_3(autdb_combined, TCG_CALL_NO_WG, i64, env, i64, i64)
30
+ *
39
DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64)
31
+ * This program is distributed in the hope that it will be useful, but WITHOUT
40
DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64)
32
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
41
33
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
42
diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c
34
+ * for more details.
43
index XXXXXXX..XXXXXXX 100644
35
+ */
44
--- a/target/arm/tcg/pauth_helper.c
36
+
45
+++ b/target/arm/tcg/pauth_helper.c
37
+#include "qemu/osdep.h"
46
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param)
38
+#include "hw/sd/npcm7xx_sdhci.h"
47
}
39
+
48
40
+#include "libqos/libqtest.h"
49
static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
41
+#include "libqtest-single.h"
50
- ARMPACKey *key, bool data, int keynumber)
42
+#include "libqos/sdhci-cmd.h"
51
+ ARMPACKey *key, bool data, int keynumber,
43
+
52
+ uintptr_t ra, bool is_combined)
44
+#define NPCM7XX_REG_SIZE 0x100
53
{
45
+#define NPCM7XX_MMC_BA 0xF0842000
54
ARMCPU *cpu = env_archcpu(env);
46
+#define NPCM7XX_BLK_SIZE 512
55
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
47
+#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30)
56
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(pacga)(CPUARMState *env, uint64_t x, uint64_t y)
48
+
57
return pac & 0xffffffff00000000ull;
49
+char *sd_path;
58
}
50
+
59
51
+static QTestState *setup_sd_card(void)
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)
52
+{
76
+{
53
+ QTestState *qts = qtest_initf(
77
+ return pauth_autia(env, x, y, GETPC(), false);
54
+ "-machine kudo-bmc "
55
+ "-device sd-card,drive=drive0 "
56
+ "-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off",
57
+ sd_path);
58
+
59
+ qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_SWRST, SDHC_RESET_ALL);
60
+ qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_CLKCON,
61
+ SDHC_CLOCK_SDCLK_EN | SDHC_CLOCK_INT_STABLE |
62
+ SDHC_CLOCK_INT_EN);
63
+ sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_APP_CMD);
64
+ sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x41200000, 0, (41 << 8));
65
+ sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_ALL_SEND_CID);
66
+ sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR);
67
+ sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x45670000, 0,
68
+ SDHC_SELECT_DESELECT_CARD);
69
+
70
+ return qts;
71
+}
78
+}
72
+
79
+
73
+static void write_sdread(QTestState *qts, const char *msg)
80
+uint64_t HELPER(autia_combined)(CPUARMState *env, uint64_t x, uint64_t y)
74
+{
81
+{
75
+ int fd, ret;
82
+ return pauth_autia(env, x, y, GETPC(), true);
76
+ size_t len = strlen(msg);
77
+ char *rmsg = g_malloc(len);
78
+
79
+ /* write message to sd */
80
+ fd = open(sd_path, O_WRONLY);
81
+ g_assert(fd >= 0);
82
+ ret = write(fd, msg, len);
83
+ close(fd);
84
+ g_assert(ret == len);
85
+
86
+ /* read message using sdhci */
87
+ ret = sdhci_read_cmd(qts, NPCM7XX_MMC_BA, rmsg, len);
88
+ g_assert(ret == len);
89
+ g_assert(!memcmp(rmsg, msg, len));
90
+
91
+ g_free(rmsg);
92
+}
83
+}
93
+
84
+
94
+/* Check MMC can read values from sd */
85
+static uint64_t pauth_autib(CPUARMState *env, uint64_t x, uint64_t y,
95
+static void test_read_sd(void)
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)
96
+{
100
+{
97
+ QTestState *qts = setup_sd_card();
101
+ return pauth_autib(env, x, y, GETPC(), false);
98
+
99
+ write_sdread(qts, "hello world");
100
+ write_sdread(qts, "goodbye");
101
+
102
+ qtest_quit(qts);
103
+}
102
+}
104
+
103
+
105
+static void sdwrite_read(QTestState *qts, const char *msg)
104
+uint64_t HELPER(autib_combined)(CPUARMState *env, uint64_t x, uint64_t y)
106
+{
105
+{
107
+ int fd, ret;
106
+ return pauth_autib(env, x, y, GETPC(), true);
108
+ size_t len = strlen(msg);
109
+ char *rmsg = g_malloc(len);
110
+
111
+ /* write message using sdhci */
112
+ sdhci_write_cmd(qts, NPCM7XX_MMC_BA, msg, len, NPCM7XX_BLK_SIZE);
113
+
114
+ /* read message from sd */
115
+ fd = open(sd_path, O_RDONLY);
116
+ g_assert(fd >= 0);
117
+ ret = read(fd, rmsg, len);
118
+ close(fd);
119
+ g_assert(ret == len);
120
+
121
+ g_assert(!memcmp(rmsg, msg, len));
122
+
123
+ g_free(rmsg);
124
+}
107
+}
125
+
108
+
126
+/* Check MMC can write values to sd */
109
+static uint64_t pauth_autda(CPUARMState *env, uint64_t x, uint64_t y,
127
+static void test_write_sd(void)
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)
128
+{
124
+{
129
+ QTestState *qts = setup_sd_card();
125
+ return pauth_autda(env, x, y, GETPC(), false);
130
+
131
+ sdwrite_read(qts, "hello world");
132
+ sdwrite_read(qts, "goodbye");
133
+
134
+ qtest_quit(qts);
135
+}
126
+}
136
+
127
+
137
+/* Check SDHCI has correct default values. */
128
+uint64_t HELPER(autda_combined)(CPUARMState *env, uint64_t x, uint64_t y)
138
+static void test_reset(void)
139
+{
129
+{
140
+ QTestState *qts = qtest_init("-machine kudo-bmc");
130
+ return pauth_autda(env, x, y, GETPC(), true);
141
+ uint64_t addr = NPCM7XX_MMC_BA;
142
+ uint64_t end_addr = addr + NPCM7XX_REG_SIZE;
143
+ uint16_t prstvals_resets[] = {NPCM7XX_PRSTVALS_0_RESET,
144
+ NPCM7XX_PRSTVALS_1_RESET,
145
+ 0,
146
+ NPCM7XX_PRSTVALS_3_RESET,
147
+ 0,
148
+ 0};
149
+ int i;
150
+ uint32_t mask;
151
+
152
+ while (addr < end_addr) {
153
+ switch (addr - NPCM7XX_MMC_BA) {
154
+ case SDHC_PRNSTS:
155
+ /*
156
+ * ignores bits 20 to 24: they are changed when reading registers
157
+ */
158
+ mask = 0x1f00000;
159
+ g_assert_cmphex(qtest_readl(qts, addr) | mask, ==,
160
+ NPCM7XX_PRSNTS_RESET | mask);
161
+ addr += 4;
162
+ break;
163
+ case SDHC_BLKGAP:
164
+ g_assert_cmphex(qtest_readb(qts, addr), ==, NPCM7XX_BLKGAP_RESET);
165
+ addr += 1;
166
+ break;
167
+ case SDHC_CAPAB:
168
+ g_assert_cmphex(qtest_readq(qts, addr), ==, NPCM7XX_CAPAB_RESET);
169
+ addr += 8;
170
+ break;
171
+ case SDHC_MAXCURR:
172
+ g_assert_cmphex(qtest_readq(qts, addr), ==, NPCM7XX_MAXCURR_RESET);
173
+ addr += 8;
174
+ break;
175
+ case SDHC_HCVER:
176
+ g_assert_cmphex(qtest_readw(qts, addr), ==, NPCM7XX_HCVER_RESET);
177
+ addr += 2;
178
+ break;
179
+ case NPCM7XX_PRSTVALS:
180
+ for (i = 0; i < NPCM7XX_PRSTVALS_SIZE; ++i) {
181
+ g_assert_cmphex(qtest_readw(qts, addr + 2 * i), ==,
182
+ prstvals_resets[i]);
183
+ }
184
+ addr += NPCM7XX_PRSTVALS_SIZE * 2;
185
+ break;
186
+ default:
187
+ g_assert_cmphex(qtest_readb(qts, addr), ==, 0);
188
+ addr += 1;
189
+ }
190
+ }
191
+
192
+ qtest_quit(qts);
193
+}
131
+}
194
+
132
+
195
+static void drive_destroy(void)
133
+static uint64_t pauth_autdb(CPUARMState *env, uint64_t x, uint64_t y,
196
+{
134
+ uintptr_t ra, bool is_combined)
197
+ unlink(sd_path);
135
{
198
+ g_free(sd_path);
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);
199
+}
144
+}
200
+
145
+
201
+static void drive_create(void)
146
+uint64_t HELPER(autdb)(CPUARMState *env, uint64_t x, uint64_t y)
202
+{
147
+{
203
+ int fd, ret;
148
+ return pauth_autdb(env, x, y, GETPC(), false);
204
+ GError *error = NULL;
205
+
206
+ /* Create a temporary raw image */
207
+ fd = g_file_open_tmp("sdhci_XXXXXX", &sd_path, &error);
208
+ if (fd == -1) {
209
+ fprintf(stderr, "unable to create sdhci file: %s\n", error->message);
210
+ g_error_free(error);
211
+ }
212
+ g_assert(sd_path != NULL);
213
+
214
+ ret = ftruncate(fd, NPCM7XX_TEST_IMAGE_SIZE);
215
+ g_assert_cmpint(ret, ==, 0);
216
+ g_message("%s", sd_path);
217
+ close(fd);
218
+}
149
+}
219
+
150
+
220
+int main(int argc, char **argv)
151
+uint64_t HELPER(autdb_combined)(CPUARMState *env, uint64_t x, uint64_t y)
221
+{
152
+{
222
+ int ret;
153
+ return pauth_autdb(env, x, y, GETPC(), true);
223
+
154
}
224
+ drive_create();
155
225
+
156
uint64_t HELPER(xpaci)(CPUARMState *env, uint64_t a)
226
+ g_test_init(&argc, &argv, NULL);
157
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
227
+
228
+ qtest_add_func("npcm7xx_sdhci/reset", test_reset);
229
+ qtest_add_func("npcm7xx_sdhci/write_sd", test_write_sd);
230
+ qtest_add_func("npcm7xx_sdhci/read_sd", test_read_sd);
231
+
232
+ ret = g_test_run();
233
+ drive_destroy();
234
+ return ret;
235
+}
236
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
237
index XXXXXXX..XXXXXXX 100644
158
index XXXXXXX..XXXXXXX 100644
238
--- a/tests/qtest/meson.build
159
--- a/target/arm/tcg/translate-a64.c
239
+++ b/tests/qtest/meson.build
160
+++ b/target/arm/tcg/translate-a64.c
240
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
161
@@ -XXX,XX +XXX,XX @@ static TCGv_i64 auth_branch_target(DisasContext *s, TCGv_i64 dst,
241
'npcm7xx_gpio-test',
162
242
'npcm7xx_pwm-test',
163
truedst = tcg_temp_new_i64();
243
'npcm7xx_rng-test',
164
if (use_key_a) {
244
+ 'npcm7xx_sdhci-test',
165
- gen_helper_autia(truedst, cpu_env, dst, modifier);
245
'npcm7xx_smbus-test',
166
+ gen_helper_autia_combined(truedst, cpu_env, dst, modifier);
246
'npcm7xx_timer-test',
167
} else {
247
'npcm7xx_watchdog_timer-test'] + \
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
248
--
189
--
249
2.25.1
190
2.34.1
191
192
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
2
3
Without FEAT_LVA, the behaviour of programming an invalid value
3
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
4
is IMPLEMENTATION DEFINED. With FEAT_LVA, programming an invalid
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
minimum value requires a Translation fault.
6
7
It is most self-consistent to choose to generate the fault always.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220301215958.157011-4-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>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
target/arm/internals.h | 1 +
12
docs/system/arm/emulation.rst | 2 ++
15
target/arm/helper.c | 32 ++++++++++++++++++++++++++++----
13
target/arm/syndrome.h | 7 +++++++
16
2 files changed, 29 insertions(+), 4 deletions(-)
14
target/arm/tcg/cpu64.c | 2 +-
15
target/arm/tcg/pauth_helper.c | 18 +++++++++++++++++-
16
4 files changed, 27 insertions(+), 2 deletions(-)
17
17
18
diff --git a/target/arm/internals.h b/target/arm/internals.h
18
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/internals.h
20
--- a/docs/system/arm/emulation.rst
21
+++ b/target/arm/internals.h
21
+++ b/docs/system/arm/emulation.rst
22
@@ -XXX,XX +XXX,XX @@ typedef struct ARMVAParameters {
22
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
23
bool hpd : 1;
23
- FEAT_FGT (Fine-Grained Traps)
24
bool using16k : 1;
24
- FEAT_FHM (Floating-point half-precision multiplication instructions)
25
bool using64k : 1;
25
- FEAT_FP16 (Half-precision floating-point data processing)
26
+ bool tsz_oob : 1; /* tsz has been clamped to legal range */
26
+- FEAT_FPAC (Faulting on AUT* instructions)
27
} ARMVAParameters;
27
+- FEAT_FPACCOMBINE (Faulting on combined pointer authentication instructions)
28
28
- FEAT_FRINTTS (Floating-point to integer instructions)
29
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
29
- FEAT_FlagM (Flag manipulation instructions v2)
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
31
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
31
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/helper.c
33
--- a/target/arm/syndrome.h
33
+++ b/target/arm/helper.c
34
+++ b/target/arm/syndrome.h
34
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
35
@@ -XXX,XX +XXX,XX @@ enum arm_exception_class {
35
ARMMMUIdx mmu_idx, bool data)
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)
36
{
54
{
37
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
55
return EC_PACTRAP << ARM_EL_EC_SHIFT;
38
- bool epd, hpd, using16k, using64k;
56
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
39
- int select, tsz, tbi, max_tsz;
57
index XXXXXXX..XXXXXXX 100644
40
+ bool epd, hpd, using16k, using64k, tsz_oob;
58
--- a/target/arm/tcg/cpu64.c
41
+ int select, tsz, tbi, max_tsz, min_tsz;
59
+++ b/target/arm/tcg/cpu64.c
42
60
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
43
if (!regime_has_2_ranges(mmu_idx)) {
61
44
select = 0;
62
t = cpu->isar.id_aa64isar1;
45
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
63
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */
46
} else {
64
- t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_2);
47
max_tsz = 39;
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)
48
}
74
}
49
+ min_tsz = 16; /* TODO: ARMv8.2-LVA */
50
51
- tsz = MIN(tsz, max_tsz);
52
- tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
53
+ if (tsz > max_tsz) {
54
+ tsz = max_tsz;
55
+ tsz_oob = true;
56
+ } else if (tsz < min_tsz) {
57
+ tsz = min_tsz;
58
+ tsz_oob = true;
59
+ } else {
60
+ tsz_oob = false;
61
+ }
62
63
/* Present TBI as a composite with TBID. */
64
tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
65
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
66
.hpd = hpd,
67
.using16k = using16k,
68
.using64k = using64k,
69
+ .tsz_oob = tsz_oob,
70
};
71
}
75
}
72
76
73
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
77
+static G_NORETURN
74
param = aa64_va_parameters(env, address, mmu_idx,
78
+void pauth_fail_exception(CPUARMState *env, bool data,
75
access_type != MMU_INST_FETCH);
79
+ int keynumber, uintptr_t ra)
76
level = 0;
80
+{
81
+ raise_exception_ra(env, EXCP_UDEF, syn_pacfail(data, keynumber),
82
+ exception_target_el(env), ra);
83
+}
77
+
84
+
78
+ /*
85
static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
79
+ * If TxSZ is programmed to a value larger than the maximum,
86
ARMPACKey *key, bool data, int keynumber,
80
+ * or smaller than the effective minimum, it is IMPLEMENTATION
87
uintptr_t ra, bool is_combined)
81
+ * DEFINED whether we behave as if the field were programmed
88
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
82
+ * within bounds, or if a level 0 Translation fault is generated.
89
cmp_mask &= ~MAKE_64BIT_MASK(55, 1);
83
+ *
90
84
+ * With FEAT_LVA, fault on less than minimum becomes required,
91
if (pauth_feature >= PauthFeat_2) {
85
+ * so our choice is to always raise the fault.
92
- return ptr ^ (pac & cmp_mask);
86
+ */
93
+ ARMPauthFeature fault_feature =
87
+ if (param.tsz_oob) {
94
+ is_combined ? PauthFeat_FPACCOMBINED : PauthFeat_FPAC;
88
+ fault_type = ARMFault_Translation;
95
+ uint64_t result = ptr ^ (pac & cmp_mask);
89
+ goto do_fault;
96
+
97
+ if (pauth_feature >= fault_feature
98
+ && ((result ^ sextract64(result, 55, 1)) & cmp_mask)) {
99
+ pauth_fail_exception(env, data, keynumber, ra);
90
+ }
100
+ }
91
+
101
+ return result;
92
addrsize = 64 - 8 * param.tbi;
102
}
93
inputsize = 64 - param.tsz;
103
94
} else {
104
if ((pac ^ ptr) & cmp_mask) {
95
--
105
--
96
2.25.1
106
2.34.1
diff view generated by jsdifflib
1
The tsc210x doesn't support anything other than 16-bit reads on the
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
SPI bus, but the guest can program the SPI controller to attempt
3
them anyway. If this happens, don't abort QEMU, just log this as
4
a guest error.
5
2
6
This fixes our machine_arm_n8x0.py:N8x0Machine.test_n800
3
Fix when using GCC v11.4 (Ubuntu 11.4.0-1ubuntu1~22.04) with CFLAGS=-Og:
7
acceptance test, which hits this assertion.
8
4
9
The reason we hit the assertion is because the guest kernel thinks
5
[4/6] Compiling C object libcommon.fa.p/hw_intc_arm_gicv3_its.c.o
10
there is a TSC2005 on this SPI bus address, not a TSC210x. (The n810
6
FAILED: libcommon.fa.p/hw_intc_arm_gicv3_its.c.o
11
*does* have a TSC2005 at this address.) The TSC2005 supports the
7
inlined from ‘lookup_vte’ at hw/intc/arm_gicv3_its.c:453:9,
12
24-bit accesses which the guest driver makes, and the TSC210x does
8
inlined from ‘vmovp_callback’ at hw/intc/arm_gicv3_its.c:1039:14:
13
not (that is, our TSC210x emulation is not missing support for a word
9
hw/intc/arm_gicv3_its.c:347:9: error: ‘vte.rdbase’ may be used uninitialized [-Werror=maybe-uninitialized]
14
width the hardware can handle). It's not clear whether the problem
10
347 | trace_gicv3_its_vte_read(vpeid, vte->valid, vte->vptsize,
15
here is that the guest kernel incorrectly thinks the n800 has the
11
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16
same device at this SPI bus address as the n810, or that QEMU's n810
12
348 | vte->vptaddr, vte->rdbase);
17
board model doesn't get the SPI devices right. At this late date
13
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
18
there no longer appears to be any reliable information on the web
14
hw/intc/arm_gicv3_its.c: In function ‘vmovp_callback’:
19
about the hardware behaviour, but I am inclined to think this is a
15
hw/intc/arm_gicv3_its.c:1036:13: note: ‘vte’ declared here
20
guest kernel bug. In any case, we prefer not to abort QEMU for
16
1036 | VTEntry vte;
21
guest-triggerable conditions, so logging the error is the right thing
17
| ^~~
22
to do.
23
18
24
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/736
19
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
21
Message-id: 20230831131348.69032-1-philmd@linaro.org
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
27
Message-id: 20220221140750.514557-1-peter.maydell@linaro.org
28
---
23
---
29
hw/input/tsc210x.c | 8 ++++++--
24
hw/intc/arm_gicv3_its.c | 15 ++++++---------
30
1 file changed, 6 insertions(+), 2 deletions(-)
25
1 file changed, 6 insertions(+), 9 deletions(-)
31
26
32
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
27
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
33
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/input/tsc210x.c
29
--- a/hw/intc/arm_gicv3_its.c
35
+++ b/hw/input/tsc210x.c
30
+++ b/hw/intc/arm_gicv3_its.c
36
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@ static MemTxResult get_vte(GICv3ITSState *s, uint32_t vpeid, VTEntry *vte)
37
#include "hw/hw.h"
32
if (entry_addr == -1) {
38
#include "audio/audio.h"
33
/* No L2 table entry, i.e. no valid VTE, or a memory error */
39
#include "qemu/timer.h"
34
vte->valid = false;
40
+#include "qemu/log.h"
35
- goto out;
41
#include "sysemu/reset.h"
36
+ trace_gicv3_its_vte_read_fault(vpeid);
42
#include "ui/console.h"
37
+ return MEMTX_OK;
43
#include "hw/arm/omap.h" /* For I2SCodec */
38
}
44
@@ -XXX,XX +XXX,XX @@ uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len)
39
vteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
45
TSC210xState *s = opaque;
40
if (res != MEMTX_OK) {
46
uint32_t ret = 0;
41
- goto out;
47
42
+ trace_gicv3_its_vte_read_fault(vpeid);
48
- if (len != 16)
43
+ return res;
49
- hw_error("%s: FIXME: bad SPI word width %i\n", __func__, len);
44
}
50
+ if (len != 16) {
45
vte->valid = FIELD_EX64(vteval, VTE, VALID);
51
+ qemu_log_mask(LOG_GUEST_ERROR,
46
vte->vptsize = FIELD_EX64(vteval, VTE, VPTSIZE);
52
+ "%s: bad SPI word width %i\n", __func__, len);
47
vte->vptaddr = FIELD_EX64(vteval, VTE, VPTADDR);
53
+ return 0;
48
vte->rdbase = FIELD_EX64(vteval, VTE, RDBASE);
54
+ }
49
-out:
55
50
- if (res != MEMTX_OK) {
56
/* TODO: sequential reads etc - how do we make sure the host doesn't
51
- trace_gicv3_its_vte_read_fault(vpeid);
57
* unintentionally read out a conversion result from a register while
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;
59
}
60
58
--
61
--
59
2.25.1
62
2.34.1
60
63
61
64
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
2
2
3
With FEAT_LPA2, rather than introducing translation level 4,
3
Introduce the Xilinx Configuration Frame Interface (CFI) for transmitting
4
we introduce level -1, below the current level 0. Extend
4
CFI data packets between the Xilinx Configuration Frame Unit models
5
arm_fi_to_lfsc to handle these faults.
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).
6
8
7
Assert that this new translation level does not leak into
9
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
fault types for which it is not defined, which allows some
10
Reviewed-by: Sai Pavan Boddu <sai.pavan.boddu@amd.com>
9
masking of fi->level to be removed.
11
Acked-by: Edgar E. Iglesias <edgar@zeroasic.com>
10
12
Message-id: 20230831165701.2016397-2-francisco.iglesias@amd.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20220301215958.157011-12-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
14
---
16
target/arm/internals.h | 35 +++++++++++++++++++++++++++++------
15
MAINTAINERS | 6 ++++
17
1 file changed, 29 insertions(+), 6 deletions(-)
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
18
22
19
diff --git a/target/arm/internals.h b/target/arm/internals.h
23
diff --git a/MAINTAINERS b/MAINTAINERS
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/internals.h
25
--- a/MAINTAINERS
22
+++ b/target/arm/internals.h
26
+++ b/MAINTAINERS
23
@@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi)
27
@@ -XXX,XX +XXX,XX @@ S: Maintained
24
case ARMFault_None:
28
F: hw/ssi/xlnx-versal-ospi.c
25
return 0;
29
F: include/hw/ssi/xlnx-versal-ospi.h
26
case ARMFault_AddressSize:
30
27
- fsc = fi->level & 3;
31
+Xilinx Versal CFI
28
+ assert(fi->level >= -1 && fi->level <= 3);
32
+M: Francisco Iglesias <francisco.iglesias@amd.com>
29
+ if (fi->level < 0) {
33
+S: Maintained
30
+ fsc = 0b101001;
34
+F: hw/misc/xlnx-cfi-if.c
31
+ } else {
35
+F: include/hw/misc/xlnx-cfi-if.h
32
+ fsc = fi->level;
36
+
33
+ }
37
STM32F100
34
break;
38
M: Alexandre Iooss <erdnaxe@crans.org>
35
case ARMFault_AccessFlag:
39
L: qemu-arm@nongnu.org
36
- fsc = (fi->level & 3) | (0x2 << 2);
40
diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h
37
+ assert(fi->level >= 0 && fi->level <= 3);
41
new file mode 100644
38
+ fsc = 0b001000 | fi->level;
42
index XXXXXXX..XXXXXXX
39
break;
43
--- /dev/null
40
case ARMFault_Permission:
44
+++ b/include/hw/misc/xlnx-cfi-if.h
41
- fsc = (fi->level & 3) | (0x3 << 2);
45
@@ -XXX,XX +XXX,XX @@
42
+ assert(fi->level >= 0 && fi->level <= 3);
46
+/*
43
+ fsc = 0b001100 | fi->level;
47
+ * Xilinx CFI interface
44
break;
48
+ *
45
case ARMFault_Translation:
49
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
46
- fsc = (fi->level & 3) | (0x1 << 2);
50
+ *
47
+ assert(fi->level >= -1 && fi->level <= 3);
51
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
48
+ if (fi->level < 0) {
52
+ *
49
+ fsc = 0b101011;
53
+ * SPDX-License-Identifier: GPL-2.0-or-later
50
+ } else {
54
+ */
51
+ fsc = 0b000100 | fi->level;
55
+#ifndef XLNX_CFI_IF_H
52
+ }
56
+#define XLNX_CFI_IF_H 1
53
break;
57
+
54
case ARMFault_SyncExternal:
58
+#include "qemu/help-texts.h"
55
fsc = 0x10 | (fi->ea << 12);
59
+#include "hw/hw.h"
56
break;
60
+#include "qom/object.h"
57
case ARMFault_SyncExternalOnWalk:
61
+
58
- fsc = (fi->level & 3) | (0x5 << 2) | (fi->ea << 12);
62
+#define TYPE_XLNX_CFI_IF "xlnx-cfi-if"
59
+ assert(fi->level >= -1 && fi->level <= 3);
63
+typedef struct XlnxCfiIfClass XlnxCfiIfClass;
60
+ if (fi->level < 0) {
64
+DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF)
61
+ fsc = 0b010011;
65
+
62
+ } else {
66
+#define XLNX_CFI_IF(obj) \
63
+ fsc = 0b010100 | fi->level;
67
+ INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF)
64
+ }
68
+
65
+ fsc |= fi->ea << 12;
69
+typedef enum {
66
break;
70
+ PACKET_TYPE_CFU = 0x52,
67
case ARMFault_SyncParity:
71
+ PACKET_TYPE_CFRAME = 0xA1,
68
fsc = 0x18;
72
+} xlnx_cfi_packet_type;
69
break;
73
+
70
case ARMFault_SyncParityOnWalk:
74
+typedef enum {
71
- fsc = (fi->level & 3) | (0x7 << 2);
75
+ CFRAME_FAR = 1,
72
+ assert(fi->level >= -1 && fi->level <= 3);
76
+ CFRAME_SFR = 2,
73
+ if (fi->level < 0) {
77
+ CFRAME_FDRI = 4,
74
+ fsc = 0b011011;
78
+ CFRAME_CMD = 6,
75
+ } else {
79
+} xlnx_cfi_reg_addr;
76
+ fsc = 0b011100 | fi->level;
80
+
77
+ }
81
+typedef struct XlnxCfiPacket {
78
break;
82
+ uint8_t reg_addr;
79
case ARMFault_AsyncParity:
83
+ uint32_t data[4];
80
fsc = 0x19;
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'))
81
--
157
--
82
2.25.1
158
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
2
2
3
The original A.a revision of the AArch64 ARM required that we
3
Introduce a model of the software programming interface (CFU_APB) of
4
force-extend the addresses in these registers from 49 bits.
4
Xilinx Versal's Configuration Frame Unit.
5
This language has been loosened via a combination of IMPLEMENTATION
6
DEFINED and CONSTRAINTED UNPREDICTABLE to allow consideration of
7
the entire aligned address.
8
5
9
This means that we do not have to consider whether or not FEAT_LVA
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
10
is enabled, and decide from which bit an address might need to be
11
extended.
12
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230831165701.2016397-3-francisco.iglesias@amd.com
15
Message-id: 20220301215958.157011-9-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
target/arm/helper.c | 32 ++++++++++++++++++++++++--------
11
MAINTAINERS | 2 +
19
1 file changed, 24 insertions(+), 8 deletions(-)
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
20
18
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/MAINTAINERS b/MAINTAINERS
22
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
21
--- a/MAINTAINERS
24
+++ b/target/arm/helper.c
22
+++ b/MAINTAINERS
25
@@ -XXX,XX +XXX,XX @@ static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
23
@@ -XXX,XX +XXX,XX @@ M: Francisco Iglesias <francisco.iglesias@amd.com>
26
ARMCPU *cpu = env_archcpu(env);
24
S: Maintained
27
int i = ri->crm;
25
F: hw/misc/xlnx-cfi-if.c
28
26
F: include/hw/misc/xlnx-cfi-if.h
29
- /* Bits [63:49] are hardwired to the value of bit [48]; that is, the
27
+F: hw/misc/xlnx-versal-cfu.c
30
- * register reads and behaves as if values written are sign extended.
28
+F: include/hw/misc/xlnx-versal-cfu.h
31
+ /*
29
32
* Bits [1:0] are RES0.
30
STM32F100
33
+ *
31
M: Alexandre Iooss <erdnaxe@crans.org>
34
+ * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA)
32
diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h
35
+ * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if
33
new file mode 100644
36
+ * they contain the value written. It is CONSTRAINED UNPREDICTABLE
34
index XXXXXXX..XXXXXXX
37
+ * whether the RESS bits are ignored when comparing an address.
35
--- /dev/null
38
+ *
36
+++ b/include/hw/misc/xlnx-versal-cfu.h
39
+ * Therefore we are allowed to compare the entire register, which lets
37
@@ -XXX,XX +XXX,XX @@
40
+ * us avoid considering whether or not FEAT_LVA is actually enabled.
38
+/*
41
*/
39
+ * QEMU model of the CFU Configuration Unit.
42
- value = sextract64(value, 0, 49) & ~3ULL;
40
+ *
43
+ value &= ~3ULL;
41
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
44
42
+ *
45
raw_write(env, ri, value);
43
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
46
hw_watchpoint_update(cpu, i);
44
+ *
47
@@ -XXX,XX +XXX,XX @@ void hw_breakpoint_update(ARMCPU *cpu, int n)
45
+ * SPDX-License-Identifier: GPL-2.0-or-later
48
case 0: /* unlinked address match */
46
+ *
49
case 1: /* linked address match */
47
+ * References:
50
{
48
+ * [1] Versal ACAP Technical Reference Manual,
51
- /* Bits [63:49] are hardwired to the value of bit [48]; that is,
49
+ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
52
- * we behave as if the register was sign extended. Bits [1:0] are
50
+ *
53
- * RES0. The BAS field is used to allow setting breakpoints on 16
51
+ * [2] Versal ACAP Register Reference,
54
- * bit wide instructions; it is CONSTRAINED UNPREDICTABLE whether
52
+ * https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html
55
+ /*
53
+ */
56
+ * Bits [1:0] are RES0.
54
+#ifndef HW_MISC_XLNX_VERSAL_CFU_APB_H
57
+ *
55
+#define HW_MISC_XLNX_VERSAL_CFU_APB_H
58
+ * It is IMPLEMENTATION DEFINED whether bits [63:49]
56
+
59
+ * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit
57
+#include "hw/sysbus.h"
60
+ * of the VA field ([48] or [52] for FEAT_LVA), or whether the
58
+#include "hw/register.h"
61
+ * value is read as written. It is CONSTRAINED UNPREDICTABLE
59
+#include "hw/misc/xlnx-cfi-if.h"
62
+ * whether the RESS bits are ignored when comparing an address.
60
+
63
+ * Therefore we are allowed to compare the entire register, which
61
+#define TYPE_XLNX_VERSAL_CFU_APB "xlnx,versal-cfu-apb"
64
+ * lets us avoid considering whether FEAT_LVA is actually enabled.
62
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, XLNX_VERSAL_CFU_APB)
65
+ *
63
+
66
+ * The BAS field is used to allow setting breakpoints on 16-bit
64
+REG32(CFU_ISR, 0x0)
67
+ * wide instructions; it is CONSTRAINED UNPREDICTABLE whether
65
+ FIELD(CFU_ISR, USR_GTS_EVENT, 9, 1)
68
* a bp will fire if the addresses covered by the bp and the addresses
66
+ FIELD(CFU_ISR, USR_GSR_EVENT, 8, 1)
69
* covered by the insn overlap but the insn doesn't start at the
67
+ FIELD(CFU_ISR, SLVERR, 7, 1)
70
* start of the bp address range. We choose to require the insn and
68
+ FIELD(CFU_ISR, DECOMP_ERROR, 6, 1)
71
@@ -XXX,XX +XXX,XX @@ void hw_breakpoint_update(ARMCPU *cpu, int n)
69
+ FIELD(CFU_ISR, BAD_CFI_PACKET, 5, 1)
72
* See also figure D2-3 in the v8 ARM ARM (DDI0487A.c).
70
+ FIELD(CFU_ISR, AXI_ALIGN_ERROR, 4, 1)
73
*/
71
+ FIELD(CFU_ISR, CFI_ROW_ERROR, 3, 1)
74
int bas = extract64(bcr, 5, 4);
72
+ FIELD(CFU_ISR, CRC32_ERROR, 2, 1)
75
- addr = sextract64(bvr, 0, 49) & ~3ULL;
73
+ FIELD(CFU_ISR, CRC8_ERROR, 1, 1)
76
+ addr = bvr & ~3ULL;
74
+ FIELD(CFU_ISR, SEU_ENDOFCALIB, 0, 1)
77
if (bas == 0) {
75
+REG32(CFU_IMR, 0x4)
78
return;
76
+ FIELD(CFU_IMR, USR_GTS_EVENT, 9, 1)
79
}
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'))
80
--
667
--
81
2.25.1
668
2.34.1
diff view generated by jsdifflib
1
The updateUIInfo method makes Cocoa API calls. It also calls back
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
2
into QEMU functions like dpy_set_ui_info(). To do this safely, we
3
need to follow two rules:
4
* Cocoa API calls are made on the Cocoa UI thread
5
* When calling back into QEMU we must hold the iothread lock
6
2
7
Fix the places where we got this wrong, by taking the iothread lock
3
Introduce a model of Xilinx Versal's Configuration Frame Unit's data out
8
while executing updateUIInfo, and moving the call in cocoa_switch()
4
port (CFU_FDRO).
9
inside the dispatch_async block.
10
5
11
Some of the Cocoa UI methods which call updateUIInfo are invoked as
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
12
part of the initial application startup, while we're still doing the
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
little cross-thread dance described in the comment just above
8
Message-id: 20230831165701.2016397-4-francisco.iglesias@amd.com
14
call_qemu_main(). This meant they were calling back into the QEMU UI
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
layer before we'd actually finished initializing our display and
10
---
16
registered the DisplayChangeListener, which isn't really valid. Once
11
include/hw/misc/xlnx-versal-cfu.h | 12 ++++
17
updateUIInfo takes the iothread lock, we no longer get away with
12
hw/misc/xlnx-versal-cfu.c | 96 +++++++++++++++++++++++++++++++
18
this, because during this startup phase the iothread lock is held by
13
2 files changed, 108 insertions(+)
19
the QEMU main-loop thread which is waiting for us to finish our
20
display initialization. So we must suppress updateUIInfo until
21
applicationDidFinishLaunching allows the QEMU main-loop thread to
22
continue.
23
14
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h
25
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
26
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
27
Message-id: 20220224101330.967429-2-peter.maydell@linaro.org
28
---
29
ui/cocoa.m | 25 ++++++++++++++++++++++---
30
1 file changed, 22 insertions(+), 3 deletions(-)
31
32
diff --git a/ui/cocoa.m b/ui/cocoa.m
33
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
34
--- a/ui/cocoa.m
17
--- a/include/hw/misc/xlnx-versal-cfu.h
35
+++ b/ui/cocoa.m
18
+++ b/include/hw/misc/xlnx-versal-cfu.h
36
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
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,
37
}
54
}
38
}
55
}
39
56
40
-- (void) updateUIInfo
57
+static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
41
+- (void) updateUIInfoLocked
42
{
43
+ /* Must be called with the iothread lock, i.e. via updateUIInfo */
44
NSSize frameSize;
45
QemuUIInfo info;
46
47
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
48
dpy_set_ui_info(dcl.con, &info, TRUE);
49
}
50
51
+- (void) updateUIInfo
52
+{
58
+{
53
+ if (!allow_events) {
59
+ XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
54
+ /*
60
+ uint64_t ret = 0;
55
+ * Don't try to tell QEMU about UI information in the application
61
+
56
+ * startup phase -- we haven't yet registered dcl with the QEMU UI
62
+ if (!fifo32_is_empty(&s->fdro_data)) {
57
+ * layer, and also trying to take the iothread lock would deadlock.
63
+ ret = fifo32_pop(&s->fdro_data);
58
+ * When cocoa_display_init() does register the dcl, the UI layer
59
+ * will call cocoa_switch(), which will call updateUIInfo, so
60
+ * we don't lose any information here.
61
+ */
62
+ return;
63
+ }
64
+ }
64
+
65
+
65
+ with_iothread_lock(^{
66
+ return ret;
66
+ [self updateUIInfoLocked];
67
+ });
68
+}
67
+}
69
+
68
+
70
- (void)viewDidMoveToWindow
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)
71
{
94
{
72
[self updateUIInfo];
95
XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
73
@@ -XXX,XX +XXX,XX @@ static void cocoa_switch(DisplayChangeListener *dcl,
96
@@ -XXX,XX +XXX,XX @@ static void cfu_apb_init(Object *obj)
74
97
sysbus_init_irq(sbd, &s->irq_cfu_imr);
75
COCOA_DEBUG("qemu_cocoa: cocoa_switch\n");
98
}
76
99
77
- [cocoaView updateUIInfo];
100
+static void cfu_fdro_init(Object *obj)
78
-
101
+{
79
// The DisplaySurface will be freed as soon as this callback returns.
102
+ XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
80
// We take a reference to the underlying pixman image here so it does
103
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
81
// not disappear from under our feet; the switchSurface method will
104
+
82
@@ -XXX,XX +XXX,XX @@ static void cocoa_switch(DisplayChangeListener *dcl,
105
+ memory_region_init_io(&s->iomem_fdro, obj, &cfu_fdro_ops, s,
83
pixman_image_ref(image);
106
+ TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K);
84
107
+ sysbus_init_mmio(sbd, &s->iomem_fdro);
85
dispatch_async(dispatch_get_main_queue(), ^{
108
+ fifo32_create(&s->fdro_data, 8 * KiB / sizeof(uint32_t));
86
+ [cocoaView updateUIInfo];
109
+}
87
[cocoaView switchSurface:image];
110
+
88
});
111
+static void cfu_fdro_reset_enter(Object *obj, ResetType type)
89
[pool release];
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)
90
--
194
--
91
2.25.1
195
2.34.1
diff view generated by jsdifflib
1
From: Patrick Venture <venture@google.com>
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
2
2
3
Previously this device created N subdevices which each owned an i2c bus.
3
Introduce a model of Xilinx Versal's Configuration Frame Unit's Single
4
Now this device simply owns the N i2c busses directly.
4
Frame Read port (CFU_SFR).
5
5
6
Tested: Verified devices behind mux are still accessible via qmp and i2c
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
from within an arm32 SoC.
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
8
Message-id: 20230831165701.2016397-5-francisco.iglesias@amd.com
9
Reviewed-by: Hao Wu <wuhaotsh@google.com>
10
Signed-off-by: Patrick Venture <venture@google.com>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20220202164533.1283668-1-venture@google.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
hw/i2c/i2c_mux_pca954x.c | 77 +++++++---------------------------------
11
include/hw/misc/xlnx-versal-cfu.h | 15 ++++++
17
1 file changed, 13 insertions(+), 64 deletions(-)
12
hw/misc/xlnx-versal-cfu.c | 87 +++++++++++++++++++++++++++++++
13
2 files changed, 102 insertions(+)
18
14
19
diff --git a/hw/i2c/i2c_mux_pca954x.c b/hw/i2c/i2c_mux_pca954x.c
15
diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/i2c/i2c_mux_pca954x.c
17
--- a/include/hw/misc/xlnx-versal-cfu.h
22
+++ b/hw/i2c/i2c_mux_pca954x.c
18
+++ b/include/hw/misc/xlnx-versal-cfu.h
23
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, XLNX_VERSAL_CFU_APB)
24
#define PCA9548_CHANNEL_COUNT 8
20
#define TYPE_XLNX_VERSAL_CFU_FDRO "xlnx,versal-cfu-fdro"
25
#define PCA9546_CHANNEL_COUNT 4
21
OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUFDRO, XLNX_VERSAL_CFU_FDRO)
26
22
27
-/*
23
+#define TYPE_XLNX_VERSAL_CFU_SFR "xlnx,versal-cfu-sfr"
28
- * struct Pca954xChannel - The i2c mux device will have N of these states
24
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUSFR, XLNX_VERSAL_CFU_SFR)
29
- * that own the i2c channel bus.
25
+
30
- * @bus: The owned channel bus.
26
REG32(CFU_ISR, 0x0)
31
- * @enabled: Is this channel active?
27
FIELD(CFU_ISR, USR_GTS_EVENT, 9, 1)
32
- */
28
FIELD(CFU_ISR, USR_GSR_EVENT, 8, 1)
33
-typedef struct Pca954xChannel {
29
@@ -XXX,XX +XXX,XX @@ struct XlnxVersalCFUFDRO {
34
- SysBusDevice parent;
30
Fifo32 fdro_data;
35
-
31
};
36
- I2CBus *bus;
32
37
-
33
+struct XlnxVersalCFUSFR {
38
- bool enabled;
34
+ SysBusDevice parent_obj;
39
-} Pca954xChannel;
35
+ MemoryRegion iomem_sfr;
40
-
36
+
41
-#define TYPE_PCA954X_CHANNEL "pca954x-channel"
37
+ /* 128-bit wfifo. */
42
-#define PCA954X_CHANNEL(obj) \
38
+ uint32_t wfifo[WFIFO_SZ];
43
- OBJECT_CHECK(Pca954xChannel, (obj), TYPE_PCA954X_CHANNEL)
39
+
44
-
40
+ struct {
45
/*
41
+ XlnxVersalCFUAPB *cfu;
46
* struct Pca954xState - The pca954x state object.
42
+ } cfg;
47
* @control: The value written to the mux control.
43
+};
48
@@ -XXX,XX +XXX,XX @@ typedef struct Pca954xState {
44
+
49
45
/**
50
uint8_t control;
46
* This is a helper function for updating a CFI data write fifo, an array of 4
51
47
* uint32_t and 128 bits of data that are allowed to be written through 4
52
- /* The channel i2c buses. */
48
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
53
- Pca954xChannel channel[PCA9548_CHANNEL_COUNT];
49
index XXXXXXX..XXXXXXX 100644
54
+ bool enabled[PCA9548_CHANNEL_COUNT];
50
--- a/hw/misc/xlnx-versal-cfu.c
55
+ I2CBus *bus[PCA9548_CHANNEL_COUNT];
51
+++ b/hw/misc/xlnx-versal-cfu.c
56
} Pca954xState;
52
@@ -XXX,XX +XXX,XX @@ static void cfu_stream_write(void *opaque, hwaddr addr, uint64_t value,
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ static bool pca954x_match(I2CSlave *candidate, uint8_t address,
60
}
61
62
for (i = 0; i < mc->nchans; i++) {
63
- if (!mux->channel[i].enabled) {
64
+ if (!mux->enabled[i]) {
65
continue;
66
}
67
68
- if (i2c_scan_bus(mux->channel[i].bus, address, broadcast,
69
+ if (i2c_scan_bus(mux->bus[i], address, broadcast,
70
current_devs)) {
71
if (!broadcast) {
72
return true;
73
@@ -XXX,XX +XXX,XX @@ static void pca954x_enable_channel(Pca954xState *s, uint8_t enable_mask)
74
*/
75
for (i = 0; i < mc->nchans; i++) {
76
if (enable_mask & (1 << i)) {
77
- s->channel[i].enabled = true;
78
+ s->enabled[i] = true;
79
} else {
80
- s->channel[i].enabled = false;
81
+ s->enabled[i] = false;
82
}
83
}
53
}
84
}
54
}
85
@@ -XXX,XX +XXX,XX @@ I2CBus *pca954x_i2c_get_bus(I2CSlave *mux, uint8_t channel)
55
86
Pca954xState *pca954x = PCA954X(mux);
56
+static uint64_t cfu_sfr_read(void *opaque, hwaddr addr, unsigned size)
87
57
+{
88
g_assert(channel < pc->nchans);
58
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
89
- return I2C_BUS(qdev_get_child_bus(DEVICE(&pca954x->channel[channel]),
59
+ HWADDR_PRIx "\n", __func__, addr);
90
- "i2c-bus"));
60
+ return 0;
91
-}
61
+}
92
-
62
+
93
-static void pca954x_channel_init(Object *obj)
63
+static void cfu_sfr_write(void *opaque, hwaddr addr, uint64_t value,
94
-{
64
+ unsigned size)
95
- Pca954xChannel *s = PCA954X_CHANNEL(obj);
65
+{
96
- s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
66
+ XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(opaque);
97
-
67
+ uint32_t wfifo[WFIFO_SZ];
98
- /* Start all channels as disabled. */
68
+
99
- s->enabled = false;
69
+ if (update_wfifo(addr, value, s->wfifo, wfifo)) {
100
-}
70
+ uint8_t row_addr = extract32(wfifo[0], 23, 5);
101
-
71
+ uint32_t frame_addr = extract32(wfifo[0], 0, 23);
102
-static void pca954x_channel_class_init(ObjectClass *klass, void *data)
72
+ XlnxCfiPacket pkt = { .reg_addr = CFRAME_SFR,
103
-{
73
+ .data[0] = frame_addr };
104
- DeviceClass *dc = DEVICE_CLASS(klass);
74
+
105
- dc->desc = "Pca954x Channel";
75
+ if (s->cfg.cfu) {
106
+ return pca954x->bus[channel];
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);
107
}
103
}
108
104
109
static void pca9546_class_init(ObjectClass *klass, void *data)
105
+static void cfu_sfr_init(Object *obj)
110
@@ -XXX,XX +XXX,XX @@ static void pca9548_class_init(ObjectClass *klass, void *data)
106
+{
111
s->nchans = PCA9548_CHANNEL_COUNT;
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;
112
}
157
}
113
158
114
-static void pca954x_realize(DeviceState *dev, Error **errp)
159
+static void cfu_sfr_class_init(ObjectClass *klass, void *data)
115
-{
160
+{
116
- Pca954xState *s = PCA954X(dev);
161
+ DeviceClass *dc = DEVICE_CLASS(klass);
117
- Pca954xClass *c = PCA954X_GET_CLASS(s);
162
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
118
- int i;
163
+
119
-
164
+ device_class_set_props(dc, cfu_sfr_props);
120
- /* SMBus modules. Cannot fail. */
165
+ dc->vmsd = &vmstate_cfu_sfr;
121
- for (i = 0; i < c->nchans; i++) {
166
+ rc->phases.enter = cfu_sfr_reset_enter;
122
- sysbus_realize(SYS_BUS_DEVICE(&s->channel[i]), &error_abort);
167
+}
123
- }
168
+
124
-}
169
static const TypeInfo cfu_apb_info = {
125
-
170
.name = TYPE_XLNX_VERSAL_CFU_APB,
126
static void pca954x_init(Object *obj)
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)
127
{
185
{
128
Pca954xState *s = PCA954X(obj);
186
type_register_static(&cfu_apb_info);
129
Pca954xClass *c = PCA954X_GET_CLASS(obj);
187
type_register_static(&cfu_fdro_info);
130
int i;
188
+ type_register_static(&cfu_sfr_info);
131
132
- /* Only initialize the children we expect. */
133
+ /* SMBus modules. Cannot fail. */
134
for (i = 0; i < c->nchans; i++) {
135
- object_initialize_child(obj, "channel[*]", &s->channel[i],
136
- TYPE_PCA954X_CHANNEL);
137
+ g_autofree gchar *bus_name = g_strdup_printf("i2c.%d", i);
138
+
139
+ /* start all channels as disabled. */
140
+ s->enabled[i] = false;
141
+ s->bus[i] = i2c_init_bus(DEVICE(s), bus_name);
142
}
143
}
189
}
144
190
145
@@ -XXX,XX +XXX,XX @@ static void pca954x_class_init(ObjectClass *klass, void *data)
191
type_init(cfu_apb_register_types)
146
rc->phases.enter = pca954x_enter_reset;
147
148
dc->desc = "Pca954x i2c-mux";
149
- dc->realize = pca954x_realize;
150
151
k->write_data = pca954x_write_data;
152
k->receive_byte = pca954x_read_byte;
153
@@ -XXX,XX +XXX,XX @@ static const TypeInfo pca954x_info[] = {
154
.parent = TYPE_PCA954X,
155
.class_init = pca9548_class_init,
156
},
157
- {
158
- .name = TYPE_PCA954X_CHANNEL,
159
- .parent = TYPE_SYS_BUS_DEVICE,
160
- .class_init = pca954x_channel_class_init,
161
- .instance_size = sizeof(Pca954xChannel),
162
- .instance_init = pca954x_channel_init,
163
- }
164
};
165
166
DEFINE_TYPES(pca954x_info)
167
--
192
--
168
2.25.1
193
2.34.1
169
170
diff view generated by jsdifflib
1
The AN547 application note URL has changed: update our comment
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
2
accordingly. (Rev B is still downloadable from the old URL,
3
but there is a new Rev C of the document now.)
4
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>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20220221094144.426191-1-peter.maydell@linaro.org
9
---
10
---
10
hw/arm/mps2-tz.c | 2 +-
11
MAINTAINERS | 2 +
11
1 file changed, 1 insertion(+), 1 deletion(-)
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
12
18
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
19
diff --git a/MAINTAINERS b/MAINTAINERS
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
21
--- a/MAINTAINERS
16
+++ b/hw/arm/mps2-tz.c
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
17
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
18
* Application Note AN524:
38
+/*
19
* https://developer.arm.com/documentation/dai0524/latest/
39
+ * QEMU model of the Configuration Frame Control module
20
* Application Note AN547:
40
+ *
21
- * https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/DAI0547B_SSE300_PLUS_U55_FPGA_for_mps3.pdf
41
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
22
+ * https://developer.arm.com/documentation/dai0547/latest/
42
+ *
23
*
43
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
24
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
44
+ *
25
* (ARM ECM0601256) for the details of some of the device layout:
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'))
26
--
1039
--
27
2.25.1
1040
2.34.1
28
29
diff view generated by jsdifflib
1
In commit 6e657e64cdc478 in 2013 we added some autorelease pools to
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
2
deal with complaints from macOS when we made calls into Cocoa from
3
threads that didn't have automatically created autorelease pools.
4
Later on, macOS got stricter about forbidding cross-thread Cocoa
5
calls, and in commit 5588840ff77800e839d8 we restructured the code to
6
avoid them. This left the autorelease pool creation in several
7
functions without any purpose; delete it.
8
2
9
We still need the pool in cocoa_refresh() for the clipboard related
3
Introduce a model of Xilinx Versal's Configuration Frame broadcast
10
code which is called directly there.
4
controller (CFRAME_BCAST_REG).
11
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
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
14
Tested-by: Akihiko Odaki <akihiko.odaki@gmail.com>
15
Message-id: 20220224101330.967429-3-peter.maydell@linaro.org
16
---
10
---
17
ui/cocoa.m | 6 ------
11
include/hw/misc/xlnx-versal-cframe-reg.h | 17 +++
18
1 file changed, 6 deletions(-)
12
hw/misc/xlnx-versal-cframe-reg.c | 161 +++++++++++++++++++++++
13
2 files changed, 178 insertions(+)
19
14
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
15
diff --git a/include/hw/misc/xlnx-versal-cframe-reg.h b/include/hw/misc/xlnx-versal-cframe-reg.h
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/ui/cocoa.m
17
--- a/include/hw/misc/xlnx-versal-cframe-reg.h
23
+++ b/ui/cocoa.m
18
+++ b/include/hw/misc/xlnx-versal-cframe-reg.h
24
@@ -XXX,XX +XXX,XX @@ int main (int argc, char **argv) {
19
@@ -XXX,XX +XXX,XX @@
25
static void cocoa_update(DisplayChangeListener *dcl,
20
#define TYPE_XLNX_VERSAL_CFRAME_REG "xlnx,cframe-reg"
26
int x, int y, int w, int h)
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)
27
{
134
{
28
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
135
XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev);
29
-
136
@@ -XXX,XX +XXX,XX @@ static Property cframe_regs_props[] = {
30
COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
137
DEFINE_PROP_END_OF_LIST(),
31
138
};
32
dispatch_async(dispatch_get_main_queue(), ^{
139
33
@@ -XXX,XX +XXX,XX @@ static void cocoa_update(DisplayChangeListener *dcl,
140
+static void cframe_bcast_reg_init(Object *obj)
34
}
141
+{
35
[cocoaView setNeedsDisplayInRect:rect];
142
+ XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
36
});
143
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
37
-
144
+
38
- [pool release];
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;
39
}
210
}
40
211
41
static void cocoa_switch(DisplayChangeListener *dcl,
212
+static void cframe_bcast_reg_class_init(ObjectClass *klass, void *data)
42
DisplaySurface *surface)
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)
43
{
238
{
44
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
239
type_register_static(&cframe_reg_info);
45
pixman_image_t *image = surface->image;
240
+ type_register_static(&cframe_bcast_reg_info);
46
47
COCOA_DEBUG("qemu_cocoa: cocoa_switch\n");
48
@@ -XXX,XX +XXX,XX @@ static void cocoa_switch(DisplayChangeListener *dcl,
49
[cocoaView updateUIInfo];
50
[cocoaView switchSurface:image];
51
});
52
- [pool release];
53
}
241
}
54
242
55
static void cocoa_refresh(DisplayChangeListener *dcl)
243
type_init(cframe_reg_register_types)
56
--
244
--
57
2.25.1
245
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
2
2
3
Merge tlbi_aa64_range_get_length and tlbi_aa64_range_get_base,
3
Connect the Configuration Frame Unit (CFU_APB, CFU_FDRO and CFU_SFR) to
4
returning a structure containing both results. Pass in the
4
the Versal machine.
5
ARMMMUIdx, rather than the digested two_ranges boolean.
6
5
7
This is in preparation for FEAT_LPA2, where the interpretation
6
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
of 'value' depends on the effective value of DS for the regime.
7
Acked-by: Edgar E. Iglesias <edgar@zeroasic.com>
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230831165701.2016397-8-francisco.iglesias@amd.com
12
Message-id: 20220301215958.157011-13-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
11
---
15
target/arm/helper.c | 58 +++++++++++++++++++--------------------------
12
include/hw/arm/xlnx-versal.h | 16 ++++++++++++++
16
1 file changed, 24 insertions(+), 34 deletions(-)
13
hw/arm/xlnx-versal.c | 42 ++++++++++++++++++++++++++++++++++++
14
2 files changed, 58 insertions(+)
17
15
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
18
--- a/include/hw/arm/xlnx-versal.h
21
+++ b/target/arm/helper.c
19
+++ b/include/hw/arm/xlnx-versal.h
22
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
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]);
23
}
70
}
24
71
25
#ifdef TARGET_AARCH64
72
+static void versal_create_cfu(Versal *s, qemu_irq *pic)
26
-static uint64_t tlbi_aa64_range_get_length(CPUARMState *env,
73
+{
27
- uint64_t value)
74
+ SysBusDevice *sbd;
28
-{
29
- unsigned int page_shift;
30
- unsigned int page_size_granule;
31
- uint64_t num;
32
- uint64_t scale;
33
- uint64_t exponent;
34
+typedef struct {
35
+ uint64_t base;
36
uint64_t length;
37
+} TLBIRange;
38
+
75
+
39
+static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
76
+ /* CFU FDRO */
40
+ uint64_t value)
77
+ object_initialize_child(OBJECT(s), "cfu-fdro", &s->pmc.cfu_fdro,
41
+{
78
+ TYPE_XLNX_VERSAL_CFU_FDRO);
42
+ unsigned int page_size_granule, page_shift, num, scale, exponent;
79
+ sbd = SYS_BUS_DEVICE(&s->pmc.cfu_fdro);
43
+ TLBIRange ret = { };
80
+
44
81
+ sysbus_realize(sbd, &error_fatal);
45
- num = extract64(value, 39, 5);
82
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_FDRO,
46
- scale = extract64(value, 44, 2);
83
+ sysbus_mmio_get_region(sbd, 0));
47
page_size_granule = extract64(value, 46, 2);
84
+
48
85
+ /* CFU APB */
49
if (page_size_granule == 0) {
86
+ object_initialize_child(OBJECT(s), "cfu-apb", &s->pmc.cfu_apb,
50
qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n",
87
+ TYPE_XLNX_VERSAL_CFU_APB);
51
page_size_granule);
88
+ sbd = SYS_BUS_DEVICE(&s->pmc.cfu_apb);
52
- return 0;
89
+
53
+ return ret;
90
+ sysbus_realize(sbd, &error_fatal);
54
}
91
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_APB,
55
92
+ sysbus_mmio_get_region(sbd, 0));
56
page_shift = (page_size_granule - 1) * 2 + 12;
93
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM,
57
-
94
+ sysbus_mmio_get_region(sbd, 1));
58
+ num = extract64(value, 39, 5);
95
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_STREAM_2,
59
+ scale = extract64(value, 44, 2);
96
+ sysbus_mmio_get_region(sbd, 2));
60
exponent = (5 * scale) + 1;
97
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
61
- length = (num + 1) << (exponent + page_shift);
98
+
62
99
+ /* CFU SFR */
63
- return length;
100
+ object_initialize_child(OBJECT(s), "cfu-sfr", &s->pmc.cfu_sfr,
64
-}
101
+ TYPE_XLNX_VERSAL_CFU_SFR);
65
+ ret.length = (num + 1) << (exponent + page_shift);
102
+
66
103
+ sbd = SYS_BUS_DEVICE(&s->pmc.cfu_sfr);
67
-static uint64_t tlbi_aa64_range_get_base(CPUARMState *env, uint64_t value,
104
+
68
- bool two_ranges)
105
+ object_property_set_link(OBJECT(&s->pmc.cfu_sfr),
69
-{
106
+ "cfu", OBJECT(&s->pmc.cfu_apb), &error_abort);
70
- /* TODO: ARMv8.7 FEAT_LPA2 */
107
+
71
- uint64_t pageaddr;
108
+ sysbus_realize(sbd, &error_fatal);
72
-
109
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_CFU_SFR,
73
- if (two_ranges) {
110
+ sysbus_mmio_get_region(sbd, 0));
74
- pageaddr = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
111
+}
75
+ if (regime_has_2_ranges(mmuidx)) {
112
+
76
+ ret.base = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
113
static void versal_create_crl(Versal *s, qemu_irq *pic)
77
} else {
78
- pageaddr = extract64(value, 0, 37) << TARGET_PAGE_BITS;
79
+ ret.base = extract64(value, 0, 37) << TARGET_PAGE_BITS;
80
}
81
82
- return pageaddr;
83
+ return ret;
84
}
85
86
static void do_rvae_write(CPUARMState *env, uint64_t value,
87
int idxmap, bool synced)
88
{
114
{
89
ARMMMUIdx one_idx = ARM_MMU_IDX_A | ctz32(idxmap);
115
SysBusDevice *sbd;
90
- bool two_ranges = regime_has_2_ranges(one_idx);
116
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
91
- uint64_t baseaddr, length;
117
versal_create_pmc_iou_slcr(s, pic);
92
+ TLBIRange range;
118
versal_create_ospi(s, pic);
93
int bits;
119
versal_create_crl(s, pic);
94
120
+ versal_create_cfu(s, pic);
95
- baseaddr = tlbi_aa64_range_get_base(env, value, two_ranges);
121
versal_map_ddr(s);
96
- length = tlbi_aa64_range_get_length(env, value);
122
versal_unimp(s);
97
- bits = tlbbits_for_regime(env, one_idx, baseaddr);
98
+ range = tlbi_aa64_get_range(env, one_idx, value);
99
+ bits = tlbbits_for_regime(env, one_idx, range.base);
100
101
if (synced) {
102
tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env),
103
- baseaddr,
104
- length,
105
+ range.base,
106
+ range.length,
107
idxmap,
108
bits);
109
} else {
110
- tlb_flush_range_by_mmuidx(env_cpu(env), baseaddr,
111
- length, idxmap, bits);
112
+ tlb_flush_range_by_mmuidx(env_cpu(env), range.base,
113
+ range.length, idxmap, bits);
114
}
115
}
116
123
117
--
124
--
118
2.25.1
125
2.34.1
diff view generated by jsdifflib
1
From: Jimmy Brisson <jimmy.brisson@linaro.org>
1
From: Francisco Iglesias <francisco.iglesias@amd.com>
2
2
3
With these interfaces missing, TFM would delegate peripherals 0, 1,
3
Connect the Configuration Frame controller (CFRAME_REG) and the
4
2, 3 and 8, and qemu would ignore the delegation of interface 8, as
4
Configuration Frame broadcast controller (CFRAME_BCAST_REG) to the
5
it thought interface 4 was eth & USB.
5
Versal machine.
6
6
7
This patch corrects this behavior and allows TFM to delegate the
7
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
eth & USB peripheral to NS mode.
9
10
(The old QEMU behaviour was based on revision B of the AN547
11
appnote; revision C corrects this error in the documentation,
12
and this commit brings QEMU in to line with how the FPGA
13
image really behaves.)
14
15
Signed-off-by: Jimmy Brisson <jimmy.brisson@linaro.org>
16
Message-id: 20220210210227.3203883-1-jimmy.brisson@linaro.org
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
[PMM: added commit message note clarifying that the old behaviour
9
Message-id: 20230831165701.2016397-9-francisco.iglesias@amd.com
19
was a docs issue, not because there were two different versions
20
of the FPGA image]
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
11
---
23
hw/arm/mps2-tz.c | 4 ++++
12
include/hw/arm/xlnx-versal.h | 69 +++++++++++++++++++++
24
1 file changed, 4 insertions(+)
13
hw/arm/xlnx-versal.c | 113 ++++++++++++++++++++++++++++++++++-
14
2 files changed, 181 insertions(+), 1 deletion(-)
25
15
26
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
27
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/mps2-tz.c
18
--- a/include/hw/arm/xlnx-versal.h
29
+++ b/hw/arm/mps2-tz.c
19
+++ b/include/hw/arm/xlnx-versal.h
30
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
20
@@ -XXX,XX +XXX,XX @@
31
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
21
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
32
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
22
#include "hw/net/xlnx-versal-canfd.h"
33
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
23
#include "hw/misc/xlnx-versal-cfu.h"
34
+ { /* port 4 USER AHB interface 0 */ },
24
+#include "hw/misc/xlnx-versal-cframe-reg.h"
35
+ { /* port 5 USER AHB interface 1 */ },
25
36
+ { /* port 6 USER AHB interface 2 */ },
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
37
+ { /* port 7 USER AHB interface 3 */ },
27
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
38
{ "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 49 } },
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
39
},
29
#define XLNX_VERSAL_NR_IRQS 192
40
},
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,
41
--
266
--
42
2.25.1
267
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The shift of the BaseADDR field depends on the translation
3
STGP writes to tag memory, it does not check it.
4
granule in use.
4
This happened to work because we wrote tag memory first
5
so that the check always succeeded.
5
6
6
Fixes: 84940ed8255 ("target/arm: Add support for FEAT_TLBIRANGE")
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reported-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230901203103.136408-1-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220301215958.157011-14-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
target/arm/helper.c | 5 +++--
12
target/arm/tcg/translate-a64.c | 41 +++++++++++++---------------------
14
1 file changed, 3 insertions(+), 2 deletions(-)
13
1 file changed, 15 insertions(+), 26 deletions(-)
15
14
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
17
--- a/target/arm/tcg/translate-a64.c
19
+++ b/target/arm/helper.c
18
+++ b/target/arm/tcg/translate-a64.c
20
@@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
19
@@ -XXX,XX +XXX,XX @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
21
ret.length = (num + 1) << (exponent + page_shift);
20
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
22
23
if (regime_has_2_ranges(mmuidx)) {
24
- ret.base = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
25
+ ret.base = sextract64(value, 0, 37);
26
} else {
27
- ret.base = extract64(value, 0, 37) << TARGET_PAGE_BITS;
28
+ ret.base = extract64(value, 0, 37);
29
}
21
}
30
+ ret.base <<= page_shift;
22
31
23
- if (!s->ata) {
32
return ret;
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;
33
}
78
}
34
--
79
--
35
2.25.1
80
2.34.1
diff view generated by jsdifflib
1
When we're using KVM, the PSCI implementation is provided by the
1
From: Colton Lewis <coltonlewis@google.com>
2
kernel, but QEMU has to tell the guest about it via the device tree.
3
Currently we look at the KVM_CAP_ARM_PSCI_0_2 capability to determine
4
if the kernel is providing at least PSCI 0.2, but if the kernel
5
provides a newer version than that we will still only tell the guest
6
it has PSCI 0.2. (This is fairly harmless; it just means the guest
7
won't use newer parts of the PSCI API.)
8
2
9
The kernel exposes the specific PSCI version it is implementing via
3
Due to recent KVM changes, QEMU is setting a ptimer offset resulting
10
the ONE_REG API; use this to report in the dtb that the PSCI
4
in unintended trap and emulate access and a consequent performance
11
implementation is 1.0-compatible if appropriate. (The device tree
5
hit. Filter out the PTIMER_CNT register to restore trapless ptimer
12
binding currently only distinguishes "pre-0.2", "0.2-compatible" and
6
access.
13
"1.0-compatible".)
14
7
8
Quoting Andrew Jones:
9
10
Simply reading the CNT register and writing back the same value is
11
enough to set an offset, since the timer will have certainly moved
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
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Marc Zyngier <maz@kernel.org>
17
Reviewed-by: Akihiko Odaki <akihiko.odaki@gmail.com>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Andrew Jones <drjones@redhat.com>
20
Message-id: 20220224134655.1207865-1-peter.maydell@linaro.org
21
---
30
---
22
target/arm/kvm-consts.h | 1 +
31
target/arm/kvm64.c | 1 +
23
hw/arm/boot.c | 5 ++---
32
1 file changed, 1 insertion(+)
24
target/arm/kvm64.c | 12 ++++++++++++
25
3 files changed, 15 insertions(+), 3 deletions(-)
26
33
27
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/kvm-consts.h
30
+++ b/target/arm/kvm-consts.h
31
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_1_0_FN_PSCI_FEATURES, PSCI_1_0_FN_PSCI_FEATURES);
32
33
#define QEMU_PSCI_VERSION_0_1 0x00001
34
#define QEMU_PSCI_VERSION_0_2 0x00002
35
+#define QEMU_PSCI_VERSION_1_0 0x10000
36
#define QEMU_PSCI_VERSION_1_1 0x10001
37
38
MISMATCH_CHECK(QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED, PSCI_0_2_TOS_MP);
39
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/boot.c
42
+++ b/hw/arm/boot.c
43
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
44
}
45
46
qemu_fdt_add_subnode(fdt, "/psci");
47
- if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2 ||
48
- armcpu->psci_version == QEMU_PSCI_VERSION_1_1) {
49
- if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2) {
50
+ if (armcpu->psci_version >= QEMU_PSCI_VERSION_0_2) {
51
+ if (armcpu->psci_version < QEMU_PSCI_VERSION_1_0) {
52
const char comp[] = "arm,psci-0.2\0arm,psci";
53
qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
54
} else {
55
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
34
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
56
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/kvm64.c
36
--- a/target/arm/kvm64.c
58
+++ b/target/arm/kvm64.c
37
+++ b/target/arm/kvm64.c
59
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
38
@@ -XXX,XX +XXX,XX @@ typedef struct CPRegStateLevel {
60
uint64_t mpidr;
39
*/
61
ARMCPU *cpu = ARM_CPU(cs);
40
static const CPRegStateLevel non_runtime_cpregs[] = {
62
CPUARMState *env = &cpu->env;
41
{ KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
63
+ uint64_t psciver;
42
+ { KVM_REG_ARM_PTIMER_CNT, KVM_PUT_FULL_STATE },
64
43
};
65
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE ||
44
66
!object_dynamic_cast(OBJECT(cpu), TYPE_AARCH64_CPU)) {
45
int kvm_arm_cpreg_level(uint64_t regidx)
67
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
68
}
69
}
70
71
+ /*
72
+ * KVM reports the exact PSCI version it is implementing via a
73
+ * special sysreg. If it is present, use its contents to determine
74
+ * what to report to the guest in the dtb (it is the PSCI version,
75
+ * in the same 15-bits major 16-bits minor format that PSCI_VERSION
76
+ * returns).
77
+ */
78
+ if (!kvm_get_one_reg(cs, KVM_REG_ARM_PSCI_VERSION, &psciver)) {
79
+ cpu->psci_version = psciver;
80
+ }
81
+
82
/*
83
* When KVM is in use, PSCI is emulated in-kernel and not by qemu.
84
* Currently KVM has its own idea about MPIDR assignment, so we
85
--
46
--
86
2.25.1
47
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The macro is a bit more readable than the inlined computation.
3
Provide a stub implementation, as a write is a "request".
4
4
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220301215958.157011-7-richard.henderson@linaro.org
6
Message-id: 20230831232441.66020-2-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/helper.c | 4 ++--
10
target/arm/helper.c | 64 +++++++++++++++++++++++++++++----------------
11
1 file changed, 2 insertions(+), 2 deletions(-)
11
1 file changed, 41 insertions(+), 23 deletions(-)
12
12
13
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
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
17
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
18
level = startlevel;
18
};
19
modify_arm_cp_regs(v8_idregs, v8_user_idregs);
20
#endif
21
- /* RVBAR_EL1 is only implemented if EL1 is the highest EL */
22
+ /*
23
+ * RVBAR_EL1 and RMR_EL1 only implemented if EL1 is the highest EL.
24
+ * TODO: For RMR, a write with bit 1 set should do something with
25
+ * cpu_reset(). In the meantime, "the bit is strictly a request",
26
+ * so we are in spec just ignoring writes.
27
+ */
28
if (!arm_feature(env, ARM_FEATURE_EL3) &&
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
}
19
}
88
}
20
89
21
- indexmask_grainsize = (1ULL << (stride + 3)) - 1;
90
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
22
- indexmask = (1ULL << (inputsize - (stride * (4 - level)))) - 1;
91
{ .name = "RVBAR_EL3", .state = ARM_CP_STATE_AA64,
23
+ indexmask_grainsize = MAKE_64BIT_MASK(0, stride + 3);
92
.opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 1,
24
+ indexmask = MAKE_64BIT_MASK(0, inputsize - (stride * (4 - level)));
93
.access = PL3_R,
25
94
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
26
/* Now we can extract the actual base address from the TTBR */
95
- },
27
descaddr = extract64(ttbr, 0, 48);
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,
28
--
107
--
29
2.25.1
108
2.34.1
30
31
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We will shortly share parts of this function with other portions
3
The cortex-a710 is a first generation ARMv9.0-A processor.
4
of address translation.
5
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230831232441.66020-3-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220301215958.157011-5-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
9
---
13
target/arm/internals.h | 19 +------------------
10
docs/system/arm/virt.rst | 1 +
14
target/arm/helper.c | 22 ++++++++++++++++++++++
11
hw/arm/virt.c | 1 +
15
2 files changed, 23 insertions(+), 18 deletions(-)
12
target/arm/tcg/cpu64.c | 212 +++++++++++++++++++++++++++++++++++++++
13
3 files changed, 214 insertions(+)
16
14
17
diff --git a/target/arm/internals.h b/target/arm/internals.h
15
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/internals.h
17
--- a/docs/system/arm/virt.rst
20
+++ b/target/arm/internals.h
18
+++ b/docs/system/arm/virt.rst
21
@@ -XXX,XX +XXX,XX @@ static inline void update_spsel(CPUARMState *env, uint32_t imm)
19
@@ -XXX,XX +XXX,XX @@ Supported guest CPU types:
22
* Returns the implementation defined bit-width of physical addresses.
20
- ``cortex-a57`` (64-bit)
23
* The ARMv8 reference manuals refer to this as PAMax().
21
- ``cortex-a72`` (64-bit)
24
*/
22
- ``cortex-a76`` (64-bit)
25
-static inline unsigned int arm_pamax(ARMCPU *cpu)
23
+- ``cortex-a710`` (64-bit)
26
-{
24
- ``a64fx`` (64-bit)
27
- static const unsigned int pamax_map[] = {
25
- ``host`` (with KVM only)
28
- [0] = 32,
26
- ``neoverse-n1`` (64-bit)
29
- [1] = 36,
27
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
30
- [2] = 40,
31
- [3] = 42,
32
- [4] = 44,
33
- [5] = 48,
34
- };
35
- unsigned int parange =
36
- FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
37
-
38
- /* id_aa64mmfr0 is a read-only register so values outside of the
39
- * supported mappings can be considered an implementation error. */
40
- assert(parange < ARRAY_SIZE(pamax_map));
41
- return pamax_map[parange];
42
-}
43
+unsigned int arm_pamax(ARMCPU *cpu);
44
45
/* Return true if extended addresses are enabled.
46
* This is always the case if our translation regime is 64 bit,
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
29
--- a/hw/arm/virt.c
50
+++ b/target/arm/helper.c
30
+++ b/hw/arm/virt.c
51
@@ -XXX,XX +XXX,XX @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs)
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);
52
}
45
}
53
#endif /* !CONFIG_USER_ONLY */
46
54
47
+static const ARMCPRegInfo cortex_a710_cp_reginfo[] = {
55
+/* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */
48
+ { .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
56
+unsigned int arm_pamax(ARMCPU *cpu)
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)
57
+{
172
+{
58
+ static const unsigned int pamax_map[] = {
173
+ ARMCPU *cpu = ARM_CPU(obj);
59
+ [0] = 32,
174
+
60
+ [1] = 36,
175
+ cpu->dtb_compatible = "arm,cortex-a710";
61
+ [2] = 40,
176
+ set_feature(&cpu->env, ARM_FEATURE_V8);
62
+ [3] = 42,
177
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
63
+ [4] = 44,
178
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
64
+ [5] = 48,
179
+ set_feature(&cpu->env, ARM_FEATURE_AARCH64);
65
+ };
180
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
66
+ unsigned int parange =
181
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
67
+ FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
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 */
68
+
237
+
69
+ /*
238
+ /*
70
+ * id_aa64mmfr0 is a read-only register so values outside of the
239
+ * The cortex-a710 TRM does not list CCSIDR values. The layout of
71
+ * supported mappings can be considered an implementation error.
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.
72
+ */
244
+ */
73
+ assert(parange < ARRAY_SIZE(pamax_map));
245
+ cpu->ccsidr[0] = make_ccsidr64(4, 64, 64 * KiB); /* L1 dcache */
74
+ return pamax_map[parange];
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);
75
+}
256
+}
76
+
257
+
77
static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx)
258
/*
78
{
259
* -cpu max: a CPU with as many features enabled as our emulation supports.
79
if (regime_has_2_ranges(mmu_idx)) {
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 },
80
--
269
--
81
2.25.1
270
2.34.1
82
83
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This field controls the output (intermediate) physical address size
3
Perform the check for EL2 enabled in the security space and the
4
of the translation process. V8 requires to raise an AddressSize
4
TIDCP bit in an out-of-line helper.
5
fault if the page tables are programmed incorrectly, such that any
6
intermediate descriptor address, or the final translated address,
7
is out of range.
8
5
9
Add a PS field to ARMVAParameters, and properly compute outputsize
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
in get_phys_addr_lpae. Test the descaddr as extracted from TTBR
7
Message-id: 20230831232441.66020-4-richard.henderson@linaro.org
11
and from page table entries.
12
13
Restrict descaddrmask so that we won't raise the fault for v7.
14
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20220301215958.157011-8-richard.henderson@linaro.org
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
10
---
21
target/arm/internals.h | 1 +
11
target/arm/helper.h | 1 +
22
target/arm/helper.c | 72 ++++++++++++++++++++++++++++++++----------
12
target/arm/tcg/op_helper.c | 13 +++++++++++++
23
2 files changed, 57 insertions(+), 16 deletions(-)
13
target/arm/tcg/translate-a64.c | 16 ++++++++++++++--
14
target/arm/tcg/translate.c | 27 +++++++++++++++++++++++++++
15
4 files changed, 55 insertions(+), 2 deletions(-)
24
16
25
diff --git a/target/arm/internals.h b/target/arm/internals.h
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/internals.h
19
--- a/target/arm/helper.h
28
+++ b/target/arm/internals.h
20
+++ b/target/arm/helper.h
29
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, i32)
30
*/
22
31
typedef struct ARMVAParameters {
23
DEF_HELPER_4(access_check_cp_reg, cptr, env, i32, i32, i32)
32
unsigned tsz : 8;
24
DEF_HELPER_FLAGS_2(lookup_cp_reg, TCG_CALL_NO_RWG_SE, cptr, env, i32)
33
+ unsigned ps : 3;
25
+DEF_HELPER_FLAGS_2(tidcp_el1, TCG_CALL_NO_WG, void, env, i32)
34
unsigned select : 1;
26
DEF_HELPER_3(set_cp_reg, void, env, cptr, i32)
35
bool tbi : 1;
27
DEF_HELPER_2(get_cp_reg, i32, env, cptr)
36
bool epd : 1;
28
DEF_HELPER_3(set_cp_reg64, void, env, cptr, i64)
37
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
38
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/helper.c
31
--- a/target/arm/tcg/op_helper.c
40
+++ b/target/arm/helper.c
32
+++ b/target/arm/tcg/op_helper.c
41
@@ -XXX,XX +XXX,XX @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs)
33
@@ -XXX,XX +XXX,XX @@ const void *HELPER(lookup_cp_reg)(CPUARMState *env, uint32_t key)
34
return ri;
42
}
35
}
43
#endif /* !CONFIG_USER_ONLY */
36
44
37
+/*
45
+/* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
38
+ * Test for HCR_EL2.TIDCP at EL1.
46
+static const uint8_t pamax_map[] = {
39
+ * Since implementation defined registers are rare, and within QEMU
47
+ [0] = 32,
40
+ * most of them are no-op, do not waste HFLAGS space for this and
48
+ [1] = 36,
41
+ * always use a helper.
49
+ [2] = 40,
42
+ */
50
+ [3] = 42,
43
+void HELPER(tidcp_el1)(CPUARMState *env, uint32_t syndrome)
51
+ [4] = 44,
44
+{
52
+ [5] = 48,
45
+ if (arm_hcr_el2_eff(env) & HCR_TIDCP) {
53
+};
46
+ raise_exception_ra(env, EXCP_UDEF, syndrome, 2, GETPC());
47
+ }
48
+}
54
+
49
+
55
/* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */
50
void HELPER(set_cp_reg)(CPUARMState *env, const void *rip, uint32_t value)
56
unsigned int arm_pamax(ARMCPU *cpu)
57
{
51
{
58
- static const unsigned int pamax_map[] = {
52
const ARMCPRegInfo *ri = rip;
59
- [0] = 32,
53
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
60
- [1] = 36,
54
index XXXXXXX..XXXXXXX 100644
61
- [2] = 40,
55
--- a/target/arm/tcg/translate-a64.c
62
- [3] = 42,
56
+++ b/target/arm/tcg/translate-a64.c
63
- [4] = 44,
57
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, bool isread,
64
- [5] = 48,
58
bool need_exit_tb = false;
65
- };
59
TCGv_ptr tcg_ri = NULL;
66
unsigned int parange =
60
TCGv_i64 tcg_rt;
67
FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
61
+ uint32_t syndrome;
68
62
+
69
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
63
+ if (crn == 11 || crn == 15) {
70
{
64
+ /*
71
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
65
+ * Check for TIDCP trap, which must take precedence over
72
bool epd, hpd, using16k, using64k, tsz_oob;
66
+ * the UNDEF for "no such register" etc.
73
- int select, tsz, tbi, max_tsz, min_tsz;
67
+ */
74
+ int select, tsz, tbi, max_tsz, min_tsz, ps;
68
+ syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
75
69
+ switch (s->current_el) {
76
if (!regime_has_2_ranges(mmu_idx)) {
70
+ case 1:
77
select = 0;
71
+ gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
78
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
72
+ break;
79
hpd = extract32(tcr, 24, 1);
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,
80
}
113
}
81
epd = false;
82
+ ps = extract32(tcr, 16, 3);
83
} else {
84
/*
85
* Bit 55 is always between the two regions, and is canonical for
86
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
87
epd = extract32(tcr, 23, 1);
88
hpd = extract64(tcr, 42, 1);
89
}
90
+ ps = extract64(tcr, 32, 3);
91
}
114
}
92
115
93
if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
116
+ if (cpnum == 15 && aa32_cpreg_encoding_in_impdef_space(crn, crm)) {
94
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
95
96
return (ARMVAParameters) {
97
.tsz = tsz,
98
+ .ps = ps,
99
.select = select,
100
.tbi = tbi,
101
.epd = epd,
102
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
103
104
/* TODO: This code does not support shareability levels. */
105
if (aarch64) {
106
+ int ps;
107
+
108
param = aa64_va_parameters(env, address, mmu_idx,
109
access_type != MMU_INST_FETCH);
110
level = 0;
111
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
112
113
addrsize = 64 - 8 * param.tbi;
114
inputsize = 64 - param.tsz;
115
- outputsize = arm_pamax(cpu);
116
+
117
+ /*
117
+ /*
118
+ * Bound PS by PARANGE to find the effective output address size.
118
+ * Check for TIDCP trap, which must take precedence over the UNDEF
119
+ * ID_AA64MMFR0 is a read-only register so values outside of the
119
+ * for "no such register" etc. It shares precedence with HSTR,
120
+ * supported mappings can be considered an implementation error.
120
+ * but raises the same exception, so order doesn't matter.
121
+ */
121
+ */
122
+ ps = FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
122
+ switch (s->current_el) {
123
+ ps = MIN(ps, param.ps);
123
+ case 1:
124
+ assert(ps < ARRAY_SIZE(pamax_map));
124
+ gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
125
+ outputsize = pamax_map[ps];
125
+ break;
126
} else {
126
+ }
127
param = aa32_va_parameters(env, address, mmu_idx);
128
level = 1;
129
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
130
131
/* Now we can extract the actual base address from the TTBR */
132
descaddr = extract64(ttbr, 0, 48);
133
+
134
+ /*
135
+ * If the base address is out of range, raise AddressSizeFault.
136
+ * In the pseudocode, this is !IsZero(baseregister<47:outputsize>),
137
+ * but we've just cleared the bits above 47, so simplify the test.
138
+ */
139
+ if (descaddr >> outputsize) {
140
+ level = 0;
141
+ fault_type = ARMFault_AddressSize;
142
+ goto do_fault;
143
+ }
127
+ }
144
+
128
+
145
/*
129
if (!ri) {
146
* We rely on this masking to clear the RES0 bits at the bottom of the TTBR
130
/*
147
* and also to mask out CnP (bit 0) which could validly be non-zero.
131
* Unknown register; this might be a guest error or a QEMU
148
*/
149
descaddr &= ~indexmask;
150
151
- /* The address field in the descriptor goes up to bit 39 for ARMv7
152
- * but up to bit 47 for ARMv8, but we use the descaddrmask
153
- * up to bit 39 for AArch32, because we don't need other bits in that case
154
- * to construct next descriptor address (anyway they should be all zeroes).
155
+ /*
156
+ * For AArch32, the address field in the descriptor goes up to bit 39
157
+ * for both v7 and v8. However, for v8 the SBZ bits [47:40] must be 0
158
+ * or an AddressSize fault is raised. So for v8 we extract those SBZ
159
+ * bits as part of the address, which will be checked via outputsize.
160
+ * For AArch64, the address field always goes up to bit 47 (with extra
161
+ * bits for FEAT_LPA placed elsewhere). AArch64 implies v8.
162
*/
163
- descaddrmask = ((1ull << (aarch64 ? 48 : 40)) - 1) &
164
- ~indexmask_grainsize;
165
+ if (arm_feature(env, ARM_FEATURE_V8)) {
166
+ descaddrmask = MAKE_64BIT_MASK(0, 48);
167
+ } else {
168
+ descaddrmask = MAKE_64BIT_MASK(0, 40);
169
+ }
170
+ descaddrmask &= ~indexmask_grainsize;
171
172
/* Secure accesses start with the page table in secure memory and
173
* can be downgraded to non-secure at any step. Non-secure accesses
174
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
175
/* Invalid, or the Reserved level 3 encoding */
176
goto do_fault;
177
}
178
+
179
descaddr = descriptor & descaddrmask;
180
+ if (descaddr >> outputsize) {
181
+ fault_type = ARMFault_AddressSize;
182
+ goto do_fault;
183
+ }
184
185
if ((descriptor & 2) && (level < 3)) {
186
/* Table entry. The top five bits are attributes which may
187
--
132
--
188
2.25.1
133
2.34.1
189
190
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This feature widens physical addresses (and intermediate physical
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
addresses for 2-stage translation) from 48 to 52 bits, when using
4
Message-id: 20230831232441.66020-5-richard.henderson@linaro.org
5
4k or 16k pages.
6
7
This introduces the DS bit to TCR_ELx, which is RES0 unless the
8
page size is enabled and supports LPA2, resulting in the effective
9
value of DS for a given table walk. The DS bit changes the format
10
of the page table descriptor slightly, moving the PS field out to
11
TCR so that all pages have the same sharability and repurposing
12
those bits of the page table descriptor for the highest bits of
13
the output address.
14
15
Do not yet enable FEAT_LPA2; we need extra plumbing to avoid
16
tickling an old kernel bug.
17
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20220301215958.157011-17-richard.henderson@linaro.org
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
7
---
23
docs/system/arm/emulation.rst | 1 +
8
docs/system/arm/emulation.rst | 1 +
24
target/arm/cpu.h | 22 ++++++++
9
target/arm/cpu.h | 5 +++++
25
target/arm/internals.h | 2 +
10
target/arm/helper.h | 1 +
26
target/arm/helper.c | 102 +++++++++++++++++++++++++++++-----
11
target/arm/tcg/cpu64.c | 1 +
27
4 files changed, 112 insertions(+), 15 deletions(-)
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(+)
28
16
29
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
30
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
31
--- a/docs/system/arm/emulation.rst
19
--- a/docs/system/arm/emulation.rst
32
+++ b/docs/system/arm/emulation.rst
20
+++ b/docs/system/arm/emulation.rst
33
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
21
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
34
- FEAT_JSCVT (JavaScript conversion instructions)
22
- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
35
- FEAT_LOR (Limited ordering regions)
23
- FEAT_SPECRES (Speculation restriction instructions)
36
- FEAT_LPA (Large Physical Address space)
24
- FEAT_SSBS (Speculative Store Bypass Safe)
37
+- FEAT_LPA2 (Large Physical and virtual Address space v2)
25
+- FEAT_TIDCP1 (EL0 use of IMPLEMENTATION DEFINED functionality)
38
- FEAT_LRCPC (Load-acquire RCpc instructions)
26
- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
39
- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
27
- FEAT_TLBIRANGE (TLB invalidate range instructions)
40
- FEAT_LSE (Large System Extensions)
28
- FEAT_TTCNP (Translation table Common not private translations)
41
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
42
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/cpu.h
31
--- a/target/arm/cpu.h
44
+++ b/target/arm/cpu.h
32
+++ b/target/arm/cpu.h
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id)
33
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
46
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0;
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
47
}
35
}
48
36
49
+static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
37
+static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
50
+{
38
+{
51
+ return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1;
39
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0;
52
+}
40
+}
53
+
41
+
54
+static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id)
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)
74
}
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)
55
+{
82
+{
56
+ unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2);
83
+ /* See arm_sctlr(), but we also need the sctlr el. */
57
+ return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id));
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
+ }
58
+}
95
+}
59
+
96
+
60
+static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id)
97
void HELPER(set_cp_reg)(CPUARMState *env, const void *rip, uint32_t value)
61
+{
62
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2;
63
+}
64
+
65
+static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id)
66
+{
67
+ unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2);
68
+ return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id));
69
+}
70
+
71
static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
72
{
98
{
73
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
99
const ARMCPRegInfo *ri = rip;
74
diff --git a/target/arm/internals.h b/target/arm/internals.h
100
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
75
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/internals.h
102
--- a/target/arm/tcg/translate-a64.c
77
+++ b/target/arm/internals.h
103
+++ b/target/arm/tcg/translate-a64.c
78
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
104
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, bool isread,
79
typedef struct ARMVAParameters {
105
*/
80
unsigned tsz : 8;
106
syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
81
unsigned ps : 3;
107
switch (s->current_el) {
82
+ unsigned sh : 2;
108
+ case 0:
83
unsigned select : 1;
109
+ if (dc_isar_feature(aa64_tidcp1, s)) {
84
bool tbi : 1;
110
+ gen_helper_tidcp_el0(cpu_env, tcg_constant_i32(syndrome));
85
bool epd : 1;
86
@@ -XXX,XX +XXX,XX @@ typedef struct ARMVAParameters {
87
bool using16k : 1;
88
bool using64k : 1;
89
bool tsz_oob : 1; /* tsz has been clamped to legal range */
90
+ bool ds : 1;
91
} ARMVAParameters;
92
93
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
94
diff --git a/target/arm/helper.c b/target/arm/helper.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/helper.c
97
+++ b/target/arm/helper.c
98
@@ -XXX,XX +XXX,XX @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
99
} else {
100
ret.base = extract64(value, 0, 37);
101
}
102
+ if (param.ds) {
103
+ /*
104
+ * With DS=1, BaseADDR is always shifted 16 so that it is able
105
+ * to address all 52 va bits. The input address is perforce
106
+ * aligned on a 64k boundary regardless of translation granule.
107
+ */
108
+ page_shift = 16;
109
+ }
110
ret.base <<= page_shift;
111
112
return ret;
113
@@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
114
const int grainsize = stride + 3;
115
int startsizecheck;
116
117
- /* Negative levels are never allowed. */
118
- if (level < 0) {
119
+ /*
120
+ * Negative levels are usually not allowed...
121
+ * Except for FEAT_LPA2, 4k page table, 52-bit address space, which
122
+ * begins with level -1. Note that previous feature tests will have
123
+ * eliminated this combination if it is not enabled.
124
+ */
125
+ if (level < (inputsize == 52 && stride == 9 ? -1 : 0)) {
126
return false;
127
}
128
129
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
130
ARMMMUIdx mmu_idx, bool data)
131
{
132
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
133
- bool epd, hpd, using16k, using64k, tsz_oob;
134
- int select, tsz, tbi, max_tsz, min_tsz, ps;
135
+ bool epd, hpd, using16k, using64k, tsz_oob, ds;
136
+ int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
137
+ ARMCPU *cpu = env_archcpu(env);
138
139
if (!regime_has_2_ranges(mmu_idx)) {
140
select = 0;
141
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
142
hpd = extract32(tcr, 24, 1);
143
}
144
epd = false;
145
+ sh = extract32(tcr, 12, 2);
146
ps = extract32(tcr, 16, 3);
147
+ ds = extract64(tcr, 32, 1);
148
} else {
149
/*
150
* Bit 55 is always between the two regions, and is canonical for
151
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
152
if (!select) {
153
tsz = extract32(tcr, 0, 6);
154
epd = extract32(tcr, 7, 1);
155
+ sh = extract32(tcr, 12, 2);
156
using64k = extract32(tcr, 14, 1);
157
using16k = extract32(tcr, 15, 1);
158
hpd = extract64(tcr, 41, 1);
159
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
160
using64k = tg == 3;
161
tsz = extract32(tcr, 16, 6);
162
epd = extract32(tcr, 23, 1);
163
+ sh = extract32(tcr, 28, 2);
164
hpd = extract64(tcr, 42, 1);
165
}
166
ps = extract64(tcr, 32, 3);
167
+ ds = extract64(tcr, 59, 1);
168
}
169
170
- if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
171
+ if (cpu_isar_feature(aa64_st, cpu)) {
172
max_tsz = 48 - using64k;
173
} else {
174
max_tsz = 39;
175
}
176
177
+ /*
178
+ * DS is RES0 unless FEAT_LPA2 is supported for the given page size;
179
+ * adjust the effective value of DS, as documented.
180
+ */
181
min_tsz = 16;
182
if (using64k) {
183
- if (cpu_isar_feature(aa64_lva, env_archcpu(env))) {
184
+ if (cpu_isar_feature(aa64_lva, cpu)) {
185
+ min_tsz = 12;
186
+ }
187
+ ds = false;
188
+ } else if (ds) {
189
+ switch (mmu_idx) {
190
+ case ARMMMUIdx_Stage2:
191
+ case ARMMMUIdx_Stage2_S:
192
+ if (using16k) {
193
+ ds = cpu_isar_feature(aa64_tgran16_2_lpa2, cpu);
194
+ } else {
195
+ ds = cpu_isar_feature(aa64_tgran4_2_lpa2, cpu);
196
+ }
111
+ }
197
+ break;
112
+ break;
198
+ default:
113
case 1:
199
+ if (using16k) {
114
gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
200
+ ds = cpu_isar_feature(aa64_tgran16_lpa2, cpu);
115
break;
201
+ } else {
116
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
202
+ ds = cpu_isar_feature(aa64_tgran4_lpa2, cpu);
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));
203
+ }
128
+ }
204
+ break;
129
+ break;
205
+ }
130
case 1:
206
+ if (ds) {
131
gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
207
min_tsz = 12;
132
break;
208
}
209
}
210
- /* TODO: FEAT_LPA2 */
211
212
if (tsz > max_tsz) {
213
tsz = max_tsz;
214
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
215
return (ARMVAParameters) {
216
.tsz = tsz,
217
.ps = ps,
218
+ .sh = sh,
219
.select = select,
220
.tbi = tbi,
221
.epd = epd,
222
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
223
.using16k = using16k,
224
.using64k = using64k,
225
.tsz_oob = tsz_oob,
226
+ .ds = ds,
227
};
228
}
229
230
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
231
* VTCR_EL2.SL0 field (whose interpretation depends on the page size)
232
*/
233
uint32_t sl0 = extract32(tcr->raw_tcr, 6, 2);
234
+ uint32_t sl2 = extract64(tcr->raw_tcr, 33, 1);
235
uint32_t startlevel;
236
bool ok;
237
238
- if (!aarch64 || stride == 9) {
239
+ /* SL2 is RES0 unless DS=1 & 4kb granule. */
240
+ if (param.ds && stride == 9 && sl2) {
241
+ if (sl0 != 0) {
242
+ level = 0;
243
+ fault_type = ARMFault_Translation;
244
+ goto do_fault;
245
+ }
246
+ startlevel = -1;
247
+ } else if (!aarch64 || stride == 9) {
248
/* AArch32 or 4KB pages */
249
startlevel = 2 - sl0;
250
251
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
252
* for both v7 and v8. However, for v8 the SBZ bits [47:40] must be 0
253
* or an AddressSize fault is raised. So for v8 we extract those SBZ
254
* bits as part of the address, which will be checked via outputsize.
255
- * For AArch64, the address field always goes up to bit 47 (with extra
256
- * bits for FEAT_LPA placed elsewhere). AArch64 implies v8.
257
+ * For AArch64, the address field goes up to bit 47, or 49 with FEAT_LPA2;
258
+ * the highest bits of a 52-bit output are placed elsewhere.
259
*/
260
- if (arm_feature(env, ARM_FEATURE_V8)) {
261
+ if (param.ds) {
262
+ descaddrmask = MAKE_64BIT_MASK(0, 50);
263
+ } else if (arm_feature(env, ARM_FEATURE_V8)) {
264
descaddrmask = MAKE_64BIT_MASK(0, 48);
265
} else {
266
descaddrmask = MAKE_64BIT_MASK(0, 40);
267
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
268
269
/*
270
* For FEAT_LPA and PS=6, bits [51:48] of descaddr are in [15:12]
271
- * of descriptor. Otherwise, if descaddr is out of range, raise
272
- * AddressSizeFault.
273
+ * of descriptor. For FEAT_LPA2 and effective DS, bits [51:50] of
274
+ * descaddr are in [9:8]. Otherwise, if descaddr is out of range,
275
+ * raise AddressSizeFault.
276
*/
277
if (outputsize > 48) {
278
- descaddr |= extract64(descriptor, 12, 4) << 48;
279
+ if (param.ds) {
280
+ descaddr |= extract64(descriptor, 8, 2) << 50;
281
+ } else {
282
+ descaddr |= extract64(descriptor, 12, 4) << 48;
283
+ }
284
} else if (descaddr >> outputsize) {
285
fault_type = ARMFault_AddressSize;
286
goto do_fault;
287
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
288
assert(attrindx <= 7);
289
cacheattrs->attrs = extract64(mair, attrindx * 8, 8);
290
}
291
- cacheattrs->shareability = extract32(attrs, 6, 2);
292
+
293
+ /*
294
+ * For FEAT_LPA2 and effective DS, the SH field in the attributes
295
+ * was re-purposed for output address bits. The SH attribute in
296
+ * that case comes from TCR_ELx, which we extracted earlier.
297
+ */
298
+ if (param.ds) {
299
+ cacheattrs->shareability = param.sh;
300
+ } else {
301
+ cacheattrs->shareability = extract32(attrs, 6, 2);
302
+ }
303
304
*phys_ptr = descaddr;
305
*page_size_ptr = page_size;
306
--
133
--
307
2.25.1
134
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Set this as the kernel would, to 48 bits, to keep the computation
3
The linux kernel detects and enables this bit. Once trapped,
4
of the address space correct for PAuth.
4
EC_SYSTEMREGISTERTRAP is treated like EC_UNCATEGORIZED, so
5
no changes required within linux-user/aarch64/cpu_loop.c.
5
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230831232441.66020-6-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220301215958.157011-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
target/arm/cpu.c | 3 ++-
12
target/arm/cpu.c | 4 ++++
12
1 file changed, 2 insertions(+), 1 deletion(-)
13
1 file changed, 4 insertions(+)
13
14
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
17
--- a/target/arm/cpu.c
17
+++ b/target/arm/cpu.c
18
+++ b/target/arm/cpu.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
19
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset_hold(Object *obj)
19
aarch64_sve_zcr_get_valid_len(cpu, cpu->sve_default_vq - 1);
20
SCTLR_EnDA | SCTLR_EnDB);
20
}
21
/* Trap on btype=3 for PACIxSP. */
21
/*
22
env->cp15.sctlr_el[1] |= SCTLR_BT0;
22
+ * Enable 48-bit address space (TODO: take reserved_va into account).
23
+ /* Trap on implementation defined registers. */
23
* Enable TBI0 but not TBI1.
24
+ if (cpu_isar_feature(aa64_tidcp1, cpu)) {
24
* Note that this must match useronly_clean_ptr.
25
+ env->cp15.sctlr_el[1] |= SCTLR_TIDCP;
25
*/
26
+ }
26
- env->cp15.tcr_el[1].raw_tcr = (1ULL << 37);
27
/* and to the FP/Neon instructions */
27
+ env->cp15.tcr_el[1].raw_tcr = 5 | (1ULL << 37);
28
env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
28
29
CPACR_EL1, FPEN, 3);
29
/* Enable MTE */
30
if (cpu_isar_feature(aa64_mte, cpu)) {
31
--
30
--
32
2.25.1
31
2.34.1
diff view generated by jsdifflib
1
From: Wentao_Liang <Wentao_Liang_g@163.com>
1
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
2
2
3
handle_simd_shift_fpint_conv() was accidentally freeing the TCG
3
Now that we have Eager Page Split support added for ARM in the kernel,
4
temporary tcg_fpstatus too early, before the last use of it. Move
4
enable it in Qemu. This adds,
5
the free down to where it belongs.
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.
6
7
7
Signed-off-by: Wentao_Liang <Wentao_Liang_g@163.com>
8
The chunk size specifies how many pages to break at a time, using a
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
single allocation. Bigger the chunk size, more pages need to be
9
[PMM: cleaned up commit message]
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
target/arm/translate-a64.c | 2 +-
17
include/sysemu/kvm_int.h | 1 +
13
1 file changed, 1 insertion(+), 1 deletion(-)
18
accel/kvm/kvm-all.c | 1 +
19
target/arm/kvm.c | 61 ++++++++++++++++++++++++++++++++++++++++
20
qemu-options.hx | 15 ++++++++++
21
4 files changed, 78 insertions(+)
14
22
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
23
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
16
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
25
--- a/include/sysemu/kvm_int.h
18
+++ b/target/arm/translate-a64.c
26
+++ b/include/sysemu/kvm_int.h
19
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
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)
20
}
60
}
21
}
61
}
22
62
23
- tcg_temp_free_ptr(tcg_fpstatus);
63
+ if (s->kvm_eager_split_size) {
24
tcg_temp_free_i32(tcg_shift);
64
+ uint32_t sizes;
25
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
65
+
26
+ tcg_temp_free_ptr(tcg_fpstatus);
66
+ sizes = kvm_vm_check_extension(s, KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES);
27
tcg_temp_free_i32(tcg_rmode);
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;
28
}
88
}
29
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.
30
--
166
--
31
2.25.1
167
2.34.1
diff view generated by jsdifflib