1
First pullreq for 6.0: mostly my v8.1M work, plus some other
1
Two small bugfixes, plus most of RTH's refactoring of cpregs
2
bits and pieces. (I still have a lot of stuff in my to-review
2
handling.
3
folder, which I may or may not get to before the Christmas break...)
4
3
5
thanks
6
-- PMM
4
-- PMM
7
5
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
6
The following changes since commit 1fba9dc71a170b3a05b9d3272dd8ecfe7f26e215:
9
7
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +0000)
8
Merge tag 'pull-request-2022-05-04' of https://gitlab.com/thuth/qemu into staging (2022-05-04 08:07:02 -0700)
11
9
12
are available in the Git repository at:
10
are available in the Git repository at:
13
11
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220505
15
13
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
14
for you to fetch changes up to 99a50d1a67c602126fc2b3a4812d3000eba9bf34:
17
15
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
16
target/arm: read access to performance counters from EL0 (2022-05-05 09:36:22 +0100)
19
17
20
----------------------------------------------------------------
18
----------------------------------------------------------------
21
target-arm queue:
19
target-arm queue:
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
20
* Enable read access to performance counters from EL0
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
21
* Enable SCTLR_EL1.BT0 for aarch64-linux-user
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
22
* Refactoring of cpreg handling
25
* Various minor code cleanups
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
27
* Implement more pieces of ARMv8.1M support
28
23
29
----------------------------------------------------------------
24
----------------------------------------------------------------
30
Alex Chen (4):
25
Alex Zuepke (1):
31
i.MX25: Fix bad printf format specifiers
26
target/arm: read access to performance counters from EL0
32
i.MX31: Fix bad printf format specifiers
33
i.MX6: Fix bad printf format specifiers
34
i.MX6ul: Fix bad printf format specifiers
35
27
36
Havard Skinnemoen (1):
28
Richard Henderson (22):
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
29
target/arm: Enable SCTLR_EL1.BT0 for aarch64-linux-user
30
target/arm: Split out cpregs.h
31
target/arm: Reorg CPAccessResult and access_check_cp_reg
32
target/arm: Replace sentinels with ARRAY_SIZE in cpregs.h
33
target/arm: Make some more cpreg data static const
34
target/arm: Reorg ARMCPRegInfo type field bits
35
target/arm: Avoid bare abort() or assert(0)
36
target/arm: Change cpreg access permissions to enum
37
target/arm: Name CPState type
38
target/arm: Name CPSecureState type
39
target/arm: Drop always-true test in define_arm_vh_e2h_redirects_aliases
40
target/arm: Store cpregs key in the hash table directly
41
target/arm: Merge allocation of the cpreg and its name
42
target/arm: Hoist computation of key in add_cpreg_to_hashtable
43
target/arm: Consolidate cpreg updates in add_cpreg_to_hashtable
44
target/arm: Use bool for is64 and ns in add_cpreg_to_hashtable
45
target/arm: Hoist isbanked computation in add_cpreg_to_hashtable
46
target/arm: Perform override check early in add_cpreg_to_hashtable
47
target/arm: Reformat comments in add_cpreg_to_hashtable
48
target/arm: Remove HOST_BIG_ENDIAN ifdef in add_cpreg_to_hashtable
49
target/arm: Add isar predicates for FEAT_Debugv8p2
50
target/arm: Add isar_feature_{aa64,any}_ras
38
51
39
Kunkun Jiang (1):
52
target/arm/cpregs.h | 453 ++++++++++++++++++++++++++++++++++++++
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
53
target/arm/cpu.h | 393 +++------------------------------
41
54
hw/arm/pxa2xx.c | 2 +-
42
Marcin Juszkiewicz (1):
55
hw/arm/pxa2xx_pic.c | 2 +-
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
56
hw/intc/arm_gicv3_cpuif.c | 6 +-
44
57
hw/intc/arm_gicv3_kvm.c | 3 +-
45
Peter Maydell (25):
58
target/arm/cpu.c | 25 +--
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
59
target/arm/cpu64.c | 2 +-
47
target/arm: Implement v8.1M PXN extension
60
target/arm/cpu_tcg.c | 5 +-
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
61
target/arm/gdbstub.c | 5 +-
49
target/arm: Implement VSCCLRM insn
62
target/arm/helper.c | 358 +++++++++++++-----------------
50
target/arm: Implement CLRM instruction
63
target/arm/hvf/hvf.c | 2 +-
51
target/arm: Enforce M-profile VMRS/VMSR register restrictions
64
target/arm/kvm-stub.c | 4 +-
52
target/arm: Refactor M-profile VMSR/VMRS handling
65
target/arm/kvm.c | 4 +-
53
target/arm: Move general-use constant expanders up in translate.c
66
target/arm/machine.c | 4 +-
54
target/arm: Implement VLDR/VSTR system register
67
target/arm/op_helper.c | 57 ++---
55
target/arm: Implement M-profile FPSCR_nzcvqc
68
target/arm/translate-a64.c | 14 +-
56
target/arm: Use new FPCR_NZCV_MASK constant
69
target/arm/translate-neon.c | 2 +-
57
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
70
target/arm/translate.c | 13 +-
58
target/arm: Implement FPCXT_S fp system register
71
tests/tcg/aarch64/bti-3.c | 42 ++++
59
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
72
tests/tcg/aarch64/Makefile.target | 6 +-
60
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
73
21 files changed, 738 insertions(+), 664 deletions(-)
61
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
74
create mode 100644 target/arm/cpregs.h
62
target/arm: Implement v8.1M REVIDR register
75
create mode 100644 tests/tcg/aarch64/bti-3.c
63
target/arm: Implement new v8.1M NOCP check for exception return
64
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
65
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
66
target/arm: Implement CCR_S.TRD behaviour for SG insns
67
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
68
target/arm: Implement M-profile "minimal RAS implementation"
69
hw/intc/armv7m_nvic: Implement read/write for RAS register block
70
hw/arm/armv7m: Correct typo in QOM object name
71
72
Vikram Garhwal (4):
73
hw/net/can: Introduce Xilinx ZynqMP CAN controller
74
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
75
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
76
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
77
78
meson.build | 1 +
79
hw/arm/smmuv3-internal.h | 2 +-
80
hw/net/can/trace.h | 1 +
81
include/hw/arm/xlnx-zynqmp.h | 8 +
82
include/hw/intc/armv7m_nvic.h | 2 +
83
include/hw/net/xlnx-zynqmp-can.h | 78 +++
84
target/arm/cpu.h | 46 ++
85
target/arm/m-nocp.decode | 10 +-
86
target/arm/t32.decode | 10 +-
87
target/arm/vfp.decode | 14 +
88
hw/arm/armv7m.c | 4 +-
89
hw/arm/sbsa-ref.c | 23 +-
90
hw/arm/xlnx-zcu102.c | 20 +
91
hw/arm/xlnx-zynqmp.c | 34 ++
92
hw/intc/armv7m_nvic.c | 246 ++++++--
93
hw/misc/imx25_ccm.c | 12 +-
94
hw/misc/imx31_ccm.c | 14 +-
95
hw/misc/imx6_ccm.c | 20 +-
96
hw/misc/imx6_src.c | 2 +-
97
hw/misc/imx6ul_ccm.c | 4 +-
98
hw/misc/imx_ccm.c | 4 +-
99
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++++++
100
target/arm/cpu.c | 5 +-
101
target/arm/helper.c | 7 +-
102
target/arm/m_helper.c | 130 ++++-
103
target/arm/translate.c | 105 +++-
104
tests/qtest/npcm7xx_rng-test.c | 12 +
105
tests/qtest/xlnx-can-test.c | 360 ++++++++++++
106
MAINTAINERS | 8 +
107
hw/Kconfig | 1 +
108
hw/net/can/meson.build | 1 +
109
hw/net/can/trace-events | 9 +
110
target/arm/translate-vfp.c.inc | 511 ++++++++++++++++-
111
tests/qtest/meson.build | 1 +
112
34 files changed, 2713 insertions(+), 153 deletions(-)
113
create mode 100644 hw/net/can/trace.h
114
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
115
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
116
create mode 100644 tests/qtest/xlnx-can-test.c
117
create mode 100644 hw/net/can/trace-events
118
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
3
This controls whether the PACI{A,B}SP instructions trap with BTYPE=3
4
Tests the CAN controller in loopback, sleep and snoop mode.
4
(indirect branch from register other than x16/x17). The linux kernel
5
Tests filtering of incoming CAN messages.
5
sets this in bti_enable().
6
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/998
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
10
Message-id: 20220427042312.294300-1-richard.henderson@linaro.org
11
[PMM: remove stray change to makefile comment]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
14
target/arm/cpu.c | 2 ++
14
tests/qtest/meson.build | 1 +
15
tests/tcg/aarch64/bti-3.c | 42 +++++++++++++++++++++++++++++++
15
2 files changed, 361 insertions(+)
16
tests/tcg/aarch64/Makefile.target | 6 ++---
16
create mode 100644 tests/qtest/xlnx-can-test.c
17
3 files changed, 47 insertions(+), 3 deletions(-)
18
create mode 100644 tests/tcg/aarch64/bti-3.c
17
19
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
25
/* Enable all PAC keys. */
26
env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
27
SCTLR_EnDA | SCTLR_EnDB);
28
+ /* Trap on btype=3 for PACIxSP. */
29
+ env->cp15.sctlr_el[1] |= SCTLR_BT0;
30
/* and to the FP/Neon instructions */
31
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
32
/* and to the SVE instructions */
33
diff --git a/tests/tcg/aarch64/bti-3.c b/tests/tcg/aarch64/bti-3.c
19
new file mode 100644
34
new file mode 100644
20
index XXXXXXX..XXXXXXX
35
index XXXXXXX..XXXXXXX
21
--- /dev/null
36
--- /dev/null
22
+++ b/tests/qtest/xlnx-can-test.c
37
+++ b/tests/tcg/aarch64/bti-3.c
23
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
24
+/*
39
+/*
25
+ * QTests for the Xilinx ZynqMP CAN controller.
40
+ * BTI vs PACIASP
26
+ *
27
+ * Copyright (c) 2020 Xilinx Inc.
28
+ *
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
30
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
48
+ */
41
+ */
49
+
42
+
50
+#include "qemu/osdep.h"
43
+#include "bti-crt.inc.c"
51
+#include "libqos/libqtest.h"
52
+
44
+
53
+/* Base address. */
45
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
54
+#define CAN0_BASE_ADDR 0xFF060000
55
+#define CAN1_BASE_ADDR 0xFF070000
56
+
57
+/* Register addresses. */
58
+#define R_SRR_OFFSET 0x00
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
46
+{
98
+ uint16_t size = 0;
47
+ uc->uc_mcontext.pc += 8;
99
+ uint8_t len = 4;
48
+ uc->uc_mcontext.pstate = 1;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
109
+ }
110
+}
49
+}
111
+
50
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
51
+#define BTYPE_1() \
52
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: hint #25; mov %0,#0" \
53
+ : "=r"(skipped) : : "x16", "x30")
54
+
55
+#define BTYPE_2() \
56
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: hint #25; mov %0,#0" \
57
+ : "=r"(skipped) : : "x16", "x30")
58
+
59
+#define BTYPE_3() \
60
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: hint #25; mov %0,#0" \
61
+ : "=r"(skipped) : : "x15", "x30")
62
+
63
+#define TEST(WHICH, EXPECT) \
64
+ do { WHICH(); fail += skipped ^ EXPECT; } while (0)
65
+
66
+int main()
113
+{
67
+{
114
+ uint32_t int_status;
68
+ int fail = 0;
69
+ int skipped;
115
+
70
+
116
+ /* Read the interrupt on CAN rx. */
71
+ /* Signal-like with SA_SIGINFO. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
72
+ signal_info(SIGILL, skip2_sigill);
118
+
73
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
74
+ /* With SCTLR_EL1.BT0 set, PACIASP is not compatible with type=3. */
75
+ TEST(BTYPE_1, 0);
76
+ TEST(BTYPE_2, 0);
77
+ TEST(BTYPE_3, 1);
120
+
78
+
121
+ /* Read the RX register data for CAN. */
79
+ return fail;
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
80
+}
130
+
81
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
131
+static void send_data(QTestState *qts, uint64_t can_base_addr,
132
+ const uint32_t *buf_tx)
133
+{
134
+ uint32_t int_status;
135
+
136
+ /* Write the TX register data for CAN. */
137
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
138
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
140
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
141
+
142
+ /* Read the interrupt on CAN for tx. */
143
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
144
+
145
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
146
+
147
+ /* Clear the interrupt for tx. */
148
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
149
+}
150
+
151
+/*
152
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
153
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
154
+ * the data sent from CAN0 with received on CAN1.
155
+ */
156
+static void test_can_bus(void)
157
+{
158
+ const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
159
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
160
+ uint32_t status = 0;
161
+ uint8_t can_timestamp = 1;
162
+
163
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
164
+ " -object can-bus,id=canbus0"
165
+ " -machine xlnx-zcu102.canbus0=canbus0"
166
+ " -machine xlnx-zcu102.canbus1=canbus0"
167
+ );
168
+
169
+ /* Configure the CAN0 and CAN1. */
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
171
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
173
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
174
+
175
+ /* Check here if CAN0 and CAN1 are in normal mode. */
176
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
177
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
178
+
179
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
180
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
181
+
182
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
183
+
184
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
185
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
186
+
187
+ qtest_quit(qts);
188
+}
189
+
190
+/*
191
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
192
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
193
+ */
194
+static void test_can_loopback(void)
195
+{
196
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
197
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
198
+ uint32_t status = 0;
199
+
200
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
201
+ " -object can-bus,id=canbus0"
202
+ " -machine xlnx-zcu102.canbus0=canbus0"
203
+ " -machine xlnx-zcu102.canbus1=canbus0"
204
+ );
205
+
206
+ /* Configure the CAN0 in loopback mode. */
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
209
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
210
+
211
+ /* Check here if CAN0 is set in loopback mode. */
212
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
213
+
214
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
215
+
216
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
217
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
218
+ match_rx_tx_data(buf_tx, buf_rx, 0);
219
+
220
+ /* Configure the CAN1 in loopback mode. */
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
223
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
224
+
225
+ /* Check here if CAN1 is set in loopback mode. */
226
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
227
+
228
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
229
+
230
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
231
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
232
+ match_rx_tx_data(buf_tx, buf_rx, 0);
233
+
234
+ qtest_quit(qts);
235
+}
236
+
237
+/*
238
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
239
+ * test message will pass through filter 2.
240
+ */
241
+static void test_can_filter(void)
242
+{
243
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
244
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
245
+ uint32_t status = 0;
246
+ uint8_t can_timestamp = 1;
247
+
248
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
249
+ " -object can-bus,id=canbus0"
250
+ " -machine xlnx-zcu102.canbus0=canbus0"
251
+ " -machine xlnx-zcu102.canbus1=canbus0"
252
+ );
253
+
254
+ /* Configure the CAN0 and CAN1. */
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
256
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
258
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
259
+
260
+ /* Check here if CAN0 and CAN1 are in normal mode. */
261
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
262
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
263
+
264
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
265
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
266
+
267
+ /* Set filter for CAN1 for incoming messages. */
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
276
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
277
+
278
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
279
+
280
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
281
+
282
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
283
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
284
+
285
+ qtest_quit(qts);
286
+}
287
+
288
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
289
+static void test_can_sleepmode(void)
290
+{
291
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
292
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
293
+ uint32_t status = 0;
294
+ uint8_t can_timestamp = 1;
295
+
296
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
297
+ " -object can-bus,id=canbus0"
298
+ " -machine xlnx-zcu102.canbus0=canbus0"
299
+ " -machine xlnx-zcu102.canbus1=canbus0"
300
+ );
301
+
302
+ /* Configure the CAN0. */
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
305
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
306
+
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
308
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
309
+
310
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
311
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
312
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
313
+
314
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
315
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
316
+
317
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
318
+
319
+ /*
320
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
321
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
322
+ * incoming data.
323
+ */
324
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
325
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
326
+
327
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
328
+
329
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
330
+
331
+ qtest_quit(qts);
332
+}
333
+
334
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
335
+static void test_can_snoopmode(void)
336
+{
337
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
338
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
339
+ uint32_t status = 0;
340
+ uint8_t can_timestamp = 1;
341
+
342
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
343
+ " -object can-bus,id=canbus0"
344
+ " -machine xlnx-zcu102.canbus0=canbus0"
345
+ " -machine xlnx-zcu102.canbus1=canbus0"
346
+ );
347
+
348
+ /* Configure the CAN0. */
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
351
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
352
+
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
354
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
355
+
356
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
357
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
358
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
359
+
360
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
361
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
362
+
363
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
364
+
365
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
366
+
367
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
368
+
369
+ qtest_quit(qts);
370
+}
371
+
372
+int main(int argc, char **argv)
373
+{
374
+ g_test_init(&argc, &argv, NULL);
375
+
376
+ qtest_add_func("/net/can/can_bus", test_can_bus);
377
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
378
+ qtest_add_func("/net/can/can_filter", test_can_filter);
379
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
380
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
381
+
382
+ return g_test_run();
383
+}
384
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
385
index XXXXXXX..XXXXXXX 100644
82
index XXXXXXX..XXXXXXX 100644
386
--- a/tests/qtest/meson.build
83
--- a/tests/tcg/aarch64/Makefile.target
387
+++ b/tests/qtest/meson.build
84
+++ b/tests/tcg/aarch64/Makefile.target
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
85
@@ -XXX,XX +XXX,XX @@ endif
389
['arm-cpu-features',
86
# BTI Tests
390
'numa-test',
87
# bti-1 tests the elf notes, so we require special compiler support.
391
'boot-serial-test',
88
ifneq ($(CROSS_CC_HAS_ARMV8_BTI),)
392
+ 'xlnx-can-test',
89
-AARCH64_TESTS += bti-1
393
'migration-test']
90
-bti-1: CFLAGS += -mbranch-protection=standard
394
91
-bti-1: LDFLAGS += -nostdlib
395
qtests_s390x = \
92
+AARCH64_TESTS += bti-1 bti-3
93
+bti-1 bti-3: CFLAGS += -mbranch-protection=standard
94
+bti-1 bti-3: LDFLAGS += -nostdlib
95
endif
96
# bti-2 tests PROT_BTI, so no special compiler support required.
97
AARCH64_TESTS += bti-2
396
--
98
--
397
2.20.1
99
2.25.1
398
399
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
3
Move ARMCPRegInfo and all related declarations to a new
4
implementation. Bus connection and socketCAN connection for each CAN module
4
internal header, out of the public cpu.h.
5
can be set through command lines.
6
5
7
Example for using single CAN:
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
-object can-bus,id=canbus0 \
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
11
12
Example for connecting both CAN to same virtual CAN on host machine:
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Message-id: 1605728926-352690-2-git-send-email-fnu.vikram@xilinx.com
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-2-richard.henderson@linaro.org
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
11
---
27
meson.build | 1 +
12
target/arm/cpregs.h | 413 +++++++++++++++++++++++++++++++++++++
28
hw/net/can/trace.h | 1 +
13
target/arm/cpu.h | 368 ---------------------------------
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
14
hw/arm/pxa2xx.c | 1 +
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
15
hw/arm/pxa2xx_pic.c | 1 +
31
hw/Kconfig | 1 +
16
hw/intc/arm_gicv3_cpuif.c | 1 +
32
hw/net/can/meson.build | 1 +
17
hw/intc/arm_gicv3_kvm.c | 2 +
33
hw/net/can/trace-events | 9 +
18
target/arm/cpu.c | 1 +
34
7 files changed, 1252 insertions(+)
19
target/arm/cpu64.c | 1 +
35
create mode 100644 hw/net/can/trace.h
20
target/arm/cpu_tcg.c | 1 +
36
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
21
target/arm/gdbstub.c | 3 +-
37
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
22
target/arm/helper.c | 1 +
38
create mode 100644 hw/net/can/trace-events
23
target/arm/op_helper.c | 1 +
24
target/arm/translate-a64.c | 4 +-
25
target/arm/translate.c | 3 +-
26
14 files changed, 427 insertions(+), 374 deletions(-)
27
create mode 100644 target/arm/cpregs.h
39
28
40
diff --git a/meson.build b/meson.build
29
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/meson.build
43
+++ b/meson.build
44
@@ -XXX,XX +XXX,XX @@ if have_system
45
'hw/misc',
46
'hw/misc/macio',
47
'hw/net',
48
+ 'hw/net/can',
49
'hw/nvram',
50
'hw/pci',
51
'hw/pci-host',
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
53
new file mode 100644
30
new file mode 100644
54
index XXXXXXX..XXXXXXX
31
index XXXXXXX..XXXXXXX
55
--- /dev/null
32
--- /dev/null
56
+++ b/hw/net/can/trace.h
33
+++ b/target/arm/cpregs.h
57
@@ -0,0 +1 @@
34
@@ -XXX,XX +XXX,XX @@
58
+#include "trace/trace-hw_net_can.h"
35
+/*
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
36
+ * QEMU ARM CP Register access and descriptions
60
new file mode 100644
61
index XXXXXXX..XXXXXXX
62
--- /dev/null
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
64
@@ -XXX,XX +XXX,XX @@
65
+/*
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
67
+ *
37
+ *
68
+ * Copyright (c) 2020 Xilinx Inc.
38
+ * Copyright (c) 2022 Linaro Ltd
69
+ *
39
+ *
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
40
+ * This program is free software; you can redistribute it and/or
41
+ * modify it under the terms of the GNU General Public License
42
+ * as published by the Free Software Foundation; either version 2
43
+ * of the License, or (at your option) any later version.
71
+ *
44
+ *
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
45
+ * This program is distributed in the hope that it will be useful,
73
+ * Pavel Pisa.
46
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
47
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48
+ * GNU General Public License for more details.
74
+ *
49
+ *
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
50
+ * You should have received a copy of the GNU General Public License
76
+ * of this software and associated documentation files (the "Software"), to deal
51
+ * along with this program; if not, see
77
+ * in the Software without restriction, including without limitation the rights
52
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53
+ */
79
+ * copies of the Software, and to permit persons to whom the Software is
54
+
80
+ * furnished to do so, subject to the following conditions:
55
+#ifndef TARGET_ARM_CPREGS_H
56
+#define TARGET_ARM_CPREGS_H
57
+
58
+/*
59
+ * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
60
+ * special-behaviour cp reg and bits [11..8] indicate what behaviour
61
+ * it has. Otherwise it is a simple cp reg, where CONST indicates that
62
+ * TCG can assume the value to be constant (ie load at translate time)
63
+ * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
64
+ * indicates that the TB should not be ended after a write to this register
65
+ * (the default is that the TB ends after cp writes). OVERRIDE permits
66
+ * a register definition to override a previous definition for the
67
+ * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
68
+ * old must have the OVERRIDE bit set.
69
+ * ALIAS indicates that this register is an alias view of some underlying
70
+ * state which is also visible via another register, and that the other
71
+ * register is handling migration and reset; registers marked ALIAS will not be
72
+ * migrated but may have their state set by syncing of register state from KVM.
73
+ * NO_RAW indicates that this register has no underlying state and does not
74
+ * support raw access for state saving/loading; it will not be used for either
75
+ * migration or KVM state synchronization. (Typically this is for "registers"
76
+ * which are actually used as instructions for cache maintenance and so on.)
77
+ * IO indicates that this register does I/O and therefore its accesses
78
+ * need to be marked with gen_io_start() and also end the TB. In particular,
79
+ * registers which implement clocks or timers require this.
80
+ * RAISES_EXC is for when the read or write hook might raise an exception;
81
+ * the generated code will synchronize the CPU state before calling the hook
82
+ * so that it is safe for the hook to call raise_exception().
83
+ * NEWEL is for writes to registers that might change the exception
84
+ * level - typically on older ARM chips. For those cases we need to
85
+ * re-read the new el when recomputing the translation flags.
86
+ */
87
+#define ARM_CP_SPECIAL 0x0001
88
+#define ARM_CP_CONST 0x0002
89
+#define ARM_CP_64BIT 0x0004
90
+#define ARM_CP_SUPPRESS_TB_END 0x0008
91
+#define ARM_CP_OVERRIDE 0x0010
92
+#define ARM_CP_ALIAS 0x0020
93
+#define ARM_CP_IO 0x0040
94
+#define ARM_CP_NO_RAW 0x0080
95
+#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
96
+#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
97
+#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
98
+#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
99
+#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
100
+#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
101
+#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
102
+#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
103
+#define ARM_CP_FPU 0x1000
104
+#define ARM_CP_SVE 0x2000
105
+#define ARM_CP_NO_GDB 0x4000
106
+#define ARM_CP_RAISES_EXC 0x8000
107
+#define ARM_CP_NEWEL 0x10000
108
+/* Used only as a terminator for ARMCPRegInfo lists */
109
+#define ARM_CP_SENTINEL 0xfffff
110
+/* Mask of only the flag bits in a type field */
111
+#define ARM_CP_FLAG_MASK 0x1f0ff
112
+
113
+/*
114
+ * Valid values for ARMCPRegInfo state field, indicating which of
115
+ * the AArch32 and AArch64 execution states this register is visible in.
116
+ * If the reginfo doesn't explicitly specify then it is AArch32 only.
117
+ * If the reginfo is declared to be visible in both states then a second
118
+ * reginfo is synthesised for the AArch32 view of the AArch64 register,
119
+ * such that the AArch32 view is the lower 32 bits of the AArch64 one.
120
+ * Note that we rely on the values of these enums as we iterate through
121
+ * the various states in some places.
122
+ */
123
+enum {
124
+ ARM_CP_STATE_AA32 = 0,
125
+ ARM_CP_STATE_AA64 = 1,
126
+ ARM_CP_STATE_BOTH = 2,
127
+};
128
+
129
+/*
130
+ * ARM CP register secure state flags. These flags identify security state
131
+ * attributes for a given CP register entry.
132
+ * The existence of both or neither secure and non-secure flags indicates that
133
+ * the register has both a secure and non-secure hash entry. A single one of
134
+ * these flags causes the register to only be hashed for the specified
135
+ * security state.
136
+ * Although definitions may have any combination of the S/NS bits, each
137
+ * registered entry will only have one to identify whether the entry is secure
138
+ * or non-secure.
139
+ */
140
+enum {
141
+ ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
142
+ ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
143
+};
144
+
145
+/*
146
+ * Return true if cptype is a valid type field. This is used to try to
147
+ * catch errors where the sentinel has been accidentally left off the end
148
+ * of a list of registers.
149
+ */
150
+static inline bool cptype_valid(int cptype)
151
+{
152
+ return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
153
+ || ((cptype & ARM_CP_SPECIAL) &&
154
+ ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
155
+}
156
+
157
+/*
158
+ * Access rights:
159
+ * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
160
+ * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
161
+ * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
162
+ * (ie any of the privileged modes in Secure state, or Monitor mode).
163
+ * If a register is accessible in one privilege level it's always accessible
164
+ * in higher privilege levels too. Since "Secure PL1" also follows this rule
165
+ * (ie anything visible in PL2 is visible in S-PL1, some things are only
166
+ * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
167
+ * terminology a little and call this PL3.
168
+ * In AArch64 things are somewhat simpler as the PLx bits line up exactly
169
+ * with the ELx exception levels.
81
+ *
170
+ *
82
+ * The above copyright notice and this permission notice shall be included in
171
+ * If access permissions for a register are more complex than can be
83
+ * all copies or substantial portions of the Software.
172
+ * described with these bits, then use a laxer set of restrictions, and
84
+ *
173
+ * do the more restrictive/complex check inside a helper function.
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
174
+ */
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
175
+#define PL3_R 0x80
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
176
+#define PL3_W 0x40
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
177
+#define PL2_R (0x20 | PL3_R)
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
178
+#define PL2_W (0x10 | PL3_W)
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
179
+#define PL1_R (0x08 | PL2_R)
91
+ * THE SOFTWARE.
180
+#define PL1_W (0x04 | PL2_W)
92
+ */
181
+#define PL0_R (0x02 | PL1_R)
93
+
182
+#define PL0_W (0x01 | PL1_W)
94
+#ifndef XLNX_ZYNQMP_CAN_H
183
+
95
+#define XLNX_ZYNQMP_CAN_H
184
+/*
96
+
185
+ * For user-mode some registers are accessible to EL0 via a kernel
97
+#include "hw/register.h"
186
+ * trap-and-emulate ABI. In this case we define the read permissions
98
+#include "net/can_emu.h"
187
+ * as actually being PL0_R. However some bits of any given register
99
+#include "net/can_host.h"
188
+ * may still be masked.
100
+#include "qemu/fifo32.h"
189
+ */
101
+#include "hw/ptimer.h"
190
+#ifdef CONFIG_USER_ONLY
102
+#include "hw/qdev-clock.h"
191
+#define PL0U_R PL0_R
103
+
192
+#else
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
193
+#define PL0U_R PL1_R
105
+
106
+#define XLNX_ZYNQMP_CAN(obj) \
107
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
108
+
109
+#define MAX_CAN_CTRLS 2
110
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
111
+#define MAILBOX_CAPACITY 64
112
+#define CAN_TIMER_MAX 0XFFFFUL
113
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
114
+
115
+/* Each CAN_FRAME will have 4 * 32bit size. */
116
+#define CAN_FRAME_SIZE 4
117
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
118
+
119
+typedef struct XlnxZynqMPCANState {
120
+ SysBusDevice parent_obj;
121
+ MemoryRegion iomem;
122
+
123
+ qemu_irq irq;
124
+
125
+ CanBusClientState bus_client;
126
+ CanBusState *canbus;
127
+
128
+ struct {
129
+ uint32_t ext_clk_freq;
130
+ } cfg;
131
+
132
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
133
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
134
+
135
+ Fifo32 rx_fifo;
136
+ Fifo32 tx_fifo;
137
+ Fifo32 txhpb_fifo;
138
+
139
+ ptimer_state *can_timer;
140
+} XlnxZynqMPCANState;
141
+
142
+#endif
194
+#endif
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
195
+
144
new file mode 100644
196
+#define PL3_RW (PL3_R | PL3_W)
145
index XXXXXXX..XXXXXXX
197
+#define PL2_RW (PL2_R | PL2_W)
146
--- /dev/null
198
+#define PL1_RW (PL1_R | PL1_W)
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
199
+#define PL0_RW (PL0_R | PL0_W)
148
@@ -XXX,XX +XXX,XX @@
200
+
149
+/*
201
+typedef enum CPAccessResult {
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
202
+ /* Access is permitted */
151
+ * This implementation is based on the following datasheet:
203
+ CP_ACCESS_OK = 0,
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
204
+ /*
153
+ *
205
+ * Access fails due to a configurable trap or enable which would
154
+ * Copyright (c) 2020 Xilinx Inc.
206
+ * result in a categorized exception syndrome giving information about
155
+ *
207
+ * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
208
+ * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
157
+ *
209
+ * PL1 if in EL0, otherwise to the current EL).
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
210
+ */
159
+ * Pavel Pisa
211
+ CP_ACCESS_TRAP = 1,
160
+ *
212
+ /*
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
213
+ * Access fails and results in an exception syndrome 0x0 ("uncategorized").
162
+ * of this software and associated documentation files (the "Software"), to deal
214
+ * Note that this is not a catch-all case -- the set of cases which may
163
+ * in the Software without restriction, including without limitation the rights
215
+ * result in this failure is specifically defined by the architecture.
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
216
+ */
165
+ * copies of the Software, and to permit persons to whom the Software is
217
+ CP_ACCESS_TRAP_UNCATEGORIZED = 2,
166
+ * furnished to do so, subject to the following conditions:
218
+ /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
167
+ *
219
+ CP_ACCESS_TRAP_EL2 = 3,
168
+ * The above copyright notice and this permission notice shall be included in
220
+ CP_ACCESS_TRAP_EL3 = 4,
169
+ * all copies or substantial portions of the Software.
221
+ /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
170
+ *
222
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
223
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
224
+} CPAccessResult;
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
225
+
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
226
+typedef struct ARMCPRegInfo ARMCPRegInfo;
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
227
+
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228
+/*
177
+ * THE SOFTWARE.
229
+ * Access functions for coprocessor registers. These cannot fail and
178
+ */
230
+ * may not raise exceptions.
179
+
231
+ */
180
+#include "qemu/osdep.h"
232
+typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
181
+#include "hw/sysbus.h"
233
+typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
182
+#include "hw/register.h"
234
+ uint64_t value);
183
+#include "hw/irq.h"
235
+/* Access permission check functions for coprocessor registers. */
184
+#include "qapi/error.h"
236
+typedef CPAccessResult CPAccessFn(CPUARMState *env,
185
+#include "qemu/bitops.h"
237
+ const ARMCPRegInfo *opaque,
186
+#include "qemu/log.h"
238
+ bool isread);
187
+#include "qemu/cutils.h"
239
+/* Hook function for register reset */
188
+#include "sysemu/sysemu.h"
240
+typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
189
+#include "migration/vmstate.h"
241
+
190
+#include "hw/qdev-properties.h"
242
+#define CP_ANY 0xff
191
+#include "net/can_emu.h"
243
+
192
+#include "net/can_host.h"
244
+/* Definition of an ARM coprocessor register */
193
+#include "qemu/event_notifier.h"
245
+struct ARMCPRegInfo {
194
+#include "qom/object_interfaces.h"
246
+ /* Name of register (useful mainly for debugging, need not be unique) */
195
+#include "hw/net/xlnx-zynqmp-can.h"
247
+ const char *name;
196
+#include "trace.h"
248
+ /*
197
+
249
+ * Location of register: coprocessor number and (crn,crm,opc1,opc2)
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
250
+ * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
251
+ * 'wildcard' field -- any value of that field in the MRC/MCR insn
200
+#endif
252
+ * will be decoded to this register. The register read and write
201
+
253
+ * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
202
+#define MAX_DLC 8
254
+ * used by the program, so it is possible to register a wildcard and
203
+#undef ERROR
255
+ * then behave differently on read/write if necessary.
204
+
256
+ * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
257
+ * must both be zero.
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
258
+ * For AArch64-visible registers, opc0 is also used.
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
259
+ * Since there are no "coprocessors" in AArch64, cp is purely used as a
208
+REG32(MODE_SELECT_REGISTER, 0x4)
260
+ * way to distinguish (for KVM's benefit) guest-visible system registers
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
261
+ * from demuxed ones provided to preserve the "no side effects on
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
262
+ * KVM register read/write from QEMU" semantics. cp==0x13 is guest
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
263
+ * visible (to match KVM's encoding); cp==0 will be converted to
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
264
+ * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
265
+ */
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
266
+ uint8_t cp;
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
267
+ uint8_t crn;
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
268
+ uint8_t crm;
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
269
+ uint8_t opc0;
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
270
+ uint8_t opc1;
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
271
+ uint8_t opc2;
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
272
+ /* Execution state in which this register is visible: ARM_CP_STATE_* */
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
273
+ int state;
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
274
+ /* Register type: ARM_CP_* bits/values */
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
275
+ int type;
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
276
+ /* Access rights: PL*_[RW] */
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
277
+ int access;
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
278
+ /* Security state: ARM_CP_SECSTATE_* bits/values */
227
+REG32(STATUS_REGISTER, 0x18)
279
+ int secure;
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
280
+ /*
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
281
+ * The opaque pointer passed to define_arm_cp_regs_with_opaque() when
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
282
+ * this register was defined: can be used to hand data through to the
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
283
+ * register read/write functions, since they are passed the ARMCPRegInfo*.
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
284
+ */
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
285
+ void *opaque;
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
286
+ /*
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
287
+ * Value of this register, if it is ARM_CP_CONST. Otherwise, if
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
288
+ * fieldoffset is non-zero, the reset value of the register.
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
289
+ */
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
290
+ uint64_t resetvalue;
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
291
+ /*
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
292
+ * Offset of the field in CPUARMState for this register.
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
293
+ * This is not needed if either:
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
294
+ * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
295
+ * 2. both readfn and writefn are specified
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
296
+ */
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
297
+ ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
298
+
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
299
+ /*
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
300
+ * Offsets of the secure and non-secure fields in CPUARMState for the
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
301
+ * register if it is banked. These fields are only used during the static
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
302
+ * registration of a register. During hashing the bank associated
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
303
+ * with a given security state is copied to fieldoffset which is used from
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
304
+ * there on out.
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
305
+ *
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
306
+ * It is expected that register definitions use either fieldoffset or
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
307
+ * bank_fieldoffsets in the definition but not both. It is also expected
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
308
+ * that both bank offsets are set when defining a banked register. This
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
309
+ * use indicates that a register is banked.
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
310
+ */
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
311
+ ptrdiff_t bank_fieldoffsets[2];
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
312
+
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
313
+ /*
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
314
+ * Function for making any access checks for this register in addition to
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
315
+ * those specified by the 'access' permissions bits. If NULL, no extra
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
316
+ * checks required. The access check is performed at runtime, not at
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
317
+ * translate time.
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
318
+ */
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
319
+ CPAccessFn *accessfn;
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
320
+ /*
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
321
+ * Function for handling reads of this register. If NULL, then reads
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
322
+ * will be done by loading from the offset into CPUARMState specified
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
323
+ * by fieldoffset.
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
324
+ */
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
325
+ CPReadFn *readfn;
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
326
+ /*
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
327
+ * Function for handling writes of this register. If NULL, then writes
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
328
+ * will be done by writing to the offset into CPUARMState specified
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
329
+ * by fieldoffset.
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
330
+ */
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
331
+ CPWriteFn *writefn;
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
332
+ /*
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
333
+ * Function for doing a "raw" read; used when we need to copy
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
334
+ * coprocessor state to the kernel for KVM or out for
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
335
+ * migration. This only needs to be provided if there is also a
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
336
+ * readfn and it has side effects (for instance clear-on-read bits).
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
337
+ */
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
338
+ CPReadFn *raw_readfn;
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
339
+ /*
288
+REG32(TIMESTAMP_REGISTER, 0x28)
340
+ * Function for doing a "raw" write; used when we need to copy KVM
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
341
+ * kernel coprocessor state into userspace, or for inbound
290
+REG32(WIR, 0x2c)
342
+ * migration. This only needs to be provided if there is also a
291
+ FIELD(WIR, EW, 8, 8)
343
+ * writefn and it masks out "unwritable" bits or has write-one-to-clear
292
+ FIELD(WIR, FW, 0, 8)
344
+ * or similar behaviour.
293
+REG32(TXFIFO_ID, 0x30)
345
+ */
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
346
+ CPWriteFn *raw_writefn;
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
347
+ /*
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
348
+ * Function for resetting the register. If NULL, then reset will be done
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
349
+ * by writing resetvalue to the field specified in fieldoffset. If
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
350
+ * fieldoffset is 0 then no reset will be done.
299
+REG32(TXFIFO_DLC, 0x34)
351
+ */
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
352
+ CPResetFn *resetfn;
301
+REG32(TXFIFO_DATA1, 0x38)
353
+
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
354
+ /*
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
355
+ * "Original" writefn and readfn.
304
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
356
+ * For ARMv8.1-VHE register aliases, we overwrite the read/write
305
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
357
+ * accessor functions of various EL1/EL0 to perform the runtime
306
+REG32(TXFIFO_DATA2, 0x3c)
358
+ * check for which sysreg should actually be modified, and then
307
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
359
+ * forwards the operation. Before overwriting the accessors,
308
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
360
+ * the original function is copied here, so that accesses that
309
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
361
+ * really do go to the EL1/EL0 version proceed normally.
310
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
362
+ * (The corresponding EL2 register is linked via opaque.)
311
+REG32(TXHPB_ID, 0x40)
363
+ */
312
+ FIELD(TXHPB_ID, IDH, 21, 11)
364
+ CPReadFn *orig_readfn;
313
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
365
+ CPWriteFn *orig_writefn;
314
+ FIELD(TXHPB_ID, IDE, 19, 1)
366
+};
315
+ FIELD(TXHPB_ID, IDL, 1, 18)
367
+
316
+ FIELD(TXHPB_ID, RTR, 0, 1)
368
+/*
317
+REG32(TXHPB_DLC, 0x44)
369
+ * Macros which are lvalues for the field in CPUARMState for the
318
+ FIELD(TXHPB_DLC, DLC, 28, 4)
370
+ * ARMCPRegInfo *ri.
319
+REG32(TXHPB_DATA1, 0x48)
371
+ */
320
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
372
+#define CPREG_FIELD32(env, ri) \
321
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
373
+ (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
322
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
374
+#define CPREG_FIELD64(env, ri) \
323
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
375
+ (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
324
+REG32(TXHPB_DATA2, 0x4c)
376
+
325
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
377
+#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
326
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
378
+
327
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
379
+void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
328
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
380
+ const ARMCPRegInfo *regs, void *opaque);
329
+REG32(RXFIFO_ID, 0x50)
381
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
330
+ FIELD(RXFIFO_ID, IDH, 21, 11)
382
+ const ARMCPRegInfo *regs, void *opaque);
331
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
383
+static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
332
+ FIELD(RXFIFO_ID, IDE, 19, 1)
333
+ FIELD(RXFIFO_ID, IDL, 1, 18)
334
+ FIELD(RXFIFO_ID, RTR, 0, 1)
335
+REG32(RXFIFO_DLC, 0x54)
336
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
337
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
338
+REG32(RXFIFO_DATA1, 0x58)
339
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
340
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
341
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
342
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
343
+REG32(RXFIFO_DATA2, 0x5c)
344
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
345
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
346
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
347
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
348
+REG32(AFR, 0x60)
349
+ FIELD(AFR, UAF4, 3, 1)
350
+ FIELD(AFR, UAF3, 2, 1)
351
+ FIELD(AFR, UAF2, 1, 1)
352
+ FIELD(AFR, UAF1, 0, 1)
353
+REG32(AFMR1, 0x64)
354
+ FIELD(AFMR1, AMIDH, 21, 11)
355
+ FIELD(AFMR1, AMSRR, 20, 1)
356
+ FIELD(AFMR1, AMIDE, 19, 1)
357
+ FIELD(AFMR1, AMIDL, 1, 18)
358
+ FIELD(AFMR1, AMRTR, 0, 1)
359
+REG32(AFIR1, 0x68)
360
+ FIELD(AFIR1, AIIDH, 21, 11)
361
+ FIELD(AFIR1, AISRR, 20, 1)
362
+ FIELD(AFIR1, AIIDE, 19, 1)
363
+ FIELD(AFIR1, AIIDL, 1, 18)
364
+ FIELD(AFIR1, AIRTR, 0, 1)
365
+REG32(AFMR2, 0x6c)
366
+ FIELD(AFMR2, AMIDH, 21, 11)
367
+ FIELD(AFMR2, AMSRR, 20, 1)
368
+ FIELD(AFMR2, AMIDE, 19, 1)
369
+ FIELD(AFMR2, AMIDL, 1, 18)
370
+ FIELD(AFMR2, AMRTR, 0, 1)
371
+REG32(AFIR2, 0x70)
372
+ FIELD(AFIR2, AIIDH, 21, 11)
373
+ FIELD(AFIR2, AISRR, 20, 1)
374
+ FIELD(AFIR2, AIIDE, 19, 1)
375
+ FIELD(AFIR2, AIIDL, 1, 18)
376
+ FIELD(AFIR2, AIRTR, 0, 1)
377
+REG32(AFMR3, 0x74)
378
+ FIELD(AFMR3, AMIDH, 21, 11)
379
+ FIELD(AFMR3, AMSRR, 20, 1)
380
+ FIELD(AFMR3, AMIDE, 19, 1)
381
+ FIELD(AFMR3, AMIDL, 1, 18)
382
+ FIELD(AFMR3, AMRTR, 0, 1)
383
+REG32(AFIR3, 0x78)
384
+ FIELD(AFIR3, AIIDH, 21, 11)
385
+ FIELD(AFIR3, AISRR, 20, 1)
386
+ FIELD(AFIR3, AIIDE, 19, 1)
387
+ FIELD(AFIR3, AIIDL, 1, 18)
388
+ FIELD(AFIR3, AIRTR, 0, 1)
389
+REG32(AFMR4, 0x7c)
390
+ FIELD(AFMR4, AMIDH, 21, 11)
391
+ FIELD(AFMR4, AMSRR, 20, 1)
392
+ FIELD(AFMR4, AMIDE, 19, 1)
393
+ FIELD(AFMR4, AMIDL, 1, 18)
394
+ FIELD(AFMR4, AMRTR, 0, 1)
395
+REG32(AFIR4, 0x80)
396
+ FIELD(AFIR4, AIIDH, 21, 11)
397
+ FIELD(AFIR4, AISRR, 20, 1)
398
+ FIELD(AFIR4, AIIDE, 19, 1)
399
+ FIELD(AFIR4, AIIDL, 1, 18)
400
+ FIELD(AFIR4, AIRTR, 0, 1)
401
+
402
+static void can_update_irq(XlnxZynqMPCANState *s)
403
+{
384
+{
404
+ uint32_t irq;
385
+ define_arm_cp_regs_with_opaque(cpu, regs, 0);
405
+
406
+ /* Watermark register interrupts. */
407
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
408
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
409
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
410
+ }
411
+
412
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
413
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
414
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
415
+ }
416
+
417
+ /* RX Interrupts. */
418
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
419
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
420
+ }
421
+
422
+ /* TX interrupts. */
423
+ if (fifo32_is_empty(&s->tx_fifo)) {
424
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
425
+ }
426
+
427
+ if (fifo32_is_full(&s->tx_fifo)) {
428
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
429
+ }
430
+
431
+ if (fifo32_is_full(&s->txhpb_fifo)) {
432
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
433
+ }
434
+
435
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
436
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
437
+
438
+ trace_xlnx_can_update_irq(s->regs[R_INTERRUPT_STATUS_REGISTER],
439
+ s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
440
+ qemu_set_irq(s->irq, irq);
441
+}
386
+}
442
+
387
+static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
443
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val)
444
+{
388
+{
445
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
389
+ define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
446
+
447
+ can_update_irq(s);
448
+}
390
+}
449
+
391
+const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
450
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val)
392
+
393
+/*
394
+ * Definition of an ARM co-processor register as viewed from
395
+ * userspace. This is used for presenting sanitised versions of
396
+ * registers to userspace when emulating the Linux AArch64 CPU
397
+ * ID/feature ABI (advertised as HWCAP_CPUID).
398
+ */
399
+typedef struct ARMCPRegUserSpaceInfo {
400
+ /* Name of register */
401
+ const char *name;
402
+
403
+ /* Is the name actually a glob pattern */
404
+ bool is_glob;
405
+
406
+ /* Only some bits are exported to user space */
407
+ uint64_t exported_bits;
408
+
409
+ /* Fixed bits are applied after the mask */
410
+ uint64_t fixed_bits;
411
+} ARMCPRegUserSpaceInfo;
412
+
413
+#define REGUSERINFO_SENTINEL { .name = NULL }
414
+
415
+void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
416
+
417
+/* CPWriteFn that can be used to implement writes-ignored behaviour */
418
+void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
419
+ uint64_t value);
420
+/* CPReadFn that can be used for read-as-zero behaviour */
421
+uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
422
+
423
+/*
424
+ * CPResetFn that does nothing, for use if no reset is required even
425
+ * if fieldoffset is non zero.
426
+ */
427
+void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
428
+
429
+/*
430
+ * Return true if this reginfo struct's field in the cpu state struct
431
+ * is 64 bits wide.
432
+ */
433
+static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
451
+{
434
+{
452
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
435
+ return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
453
+
454
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
455
+ can_update_irq(s);
456
+
457
+ return 0;
458
+}
436
+}
459
+
437
+
460
+static void can_config_reset(XlnxZynqMPCANState *s)
438
+static inline bool cp_access_ok(int current_el,
439
+ const ARMCPRegInfo *ri, int isread)
461
+{
440
+{
462
+ /* Reset all the configuration registers. */
441
+ return (ri->access >> ((current_el * 2) + isread)) & 1;
463
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
464
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
465
+ register_reset(
466
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
467
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
468
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
469
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
470
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
471
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
472
+ register_reset(&s->reg_info[R_WIR]);
473
+}
442
+}
474
+
443
+
475
+static void can_config_mode(XlnxZynqMPCANState *s)
444
+/* Raw read of a coprocessor register (as needed for migration, etc) */
476
+{
445
+uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
477
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
446
+
478
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
447
+#endif /* TARGET_ARM_CPREGS_H */
479
+
448
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
480
+ /* Put XlnxZynqMPCAN in configuration mode. */
449
index XXXXXXX..XXXXXXX 100644
481
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
450
--- a/target/arm/cpu.h
482
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
451
+++ b/target/arm/cpu.h
483
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
452
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
484
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
453
return kvmid;
485
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
454
}
486
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
455
487
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
456
-/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
488
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
457
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
489
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
458
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
490
+
459
- * TCG can assume the value to be constant (ie load at translate time)
491
+ can_update_irq(s);
460
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
492
+}
461
- * indicates that the TB should not be ended after a write to this register
493
+
462
- * (the default is that the TB ends after cp writes). OVERRIDE permits
494
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
463
- * a register definition to override a previous definition for the
495
+{
464
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
496
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
465
- * old must have the OVERRIDE bit set.
497
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
466
- * ALIAS indicates that this register is an alias view of some underlying
498
+ /* Wake up interrupt bit. */
467
- * state which is also visible via another register, and that the other
499
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
468
- * register is handling migration and reset; registers marked ALIAS will not be
500
+ /* Sleep interrupt bit. */
469
- * migrated but may have their state set by syncing of register state from KVM.
501
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
470
- * NO_RAW indicates that this register has no underlying state and does not
502
+
471
- * support raw access for state saving/loading; it will not be used for either
503
+ /* Clear previous core mode status bits. */
472
- * migration or KVM state synchronization. (Typically this is for "registers"
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
473
- * which are actually used as instructions for cache maintenance and so on.)
505
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
474
- * IO indicates that this register does I/O and therefore its accesses
506
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
475
- * need to be marked with gen_io_start() and also end the TB. In particular,
507
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
476
- * registers which implement clocks or timers require this.
508
+
477
- * RAISES_EXC is for when the read or write hook might raise an exception;
509
+ /* set current mode bit and generate irqs accordingly. */
478
- * the generated code will synchronize the CPU state before calling the hook
510
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
479
- * so that it is safe for the hook to call raise_exception().
511
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
480
- * NEWEL is for writes to registers that might change the exception
512
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
481
- * level - typically on older ARM chips. For those cases we need to
513
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
482
- * re-read the new el when recomputing the translation flags.
514
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
483
- */
515
+ sleep_irq_val);
484
-#define ARM_CP_SPECIAL 0x0001
516
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
485
-#define ARM_CP_CONST 0x0002
517
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
486
-#define ARM_CP_64BIT 0x0004
518
+ } else {
487
-#define ARM_CP_SUPPRESS_TB_END 0x0008
519
+ /*
488
-#define ARM_CP_OVERRIDE 0x0010
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
489
-#define ARM_CP_ALIAS 0x0020
521
+ */
490
-#define ARM_CP_IO 0x0040
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
491
-#define ARM_CP_NO_RAW 0x0080
523
+ /* Set wakeup interrupt bit. */
492
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
524
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
493
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
525
+ wakeup_irq_val);
494
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
526
+ }
495
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
527
+
496
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
528
+ can_update_irq(s);
497
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
529
+}
498
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
530
+
499
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
531
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
500
-#define ARM_CP_FPU 0x1000
532
+{
501
-#define ARM_CP_SVE 0x2000
533
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
502
-#define ARM_CP_NO_GDB 0x4000
534
+ update_status_register_mode_bits(s);
503
-#define ARM_CP_RAISES_EXC 0x8000
535
+}
504
-#define ARM_CP_NEWEL 0x10000
536
+
505
-/* Used only as a terminator for ARMCPRegInfo lists */
537
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
506
-#define ARM_CP_SENTINEL 0xfffff
538
+{
507
-/* Mask of only the flag bits in a type field */
539
+ frame->can_id = data[0];
508
-#define ARM_CP_FLAG_MASK 0x1f0ff
540
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
509
-
541
+
510
-/* Valid values for ARMCPRegInfo state field, indicating which of
542
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
511
- * the AArch32 and AArch64 execution states this register is visible in.
543
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
512
- * If the reginfo doesn't explicitly specify then it is AArch32 only.
544
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
513
- * If the reginfo is declared to be visible in both states then a second
545
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
514
- * reginfo is synthesised for the AArch32 view of the AArch64 register,
546
+
515
- * such that the AArch32 view is the lower 32 bits of the AArch64 one.
547
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
516
- * Note that we rely on the values of these enums as we iterate through
548
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
517
- * the various states in some places.
549
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
518
- */
550
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
519
-enum {
551
+}
520
- ARM_CP_STATE_AA32 = 0,
552
+
521
- ARM_CP_STATE_AA64 = 1,
553
+static bool tx_ready_check(XlnxZynqMPCANState *s)
522
- ARM_CP_STATE_BOTH = 2,
554
+{
523
-};
555
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
524
-
556
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
525
-/* ARM CP register secure state flags. These flags identify security state
557
+
526
- * attributes for a given CP register entry.
558
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
527
- * The existence of both or neither secure and non-secure flags indicates that
559
+ " data while controller is in reset mode.\n",
528
- * the register has both a secure and non-secure hash entry. A single one of
560
+ path);
529
- * these flags causes the register to only be hashed for the specified
561
+ return false;
530
- * security state.
562
+ }
531
- * Although definitions may have any combination of the S/NS bits, each
563
+
532
- * registered entry will only have one to identify whether the entry is secure
564
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
533
- * or non-secure.
565
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
534
- */
566
+
535
-enum {
567
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
536
- ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
568
+ " data while controller is in configuration mode. Reset"
537
- ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
569
+ " the core so operations can start fresh.\n",
538
-};
570
+ path);
539
-
571
+ return false;
540
-/* Return true if cptype is a valid type field. This is used to try to
572
+ }
541
- * catch errors where the sentinel has been accidentally left off the end
573
+
542
- * of a list of registers.
574
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
543
- */
575
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
544
-static inline bool cptype_valid(int cptype)
576
+
545
-{
577
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
546
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
578
+ " data while controller is in SNOOP MODE.\n",
547
- || ((cptype & ARM_CP_SPECIAL) &&
579
+ path);
548
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
580
+ return false;
549
-}
581
+ }
550
-
582
+
551
-/* Access rights:
583
+ return true;
552
- * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
584
+}
553
- * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
585
+
554
- * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
586
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
555
- * (ie any of the privileged modes in Secure state, or Monitor mode).
587
+{
556
- * If a register is accessible in one privilege level it's always accessible
588
+ qemu_can_frame frame;
557
- * in higher privilege levels too. Since "Secure PL1" also follows this rule
589
+ uint32_t data[CAN_FRAME_SIZE];
558
- * (ie anything visible in PL2 is visible in S-PL1, some things are only
590
+ int i;
559
- * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
591
+ bool can_tx = tx_ready_check(s);
560
- * terminology a little and call this PL3.
592
+
561
- * In AArch64 things are somewhat simpler as the PLx bits line up exactly
593
+ if (!can_tx) {
562
- * with the ELx exception levels.
594
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
563
- *
595
+
564
- * If access permissions for a register are more complex than can be
596
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for data"
565
- * described with these bits, then use a laxer set of restrictions, and
597
+ " transfer.\n", path);
566
- * do the more restrictive/complex check inside a helper function.
598
+ can_update_irq(s);
567
- */
599
+ return;
568
-#define PL3_R 0x80
600
+ }
569
-#define PL3_W 0x40
601
+
570
-#define PL2_R (0x20 | PL3_R)
602
+ while (!fifo32_is_empty(fifo)) {
571
-#define PL2_W (0x10 | PL3_W)
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
572
-#define PL1_R (0x08 | PL2_R)
604
+ data[i] = fifo32_pop(fifo);
573
-#define PL1_W (0x04 | PL2_W)
605
+ }
574
-#define PL0_R (0x02 | PL1_R)
606
+
575
-#define PL0_W (0x01 | PL1_W)
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
576
-
608
+ /*
577
-/*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
578
- * For user-mode some registers are accessible to EL0 via a kernel
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
579
- * trap-and-emulate ABI. In this case we define the read permissions
611
+ * Any message transmitted is looped back to the RX line and
580
- * as actually being PL0_R. However some bits of any given register
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
581
- * may still be masked.
613
+ * that it transmits.
582
- */
614
+ */
583
-#ifdef CONFIG_USER_ONLY
615
+ if (fifo32_is_full(&s->rx_fifo)) {
584
-#define PL0U_R PL0_R
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
585
-#else
617
+ } else {
586
-#define PL0U_R PL1_R
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
587
-#endif
619
+ fifo32_push(&s->rx_fifo, data[i]);
588
-
620
+ }
589
-#define PL3_RW (PL3_R | PL3_W)
621
+
590
-#define PL2_RW (PL2_R | PL2_W)
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
591
-#define PL1_RW (PL1_R | PL1_W)
623
+ }
592
-#define PL0_RW (PL0_R | PL0_W)
624
+ } else {
593
-
625
+ /* Normal mode Tx. */
594
/* Return the highest implemented Exception Level */
626
+ generate_frame(&frame, data);
595
static inline int arm_highest_el(CPUARMState *env)
627
+
596
{
628
+ trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc,
597
@@ -XXX,XX +XXX,XX @@ static inline int arm_current_el(CPUARMState *env)
629
+ frame.data[0], frame.data[1],
598
}
630
+ frame.data[2], frame.data[3],
599
}
631
+ frame.data[4], frame.data[5],
600
632
+ frame.data[6], frame.data[7]);
601
-typedef struct ARMCPRegInfo ARMCPRegInfo;
633
+ can_bus_client_send(&s->bus_client, &frame, 1);
602
-
634
+ }
603
-typedef enum CPAccessResult {
635
+ }
604
- /* Access is permitted */
636
+
605
- CP_ACCESS_OK = 0,
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
606
- /* Access fails due to a configurable trap or enable which would
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
607
- * result in a categorized exception syndrome giving information about
639
+
608
- * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
609
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
641
+ can_exit_sleep_mode(s);
610
- * PL1 if in EL0, otherwise to the current EL).
642
+ }
611
- */
643
+
612
- CP_ACCESS_TRAP = 1,
644
+ can_update_irq(s);
613
- /* Access fails and results in an exception syndrome 0x0 ("uncategorized").
645
+}
614
- * Note that this is not a catch-all case -- the set of cases which may
646
+
615
- * result in this failure is specifically defined by the architecture.
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
616
- */
648
+{
617
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
618
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
650
+
619
- CP_ACCESS_TRAP_EL2 = 3,
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
620
- CP_ACCESS_TRAP_EL3 = 4,
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
621
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
653
+
622
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
623
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
655
+ trace_xlnx_can_reset(val);
624
-} CPAccessResult;
656
+
625
-
657
+ /* First, core will do software reset then will enter in config mode. */
626
-/* Access functions for coprocessor registers. These cannot fail and
658
+ can_config_reset(s);
627
- * may not raise exceptions.
659
+ }
628
- */
660
+
629
-typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
630
-typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
662
+ can_config_mode(s);
631
- uint64_t value);
663
+ } else {
632
-/* Access permission check functions for coprocessor registers. */
664
+ /*
633
-typedef CPAccessResult CPAccessFn(CPUARMState *env,
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
634
- const ARMCPRegInfo *opaque,
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
635
- bool isread);
667
+ * register states.
636
-/* Hook function for register reset */
668
+ */
637
-typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
638
-
670
+
639
-#define CP_ANY 0xff
671
+ ptimer_transaction_begin(s->can_timer);
640
-
672
+ ptimer_set_count(s->can_timer, 0);
641
-/* Definition of an ARM coprocessor register */
673
+ ptimer_transaction_commit(s->can_timer);
642
-struct ARMCPRegInfo {
674
+
643
- /* Name of register (useful mainly for debugging, need not be unique) */
675
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
644
- const char *name;
676
+ transfer_fifo(s, &s->txhpb_fifo);
645
- /* Location of register: coprocessor number and (crn,crm,opc1,opc2)
677
+ transfer_fifo(s, &s->tx_fifo);
646
- * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
678
+ }
647
- * 'wildcard' field -- any value of that field in the MRC/MCR insn
679
+
648
- * will be decoded to this register. The register read and write
680
+ update_status_register_mode_bits(s);
649
- * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
681
+
650
- * used by the program, so it is possible to register a wildcard and
682
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
651
- * then behave differently on read/write if necessary.
683
+}
652
- * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
684
+
653
- * must both be zero.
685
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val)
654
- * For AArch64-visible registers, opc0 is also used.
686
+{
655
- * Since there are no "coprocessors" in AArch64, cp is purely used as a
687
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
656
- * way to distinguish (for KVM's benefit) guest-visible system registers
688
+ uint8_t multi_mode;
657
- * from demuxed ones provided to preserve the "no side effects on
689
+
658
- * KVM register read/write from QEMU" semantics. cp==0x13 is guest
690
+ /*
659
- * visible (to match KVM's encoding); cp==0 will be converted to
691
+ * Multiple mode set check. This is done to make sure user doesn't set
660
- * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
692
+ * multiple modes.
661
- */
693
+ */
662
- uint8_t cp;
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
663
- uint8_t crn;
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
664
- uint8_t crm;
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
665
- uint8_t opc0;
697
+
666
- uint8_t opc1;
698
+ if (multi_mode > 1) {
667
- uint8_t opc2;
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
668
- /* Execution state in which this register is visible: ARM_CP_STATE_* */
700
+
669
- int state;
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
670
- /* Register type: ARM_CP_* bits/values */
702
+ " several modes simultaneously. One mode will be selected"
671
- int type;
703
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
672
- /* Access rights: PL*_[RW] */
704
+ path);
673
- int access;
705
+ }
674
- /* Security state: ARM_CP_SECSTATE_* bits/values */
706
+
675
- int secure;
707
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
676
- /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
708
+ /* We are in configuration mode, any mode can be selected. */
677
- * this register was defined: can be used to hand data through to the
709
+ s->regs[R_MODE_SELECT_REGISTER] = val;
678
- * register read/write functions, since they are passed the ARMCPRegInfo*.
710
+ } else {
679
- */
711
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
680
- void *opaque;
712
+
681
- /* Value of this register, if it is ARM_CP_CONST. Otherwise, if
713
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
682
- * fieldoffset is non-zero, the reset value of the register.
714
+
683
- */
715
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
684
- uint64_t resetvalue;
716
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
685
- /* Offset of the field in CPUARMState for this register.
717
+
686
- *
718
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
687
- * This is not needed if either:
719
+ " LBACK mode without setting CEN bit as 0.\n",
688
- * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
720
+ path);
689
- * 2. both readfn and writefn are specified
721
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
690
- */
722
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
691
- ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
723
+
692
-
724
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
693
- /* Offsets of the secure and non-secure fields in CPUARMState for the
725
+ " SNOOP mode without setting CEN bit as 0.\n",
694
- * register if it is banked. These fields are only used during the static
726
+ path);
695
- * registration of a register. During hashing the bank associated
727
+ }
696
- * with a given security state is copied to fieldoffset which is used from
728
+
697
- * there on out.
729
+ update_status_register_mode_bits(s);
698
- *
730
+ }
699
- * It is expected that register definitions use either fieldoffset or
731
+
700
- * bank_fieldoffsets in the definition but not both. It is also expected
732
+ return s->regs[R_MODE_SELECT_REGISTER];
701
- * that both bank offsets are set when defining a banked register. This
733
+}
702
- * use indicates that a register is banked.
734
+
703
- */
735
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val)
704
- ptrdiff_t bank_fieldoffsets[2];
736
+{
705
-
737
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
706
- /* Function for making any access checks for this register in addition to
738
+
707
- * those specified by the 'access' permissions bits. If NULL, no extra
739
+ /* Only allow writes when in config mode. */
708
- * checks required. The access check is performed at runtime, not at
740
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
709
- * translate time.
741
+ return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
710
- */
742
+ }
711
- CPAccessFn *accessfn;
743
+
712
- /* Function for handling reads of this register. If NULL, then reads
744
+ return val;
713
- * will be done by loading from the offset into CPUARMState specified
745
+}
714
- * by fieldoffset.
746
+
715
- */
747
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val)
716
- CPReadFn *readfn;
748
+{
717
- /* Function for handling writes of this register. If NULL, then writes
749
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
718
- * will be done by writing to the offset into CPUARMState specified
750
+
719
- * by fieldoffset.
751
+ /* Only allow writes when in config mode. */
720
- */
752
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
721
- CPWriteFn *writefn;
753
+ return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
722
- /* Function for doing a "raw" read; used when we need to copy
754
+ }
723
- * coprocessor state to the kernel for KVM or out for
755
+
724
- * migration. This only needs to be provided if there is also a
756
+ return val;
725
- * readfn and it has side effects (for instance clear-on-read bits).
757
+}
726
- */
758
+
727
- CPReadFn *raw_readfn;
759
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val)
728
- /* Function for doing a "raw" write; used when we need to copy KVM
760
+{
729
- * kernel coprocessor state into userspace, or for inbound
761
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
730
- * migration. This only needs to be provided if there is also a
762
+
731
- * writefn and it masks out "unwritable" bits or has write-one-to-clear
763
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
732
- * or similar behaviour.
764
+ ptimer_transaction_begin(s->can_timer);
733
- */
765
+ ptimer_set_count(s->can_timer, 0);
734
- CPWriteFn *raw_writefn;
766
+ ptimer_transaction_commit(s->can_timer);
735
- /* Function for resetting the register. If NULL, then reset will be done
767
+ }
736
- * by writing resetvalue to the field specified in fieldoffset. If
768
+
737
- * fieldoffset is 0 then no reset will be done.
769
+ return 0;
738
- */
770
+}
739
- CPResetFn *resetfn;
771
+
740
-
772
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
741
- /*
773
+{
742
- * "Original" writefn and readfn.
774
+ bool filter_pass = false;
743
- * For ARMv8.1-VHE register aliases, we overwrite the read/write
775
+ uint16_t timestamp = 0;
744
- * accessor functions of various EL1/EL0 to perform the runtime
776
+
745
- * check for which sysreg should actually be modified, and then
777
+ /* If no filter is enabled. Message will be stored in FIFO. */
746
- * forwards the operation. Before overwriting the accessors,
778
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
747
- * the original function is copied here, so that accesses that
779
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
748
- * really do go to the EL1/EL0 version proceed normally.
780
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
749
- * (The corresponding EL2 register is linked via opaque.)
781
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
750
- */
782
+ filter_pass = true;
751
- CPReadFn *orig_readfn;
783
+ }
752
- CPWriteFn *orig_writefn;
784
+
753
-};
785
+ /*
754
-
786
+ * Messages that pass any of the acceptance filters will be stored in
755
-/* Macros which are lvalues for the field in CPUARMState for the
787
+ * the RX FIFO.
756
- * ARMCPRegInfo *ri.
788
+ */
757
- */
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
758
-#define CPREG_FIELD32(env, ri) \
790
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
759
- (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
791
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
760
-#define CPREG_FIELD64(env, ri) \
792
+
761
- (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
793
+ if (filter_id_masked == id_masked) {
762
-
794
+ filter_pass = true;
763
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
795
+ }
764
-
796
+ }
765
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
797
+
766
- const ARMCPRegInfo *regs, void *opaque);
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
767
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
799
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
768
- const ARMCPRegInfo *regs, void *opaque);
800
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
769
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
801
+
770
-{
802
+ if (filter_id_masked == id_masked) {
771
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
803
+ filter_pass = true;
772
-}
804
+ }
773
-static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
805
+ }
774
-{
806
+
775
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
807
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
776
-}
808
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
777
-const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
809
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
778
-
810
+
779
-/*
811
+ if (filter_id_masked == id_masked) {
780
- * Definition of an ARM co-processor register as viewed from
812
+ filter_pass = true;
781
- * userspace. This is used for presenting sanitised versions of
813
+ }
782
- * registers to userspace when emulating the Linux AArch64 CPU
814
+ }
783
- * ID/feature ABI (advertised as HWCAP_CPUID).
815
+
784
- */
816
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
785
-typedef struct ARMCPRegUserSpaceInfo {
817
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
786
- /* Name of register */
818
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
787
- const char *name;
819
+
788
-
820
+ if (filter_id_masked == id_masked) {
789
- /* Is the name actually a glob pattern */
821
+ filter_pass = true;
790
- bool is_glob;
822
+ }
791
-
823
+ }
792
- /* Only some bits are exported to user space */
824
+
793
- uint64_t exported_bits;
825
+ if (!filter_pass) {
794
-
826
+ trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc);
795
- /* Fixed bits are applied after the mask */
827
+ return;
796
- uint64_t fixed_bits;
828
+ }
797
-} ARMCPRegUserSpaceInfo;
829
+
798
-
830
+ /* Store the message in fifo if it passed through any of the filters. */
799
-#define REGUSERINFO_SENTINEL { .name = NULL }
831
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
800
-
832
+
801
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
833
+ if (fifo32_is_full(&s->rx_fifo)) {
802
-
834
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
803
-/* CPWriteFn that can be used to implement writes-ignored behaviour */
835
+ } else {
804
-void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
836
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
805
- uint64_t value);
837
+
806
-/* CPReadFn that can be used for read-as-zero behaviour */
838
+ fifo32_push(&s->rx_fifo, frame->can_id);
807
-uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
839
+
808
-
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
809
-/* CPResetFn that does nothing, for use if no reset is required even
841
+ R_RXFIFO_DLC_DLC_LENGTH,
810
- * if fieldoffset is non zero.
842
+ frame->can_dlc) |
811
- */
843
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
812
-void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
844
+ R_RXFIFO_DLC_RXT_LENGTH,
813
-
845
+ timestamp));
814
-/* Return true if this reginfo struct's field in the cpu state struct
846
+
815
- * is 64 bits wide.
847
+ /* First 32 bit of the data. */
816
- */
848
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
817
-static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
849
+ R_TXFIFO_DATA1_DB3_LENGTH,
818
-{
850
+ frame->data[0]) |
819
- return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
851
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
820
-}
852
+ R_TXFIFO_DATA1_DB2_LENGTH,
821
-
853
+ frame->data[1]) |
822
-static inline bool cp_access_ok(int current_el,
854
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
823
- const ARMCPRegInfo *ri, int isread)
855
+ R_TXFIFO_DATA1_DB1_LENGTH,
824
-{
856
+ frame->data[2]) |
825
- return (ri->access >> ((current_el * 2) + isread)) & 1;
857
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
826
-}
858
+ R_TXFIFO_DATA1_DB0_LENGTH,
827
-
859
+ frame->data[3]));
828
-/* Raw read of a coprocessor register (as needed for migration, etc) */
860
+ /* Last 32 bit of the data. */
829
-uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
861
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
830
-
862
+ R_TXFIFO_DATA2_DB7_LENGTH,
831
/**
863
+ frame->data[4]) |
832
* write_list_to_cpustate
864
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
833
* @cpu: ARMCPU
865
+ R_TXFIFO_DATA2_DB6_LENGTH,
834
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
866
+ frame->data[5]) |
835
index XXXXXXX..XXXXXXX 100644
867
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
836
--- a/hw/arm/pxa2xx.c
868
+ R_TXFIFO_DATA2_DB5_LENGTH,
837
+++ b/hw/arm/pxa2xx.c
869
+ frame->data[6]) |
838
@@ -XXX,XX +XXX,XX @@
870
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
839
#include "qemu/cutils.h"
871
+ R_TXFIFO_DATA2_DB4_LENGTH,
840
#include "qemu/log.h"
872
+ frame->data[7]));
841
#include "qom/object.h"
873
+
842
+#include "target/arm/cpregs.h"
874
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
843
875
+ trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc,
844
static struct {
876
+ frame->data[0], frame->data[1],
845
hwaddr io_base;
877
+ frame->data[2], frame->data[3],
846
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
878
+ frame->data[4], frame->data[5],
847
index XXXXXXX..XXXXXXX 100644
879
+ frame->data[6], frame->data[7]);
848
--- a/hw/arm/pxa2xx_pic.c
880
+ }
849
+++ b/hw/arm/pxa2xx_pic.c
881
+
850
@@ -XXX,XX +XXX,XX @@
882
+ can_update_irq(s);
851
#include "hw/sysbus.h"
883
+ }
852
#include "migration/vmstate.h"
884
+}
853
#include "qom/object.h"
885
+
854
+#include "target/arm/cpregs.h"
886
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
855
887
+{
856
#define ICIP    0x00    /* Interrupt Controller IRQ Pending register */
888
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
857
#define ICMR    0x04    /* Interrupt Controller Mask register */
889
+
858
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
890
+ if (!fifo32_is_empty(&s->rx_fifo)) {
859
index XXXXXXX..XXXXXXX 100644
891
+ val = fifo32_pop(&s->rx_fifo);
860
--- a/hw/intc/arm_gicv3_cpuif.c
892
+ } else {
861
+++ b/hw/intc/arm_gicv3_cpuif.c
893
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
862
@@ -XXX,XX +XXX,XX @@
894
+ }
863
#include "gicv3_internal.h"
895
+
864
#include "hw/irq.h"
896
+ can_update_irq(s);
865
#include "cpu.h"
897
+ return val;
866
+#include "target/arm/cpregs.h"
898
+}
867
899
+
868
/*
900
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val)
869
* Special case return value from hppvi_index(); must be larger than
901
+{
870
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
902
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
871
index XXXXXXX..XXXXXXX 100644
903
+
872
--- a/hw/intc/arm_gicv3_kvm.c
904
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
873
+++ b/hw/intc/arm_gicv3_kvm.c
905
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
874
@@ -XXX,XX +XXX,XX @@
906
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
875
#include "vgic_common.h"
907
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
876
#include "migration/blocker.h"
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
877
#include "qom/object.h"
909
+ } else {
878
+#include "target/arm/cpregs.h"
910
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
879
+
911
+ }
880
912
+}
881
#ifdef DEBUG_GICV3_KVM
913
+
882
#define DPRINTF(fmt, ...) \
914
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val)
883
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
915
+{
884
index XXXXXXX..XXXXXXX 100644
916
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
885
--- a/target/arm/cpu.c
917
+ uint32_t reg_idx = (reg->access->addr) / 4;
886
+++ b/target/arm/cpu.c
918
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
887
@@ -XXX,XX +XXX,XX @@
919
+
888
#include "kvm_arm.h"
920
+ /* modify an acceptance filter, the corresponding UAF bit should be '0'. */
889
#include "disas/capstone.h"
921
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
890
#include "fpu/softfloat.h"
922
+ s->regs[reg_idx] = val;
891
+#include "cpregs.h"
923
+
892
924
+ trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_idx]);
893
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
925
+ } else {
894
{
926
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
895
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
927
+
896
index XXXXXXX..XXXXXXX 100644
928
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
897
--- a/target/arm/cpu64.c
929
+ " mask is not set as corresponding UAF bit is not 0.\n",
898
+++ b/target/arm/cpu64.c
930
+ path, filter_number + 1);
899
@@ -XXX,XX +XXX,XX @@
931
+ }
900
#include "hvf_arm.h"
932
+
901
#include "qapi/visitor.h"
933
+ return s->regs[reg_idx];
902
#include "hw/qdev-properties.h"
934
+}
903
+#include "cpregs.h"
935
+
904
936
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val)
905
937
+{
906
#ifndef CONFIG_USER_ONLY
938
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
907
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
939
+ uint32_t reg_idx = (reg->access->addr) / 4;
908
index XXXXXXX..XXXXXXX 100644
940
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
909
--- a/target/arm/cpu_tcg.c
941
+
910
+++ b/target/arm/cpu_tcg.c
942
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
911
@@ -XXX,XX +XXX,XX @@
943
+ s->regs[reg_idx] = val;
912
#if !defined(CONFIG_USER_ONLY)
944
+
913
#include "hw/boards.h"
945
+ trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]);
914
#endif
946
+ } else {
915
+#include "cpregs.h"
947
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
916
948
+
917
/* CPU models. These are not needed for the AArch64 linux-user build. */
949
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
918
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
950
+ " id is not set as corresponding UAF bit is not 0.\n",
919
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
951
+ path, filter_number + 1);
920
index XXXXXXX..XXXXXXX 100644
952
+ }
921
--- a/target/arm/gdbstub.c
953
+
922
+++ b/target/arm/gdbstub.c
954
+ return s->regs[reg_idx];
923
@@ -XXX,XX +XXX,XX @@
955
+}
924
*/
956
+
925
#include "qemu/osdep.h"
957
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val)
926
#include "cpu.h"
958
+{
927
-#include "internals.h"
959
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
928
#include "exec/gdbstub.h"
960
+
929
+#include "internals.h"
961
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
930
+#include "cpregs.h"
962
+
931
963
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
932
typedef struct RegisterSysregXmlParam {
964
+ (reg->access->addr == A_TXHPB_DATA2);
933
CPUState *cs;
965
+
934
diff --git a/target/arm/helper.c b/target/arm/helper.c
966
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
935
index XXXXXXX..XXXXXXX 100644
967
+
936
--- a/target/arm/helper.c
968
+ if (!fifo32_is_full(f)) {
937
+++ b/target/arm/helper.c
969
+ fifo32_push(f, val);
938
@@ -XXX,XX +XXX,XX @@
970
+ } else {
939
#include "exec/cpu_ldst.h"
971
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
940
#include "semihosting/common-semi.h"
972
+
941
#endif
973
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
942
+#include "cpregs.h"
974
+ }
943
975
+
944
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
976
+ /* Initiate the message send if TX register is written. */
945
#define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */
977
+ if (initiate_transfer &&
946
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
978
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
947
index XXXXXXX..XXXXXXX 100644
979
+ transfer_fifo(s, f);
948
--- a/target/arm/op_helper.c
980
+ }
949
+++ b/target/arm/op_helper.c
981
+
950
@@ -XXX,XX +XXX,XX @@
982
+ can_update_irq(s);
951
#include "internals.h"
983
+}
952
#include "exec/exec-all.h"
984
+
953
#include "exec/cpu_ldst.h"
985
+static const RegisterAccessInfo can_regs_info[] = {
954
+#include "cpregs.h"
986
+ { .name = "SOFTWARE_RESET_REGISTER",
955
987
+ .addr = A_SOFTWARE_RESET_REGISTER,
956
#define SIGNBIT (uint32_t)0x80000000
988
+ .rsvd = 0xfffffffc,
957
#define SIGNBIT64 ((uint64_t)1 << 63)
989
+ .pre_write = can_srr_pre_write,
958
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
990
+ },{ .name = "MODE_SELECT_REGISTER",
959
index XXXXXXX..XXXXXXX 100644
991
+ .addr = A_MODE_SELECT_REGISTER,
960
--- a/target/arm/translate-a64.c
992
+ .rsvd = 0xfffffff8,
961
+++ b/target/arm/translate-a64.c
993
+ .pre_write = can_msr_pre_write,
962
@@ -XXX,XX +XXX,XX @@
994
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
963
#include "translate.h"
995
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
964
#include "internals.h"
996
+ .rsvd = 0xffffff00,
965
#include "qemu/host-utils.h"
997
+ .pre_write = can_brpr_pre_write,
966
-
998
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
967
#include "semihosting/semihost.h"
999
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
968
#include "exec/gen-icount.h"
1000
+ .rsvd = 0xfffffe00,
969
-
1001
+ .pre_write = can_btr_pre_write,
970
#include "exec/helper-proto.h"
1002
+ },{ .name = "ERROR_COUNTER_REGISTER",
971
#include "exec/helper-gen.h"
1003
+ .addr = A_ERROR_COUNTER_REGISTER,
972
#include "exec/log.h"
1004
+ .rsvd = 0xffff0000,
973
-
1005
+ .ro = 0xffffffff,
974
+#include "cpregs.h"
1006
+ },{ .name = "ERROR_STATUS_REGISTER",
975
#include "translate-a64.h"
1007
+ .addr = A_ERROR_STATUS_REGISTER,
976
#include "qemu/atomic128.h"
1008
+ .rsvd = 0xffffffe0,
977
1009
+ .w1c = 0x1f,
978
diff --git a/target/arm/translate.c b/target/arm/translate.c
1010
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
979
index XXXXXXX..XXXXXXX 100644
1011
+ .reset = 0x1,
980
--- a/target/arm/translate.c
1012
+ .rsvd = 0xffffe000,
981
+++ b/target/arm/translate.c
1013
+ .ro = 0x1fff,
982
@@ -XXX,XX +XXX,XX @@
1014
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
983
#include "qemu/bitops.h"
1015
+ .addr = A_INTERRUPT_STATUS_REGISTER,
984
#include "arm_ldst.h"
1016
+ .reset = 0x6000,
985
#include "semihosting/semihost.h"
1017
+ .rsvd = 0xffff8000,
986
-
1018
+ .ro = 0x7fff,
987
#include "exec/helper-proto.h"
1019
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
988
#include "exec/helper-gen.h"
1020
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
989
-
1021
+ .rsvd = 0xffff8000,
990
#include "exec/log.h"
1022
+ .post_write = can_ier_post_write,
991
+#include "cpregs.h"
1023
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
992
1024
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
993
1025
+ .rsvd = 0xffff8000,
994
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
1026
+ .pre_write = can_icr_pre_write,
1027
+ },{ .name = "TIMESTAMP_REGISTER",
1028
+ .addr = A_TIMESTAMP_REGISTER,
1029
+ .rsvd = 0xfffffffe,
1030
+ .pre_write = can_tcr_pre_write,
1031
+ },{ .name = "WIR", .addr = A_WIR,
1032
+ .reset = 0x3f3f,
1033
+ .rsvd = 0xffff0000,
1034
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1035
+ .post_write = can_tx_post_write,
1036
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1037
+ .rsvd = 0xfffffff,
1038
+ .post_write = can_tx_post_write,
1039
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1040
+ .post_write = can_tx_post_write,
1041
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1042
+ .post_write = can_tx_post_write,
1043
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1044
+ .post_write = can_tx_post_write,
1045
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1046
+ .rsvd = 0xfffffff,
1047
+ .post_write = can_tx_post_write,
1048
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1049
+ .post_write = can_tx_post_write,
1050
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1051
+ .post_write = can_tx_post_write,
1052
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1053
+ .ro = 0xffffffff,
1054
+ .post_read = can_rxfifo_pre_read,
1055
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1056
+ .rsvd = 0xfff0000,
1057
+ .post_read = can_rxfifo_pre_read,
1058
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1059
+ .post_read = can_rxfifo_pre_read,
1060
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1061
+ .post_read = can_rxfifo_pre_read,
1062
+ },{ .name = "AFR", .addr = A_AFR,
1063
+ .rsvd = 0xfffffff0,
1064
+ .post_write = can_filter_enable_post_write,
1065
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1066
+ .pre_write = can_filter_mask_pre_write,
1067
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1068
+ .pre_write = can_filter_id_pre_write,
1069
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1070
+ .pre_write = can_filter_mask_pre_write,
1071
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1072
+ .pre_write = can_filter_id_pre_write,
1073
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1074
+ .pre_write = can_filter_mask_pre_write,
1075
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1076
+ .pre_write = can_filter_id_pre_write,
1077
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1078
+ .pre_write = can_filter_mask_pre_write,
1079
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1080
+ .pre_write = can_filter_id_pre_write,
1081
+ }
1082
+};
1083
+
1084
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1085
+{
1086
+ /* No action required on the timer rollover. */
1087
+}
1088
+
1089
+static const MemoryRegionOps can_ops = {
1090
+ .read = register_read_memory,
1091
+ .write = register_write_memory,
1092
+ .endianness = DEVICE_LITTLE_ENDIAN,
1093
+ .valid = {
1094
+ .min_access_size = 4,
1095
+ .max_access_size = 4,
1096
+ },
1097
+};
1098
+
1099
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1100
+{
1101
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1102
+ unsigned int i;
1103
+
1104
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1105
+ register_reset(&s->reg_info[i]);
1106
+ }
1107
+
1108
+ ptimer_transaction_begin(s->can_timer);
1109
+ ptimer_set_count(s->can_timer, 0);
1110
+ ptimer_transaction_commit(s->can_timer);
1111
+}
1112
+
1113
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1114
+{
1115
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1116
+ unsigned int i;
1117
+
1118
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1119
+ register_reset(&s->reg_info[i]);
1120
+ }
1121
+
1122
+ /*
1123
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1124
+ * done by post_write which gets called from register_reset function,
1125
+ * post_write handle will not be able to trigger tx because CAN will be
1126
+ * disabled when software_reset_register is cleared first.
1127
+ */
1128
+ fifo32_reset(&s->rx_fifo);
1129
+ fifo32_reset(&s->tx_fifo);
1130
+ fifo32_reset(&s->txhpb_fifo);
1131
+}
1132
+
1133
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1134
+{
1135
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1136
+ bus_client);
1137
+
1138
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1139
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1140
+
1141
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in reset state.\n",
1142
+ path);
1143
+ return false;
1144
+ }
1145
+
1146
+ if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1147
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1148
+
1149
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is disabled. Incoming"
1150
+ " messages will be discarded.\n", path);
1151
+ return false;
1152
+ }
1153
+
1154
+ return true;
1155
+}
1156
+
1157
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1158
+ const qemu_can_frame *buf, size_t buf_size) {
1159
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1160
+ bus_client);
1161
+ const qemu_can_frame *frame = buf;
1162
+
1163
+ if (buf_size <= 0) {
1164
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1165
+
1166
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n",
1167
+ path);
1168
+ return 0;
1169
+ }
1170
+
1171
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1172
+ /* Snoop Mode: Just keep the data. no response back. */
1173
+ update_rx_fifo(s, frame);
1174
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1175
+ /*
1176
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1177
+ * up state.
1178
+ */
1179
+ can_exit_sleep_mode(s);
1180
+ update_rx_fifo(s, frame);
1181
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1182
+ update_rx_fifo(s, frame);
1183
+ } else {
1184
+ /*
1185
+ * XlnxZynqMPCAN will not participate in normal bus communication
1186
+ * and will not receive any messages transmitted by other CAN nodes.
1187
+ */
1188
+ trace_xlnx_can_rx_discard(s->regs[R_STATUS_REGISTER]);
1189
+ }
1190
+
1191
+ return 1;
1192
+}
1193
+
1194
+static CanBusClientInfo can_xilinx_bus_client_info = {
1195
+ .can_receive = xlnx_zynqmp_can_can_receive,
1196
+ .receive = xlnx_zynqmp_can_receive,
1197
+};
1198
+
1199
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1200
+ CanBusState *bus)
1201
+{
1202
+ s->bus_client.info = &can_xilinx_bus_client_info;
1203
+
1204
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1205
+ return -1;
1206
+ }
1207
+ return 0;
1208
+}
1209
+
1210
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1211
+{
1212
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1213
+
1214
+ if (s->canbus) {
1215
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1216
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1217
+
1218
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1219
+ " failed.", path);
1220
+ return;
1221
+ }
1222
+ }
1223
+
1224
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1225
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1226
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1227
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1228
+
1229
+ /* Allocate a new timer. */
1230
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1231
+ PTIMER_POLICY_DEFAULT);
1232
+
1233
+ ptimer_transaction_begin(s->can_timer);
1234
+
1235
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1236
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1237
+ ptimer_run(s->can_timer, 0);
1238
+ ptimer_transaction_commit(s->can_timer);
1239
+}
1240
+
1241
+static void xlnx_zynqmp_can_init(Object *obj)
1242
+{
1243
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1244
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1245
+
1246
+ RegisterInfoArray *reg_array;
1247
+
1248
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1249
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1250
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1251
+ ARRAY_SIZE(can_regs_info),
1252
+ s->reg_info, s->regs,
1253
+ &can_ops,
1254
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1255
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1256
+
1257
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1258
+ sysbus_init_mmio(sbd, &s->iomem);
1259
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1260
+}
1261
+
1262
+static const VMStateDescription vmstate_can = {
1263
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1264
+ .version_id = 1,
1265
+ .minimum_version_id = 1,
1266
+ .fields = (VMStateField[]) {
1267
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
1268
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
1269
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
1270
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
1271
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1272
+ VMSTATE_END_OF_LIST(),
1273
+ }
1274
+};
1275
+
1276
+static Property xlnx_zynqmp_can_properties[] = {
1277
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1278
+ CAN_DEFAULT_CLOCK),
1279
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1280
+ CanBusState *),
1281
+ DEFINE_PROP_END_OF_LIST(),
1282
+};
1283
+
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1285
+{
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1288
+
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1291
+ dc->realize = xlnx_zynqmp_can_realize;
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1293
+ dc->vmsd = &vmstate_can;
1294
+}
1295
+
1296
+static const TypeInfo can_info = {
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
1300
+ .class_init = xlnx_zynqmp_can_class_init,
1301
+ .instance_init = xlnx_zynqmp_can_init,
1302
+};
1303
+
1304
+static void can_register_types(void)
1305
+{
1306
+ type_register_static(&can_info);
1307
+}
1308
+
1309
+type_init(can_register_types)
1310
diff --git a/hw/Kconfig b/hw/Kconfig
1311
index XXXXXXX..XXXXXXX 100644
1312
--- a/hw/Kconfig
1313
+++ b/hw/Kconfig
1314
@@ -XXX,XX +XXX,XX @@ config XILINX_AXI
1315
config XLNX_ZYNQMP
1316
bool
1317
select REGISTER
1318
+ select CAN_BUS
1319
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
1320
index XXXXXXX..XXXXXXX 100644
1321
--- a/hw/net/can/meson.build
1322
+++ b/hw/net/can/meson.build
1323
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
1324
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
1325
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
1326
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
1327
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
1328
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
1329
new file mode 100644
1330
index XXXXXXX..XXXXXXX
1331
--- /dev/null
1332
+++ b/hw/net/can/trace-events
1333
@@ -XXX,XX +XXX,XX @@
1334
+# xlnx-zynqmp-can.c
1335
+xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
1336
+xlnx_can_reset(uint32_t val) "Resetting controller with value = 0x%08x"
1337
+xlnx_can_rx_fifo_filter_reject(uint32_t id, uint8_t dlc) "Frame: ID: 0x%08x DLC: 0x%02x"
1338
+xlnx_can_filter_id_pre_write(uint8_t filter_num, uint32_t value) "Filter%d ID: 0x%08x"
1339
+xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MASK: 0x%08x"
1340
+xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1341
+xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1342
+xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
1343
--
995
--
1344
2.20.1
996
2.25.1
1345
997
1346
998
diff view generated by jsdifflib
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
1
From: Richard Henderson <richard.henderson@linaro.org>
2
This is for saving and restoring the secure floating point context,
3
and it reads and writes bits [27:0] from the FPSCR and the
4
CONTROL.SFPA bit in bit [31].
5
2
3
Rearrange the values of the enumerators of CPAccessResult
4
so that we may directly extract the target el. For the two
5
special cases in access_check_cp_reg, use CPAccessResult.
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220501055028.646596-3-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
9
---
12
---
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
13
target/arm/cpregs.h | 26 ++++++++++++--------
11
1 file changed, 58 insertions(+)
14
target/arm/op_helper.c | 56 +++++++++++++++++++++---------------------
15
2 files changed, 44 insertions(+), 38 deletions(-)
12
16
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
17
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
19
--- a/target/arm/cpregs.h
16
+++ b/target/arm/translate-vfp.c.inc
20
+++ b/target/arm/cpregs.h
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
21
@@ -XXX,XX +XXX,XX @@ static inline bool cptype_valid(int cptype)
18
return false;
22
typedef enum CPAccessResult {
23
/* Access is permitted */
24
CP_ACCESS_OK = 0,
25
+
26
+ /*
27
+ * Combined with one of the following, the low 2 bits indicate the
28
+ * target exception level. If 0, the exception is taken to the usual
29
+ * target EL (EL1 or PL1 if in EL0, otherwise to the current EL).
30
+ */
31
+ CP_ACCESS_EL_MASK = 3,
32
+
33
/*
34
* Access fails due to a configurable trap or enable which would
35
* result in a categorized exception syndrome giving information about
36
* the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
37
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
38
- * PL1 if in EL0, otherwise to the current EL).
39
+ * 0xc or 0x18).
40
*/
41
- CP_ACCESS_TRAP = 1,
42
+ CP_ACCESS_TRAP = (1 << 2),
43
+ CP_ACCESS_TRAP_EL2 = CP_ACCESS_TRAP | 2,
44
+ CP_ACCESS_TRAP_EL3 = CP_ACCESS_TRAP | 3,
45
+
46
/*
47
* Access fails and results in an exception syndrome 0x0 ("uncategorized").
48
* Note that this is not a catch-all case -- the set of cases which may
49
* result in this failure is specifically defined by the architecture.
50
*/
51
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
52
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
53
- CP_ACCESS_TRAP_EL2 = 3,
54
- CP_ACCESS_TRAP_EL3 = 4,
55
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
56
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
57
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
58
+ CP_ACCESS_TRAP_UNCATEGORIZED = (2 << 2),
59
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = CP_ACCESS_TRAP_UNCATEGORIZED | 2,
60
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = CP_ACCESS_TRAP_UNCATEGORIZED | 3,
61
} CPAccessResult;
62
63
typedef struct ARMCPRegInfo ARMCPRegInfo;
64
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/op_helper.c
67
+++ b/target/arm/op_helper.c
68
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
69
uint32_t isread)
70
{
71
const ARMCPRegInfo *ri = rip;
72
+ CPAccessResult res = CP_ACCESS_OK;
73
int target_el;
74
75
if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
76
&& extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
77
- raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
78
+ res = CP_ACCESS_TRAP;
79
+ goto fail;
80
}
81
82
/*
83
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
84
mask &= ~((1 << 4) | (1 << 14));
85
86
if (env->cp15.hstr_el2 & mask) {
87
- target_el = 2;
88
- goto exept;
89
+ res = CP_ACCESS_TRAP_EL2;
90
+ goto fail;
19
}
91
}
92
}
93
94
- if (!ri->accessfn) {
95
+ if (ri->accessfn) {
96
+ res = ri->accessfn(env, ri, isread);
97
+ }
98
+ if (likely(res == CP_ACCESS_OK)) {
99
return;
100
}
101
102
- switch (ri->accessfn(env, ri, isread)) {
103
- case CP_ACCESS_OK:
104
- return;
105
+ fail:
106
+ switch (res & ~CP_ACCESS_EL_MASK) {
107
case CP_ACCESS_TRAP:
108
- target_el = exception_target_el(env);
109
- break;
110
- case CP_ACCESS_TRAP_EL2:
111
- /* Requesting a trap to EL2 when we're in EL3 is
112
- * a bug in the access function.
113
- */
114
- assert(arm_current_el(env) != 3);
115
- target_el = 2;
116
- break;
117
- case CP_ACCESS_TRAP_EL3:
118
- target_el = 3;
20
break;
119
break;
21
+ case ARM_VFP_FPCXT_S:
120
case CP_ACCESS_TRAP_UNCATEGORIZED:
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
121
- target_el = exception_target_el(env);
23
+ return false;
122
- syndrome = syn_uncategorized();
24
+ }
123
- break;
25
+ if (!s->v8m_secure) {
124
- case CP_ACCESS_TRAP_UNCATEGORIZED_EL2:
26
+ return false;
125
- target_el = 2;
27
+ }
126
- syndrome = syn_uncategorized();
28
+ break;
127
- break;
29
default:
128
- case CP_ACCESS_TRAP_UNCATEGORIZED_EL3:
30
return FPSysRegCheckFailed;
129
- target_el = 3;
31
}
130
syndrome = syn_uncategorized();
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
33
tcg_temp_free_i32(tmp);
34
break;
131
break;
35
}
36
+ case ARM_VFP_FPCXT_S:
37
+ {
38
+ TCGv_i32 sfpa, control, fpscr;
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
40
+ tmp = loadfn(s, opaque);
41
+ sfpa = tcg_temp_new_i32();
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
44
+ tcg_gen_deposit_i32(control, control, sfpa,
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
52
+ tcg_temp_free_i32(tmp);
53
+ tcg_temp_free_i32(sfpa);
54
+ break;
55
+ }
56
default:
132
default:
57
g_assert_not_reached();
133
g_assert_not_reached();
58
}
134
}
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
135
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
136
-exept:
61
storefn(s, opaque, tmp);
137
+ target_el = res & CP_ACCESS_EL_MASK;
62
break;
138
+ switch (target_el) {
63
+ case ARM_VFP_FPCXT_S:
139
+ case 0:
64
+ {
140
+ target_el = exception_target_el(env);
65
+ TCGv_i32 control, sfpa, fpscr;
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
67
+ tmp = tcg_temp_new_i32();
68
+ sfpa = tcg_temp_new_i32();
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
75
+ tcg_temp_free_i32(sfpa);
76
+ /*
77
+ * Store result before updating FPSCR etc, in case
78
+ * it is a memory write which causes an exception.
79
+ */
80
+ storefn(s, opaque, tmp);
81
+ /*
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
83
+ * CONTROL.SFPA; so we'll end the TB here.
84
+ */
85
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
86
+ store_cpu_field(control, v7m.control[M_REG_S]);
87
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
88
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
89
+ tcg_temp_free_i32(fpscr);
90
+ gen_lookup_tb(s);
91
+ break;
141
+ break;
142
+ case 2:
143
+ assert(arm_current_el(env) != 3);
144
+ assert(arm_is_el2_enabled(env));
145
+ break;
146
+ case 3:
147
+ assert(arm_feature(env, ARM_FEATURE_EL3));
148
+ break;
149
+ default:
150
+ /* No "direct" traps to EL1 */
151
+ g_assert_not_reached();
92
+ }
152
+ }
93
default:
153
+
94
g_assert_not_reached();
154
raise_exception(env, EXCP_UDEF, syndrome, target_el);
95
}
155
}
156
96
--
157
--
97
2.20.1
158
2.25.1
98
159
99
160
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
Remove a possible source of error by removing REGINFO_SENTINEL
4
argument of type "unsigned int".
4
and using ARRAY_SIZE (convinently hidden inside a macro) to
5
find the end of the set of regs being registered or modified.
5
6
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
The space saved by not having the extra array element reduces
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
the executable's .data.rel.ro section by about 9k.
8
Message-id: 20201126111109.112238-4-alex.chen@huawei.com
9
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20220501055028.646596-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
15
---
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
16
target/arm/cpregs.h | 53 +++++++++---------
13
hw/misc/imx6_src.c | 2 +-
17
hw/arm/pxa2xx.c | 1 -
14
2 files changed, 11 insertions(+), 11 deletions(-)
18
hw/arm/pxa2xx_pic.c | 1 -
19
hw/intc/arm_gicv3_cpuif.c | 5 --
20
hw/intc/arm_gicv3_kvm.c | 1 -
21
target/arm/cpu64.c | 1 -
22
target/arm/cpu_tcg.c | 4 --
23
target/arm/helper.c | 111 ++++++++------------------------------
24
8 files changed, 48 insertions(+), 129 deletions(-)
15
25
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
26
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
17
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/imx6_ccm.c
28
--- a/target/arm/cpregs.h
19
+++ b/hw/misc/imx6_ccm.c
29
+++ b/target/arm/cpregs.h
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
30
@@ -XXX,XX +XXX,XX @@
21
case CCM_CMEOR:
31
#define ARM_CP_NO_GDB 0x4000
22
return "CMEOR";
32
#define ARM_CP_RAISES_EXC 0x8000
23
default:
33
#define ARM_CP_NEWEL 0x10000
24
- sprintf(unknown, "%d ?", reg);
34
-/* Used only as a terminator for ARMCPRegInfo lists */
25
+ sprintf(unknown, "%u ?", reg);
35
-#define ARM_CP_SENTINEL 0xfffff
26
return unknown;
36
/* Mask of only the flag bits in a type field */
37
#define ARM_CP_FLAG_MASK 0x1f0ff
38
39
@@ -XXX,XX +XXX,XX @@ enum {
40
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
41
};
42
43
-/*
44
- * Return true if cptype is a valid type field. This is used to try to
45
- * catch errors where the sentinel has been accidentally left off the end
46
- * of a list of registers.
47
- */
48
-static inline bool cptype_valid(int cptype)
49
-{
50
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
51
- || ((cptype & ARM_CP_SPECIAL) &&
52
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
53
-}
54
-
55
/*
56
* Access rights:
57
* We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
58
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
59
#define CPREG_FIELD64(env, ri) \
60
(*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
61
62
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
63
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, const ARMCPRegInfo *reg,
64
+ void *opaque);
65
66
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
67
- const ARMCPRegInfo *regs, void *opaque);
68
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
69
- const ARMCPRegInfo *regs, void *opaque);
70
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
71
-{
72
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
73
-}
74
static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
75
{
76
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
77
+ define_one_arm_cp_reg_with_opaque(cpu, regs, NULL);
78
}
79
+
80
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
81
+ void *opaque, size_t len);
82
+
83
+#define define_arm_cp_regs_with_opaque(CPU, REGS, OPAQUE) \
84
+ do { \
85
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(REGS) == 0); \
86
+ define_arm_cp_regs_with_opaque_len(CPU, REGS, OPAQUE, \
87
+ ARRAY_SIZE(REGS)); \
88
+ } while (0)
89
+
90
+#define define_arm_cp_regs(CPU, REGS) \
91
+ define_arm_cp_regs_with_opaque(CPU, REGS, NULL)
92
+
93
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
94
95
/*
96
@@ -XXX,XX +XXX,XX @@ typedef struct ARMCPRegUserSpaceInfo {
97
uint64_t fixed_bits;
98
} ARMCPRegUserSpaceInfo;
99
100
-#define REGUSERINFO_SENTINEL { .name = NULL }
101
+void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
102
+ const ARMCPRegUserSpaceInfo *mods,
103
+ size_t mods_len);
104
105
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
106
+#define modify_arm_cp_regs(REGS, MODS) \
107
+ do { \
108
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(REGS) == 0); \
109
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(MODS) == 0); \
110
+ modify_arm_cp_regs_with_len(REGS, ARRAY_SIZE(REGS), \
111
+ MODS, ARRAY_SIZE(MODS)); \
112
+ } while (0)
113
114
/* CPWriteFn that can be used to implement writes-ignored behaviour */
115
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
116
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/arm/pxa2xx.c
119
+++ b/hw/arm/pxa2xx.c
120
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pxa_cp_reginfo[] = {
121
{ .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
122
.access = PL1_RW, .type = ARM_CP_IO,
123
.readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
124
- REGINFO_SENTINEL
125
};
126
127
static void pxa2xx_setup_cp14(PXA2xxState *s)
128
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/hw/arm/pxa2xx_pic.c
131
+++ b/hw/arm/pxa2xx_pic.c
132
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
133
REGINFO_FOR_PIC_CP("ICLR2", 8),
134
REGINFO_FOR_PIC_CP("ICFP2", 9),
135
REGINFO_FOR_PIC_CP("ICPR2", 0xa),
136
- REGINFO_SENTINEL
137
};
138
139
static const MemoryRegionOps pxa2xx_pic_ops = {
140
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/hw/intc/arm_gicv3_cpuif.c
143
+++ b/hw/intc/arm_gicv3_cpuif.c
144
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
145
.readfn = icc_igrpen1_el3_read,
146
.writefn = icc_igrpen1_el3_write,
147
},
148
- REGINFO_SENTINEL
149
};
150
151
static uint64_t ich_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
152
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_hcr_reginfo[] = {
153
.readfn = ich_vmcr_read,
154
.writefn = ich_vmcr_write,
155
},
156
- REGINFO_SENTINEL
157
};
158
159
static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
160
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
161
.readfn = ich_ap_read,
162
.writefn = ich_ap_write,
163
},
164
- REGINFO_SENTINEL
165
};
166
167
static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
168
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
169
.readfn = ich_ap_read,
170
.writefn = ich_ap_write,
171
},
172
- REGINFO_SENTINEL
173
};
174
175
static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
176
@@ -XXX,XX +XXX,XX @@ void gicv3_init_cpuif(GICv3State *s)
177
.readfn = ich_lr_read,
178
.writefn = ich_lr_write,
179
},
180
- REGINFO_SENTINEL
181
};
182
define_arm_cp_regs(cpu, lr_regset);
183
}
184
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/hw/intc/arm_gicv3_kvm.c
187
+++ b/hw/intc/arm_gicv3_kvm.c
188
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
189
*/
190
.resetfn = arm_gicv3_icc_reset,
191
},
192
- REGINFO_SENTINEL
193
};
194
195
/**
196
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/target/arm/cpu64.c
199
+++ b/target/arm/cpu64.c
200
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
201
{ .name = "L2MERRSR",
202
.cp = 15, .opc1 = 3, .crm = 15,
203
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
204
- REGINFO_SENTINEL
205
};
206
207
static void aarch64_a57_initfn(Object *obj)
208
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/target/arm/cpu_tcg.c
211
+++ b/target/arm/cpu_tcg.c
212
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
213
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
214
{ .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
215
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
216
- REGINFO_SENTINEL
217
};
218
219
static void cortex_a8_initfn(Object *obj)
220
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
221
.access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
222
{ .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
223
.access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
224
- REGINFO_SENTINEL
225
};
226
227
static void cortex_a9_initfn(Object *obj)
228
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
229
#endif
230
{ .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
231
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
232
- REGINFO_SENTINEL
233
};
234
235
static void cortex_a7_initfn(Object *obj)
236
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
237
.access = PL1_RW, .type = ARM_CP_CONST },
238
{ .name = "DCACHE_INVAL", .cp = 15, .opc1 = 0, .crn = 15, .crm = 5,
239
.opc2 = 0, .access = PL1_W, .type = ARM_CP_NOP },
240
- REGINFO_SENTINEL
241
};
242
243
static void cortex_r5_initfn(Object *obj)
244
diff --git a/target/arm/helper.c b/target/arm/helper.c
245
index XXXXXXX..XXXXXXX 100644
246
--- a/target/arm/helper.c
247
+++ b/target/arm/helper.c
248
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cp_reginfo[] = {
249
.secure = ARM_CP_SECSTATE_S,
250
.fieldoffset = offsetof(CPUARMState, cp15.contextidr_s),
251
.resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
252
- REGINFO_SENTINEL
253
};
254
255
static const ARMCPRegInfo not_v8_cp_reginfo[] = {
256
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v8_cp_reginfo[] = {
257
{ .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
258
.opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
259
.type = ARM_CP_NOP | ARM_CP_OVERRIDE },
260
- REGINFO_SENTINEL
261
};
262
263
static const ARMCPRegInfo not_v6_cp_reginfo[] = {
264
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v6_cp_reginfo[] = {
265
*/
266
{ .name = "WFI_v5", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = 2,
267
.access = PL1_W, .type = ARM_CP_WFI },
268
- REGINFO_SENTINEL
269
};
270
271
static const ARMCPRegInfo not_v7_cp_reginfo[] = {
272
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v7_cp_reginfo[] = {
273
.opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NOP },
274
{ .name = "NMRR", .cp = 15, .crn = 10, .crm = 2,
275
.opc1 = 0, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_NOP },
276
- REGINFO_SENTINEL
277
};
278
279
static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
280
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
281
.crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .accessfn = cpacr_access,
282
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1),
283
.resetfn = cpacr_reset, .writefn = cpacr_write, .readfn = cpacr_read },
284
- REGINFO_SENTINEL
285
};
286
287
typedef struct pm_event {
288
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
289
{ .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
290
.type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
291
.writefn = tlbimvaa_write },
292
- REGINFO_SENTINEL
293
};
294
295
static const ARMCPRegInfo v7mp_cp_reginfo[] = {
296
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7mp_cp_reginfo[] = {
297
{ .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
298
.type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
299
.writefn = tlbimvaa_is_write },
300
- REGINFO_SENTINEL
301
};
302
303
static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
304
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
305
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
306
.writefn = pmovsset_write,
307
.raw_writefn = raw_write },
308
- REGINFO_SENTINEL
309
};
310
311
static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
312
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo t2ee_cp_reginfo[] = {
313
{ .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
314
.access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr),
315
.accessfn = teehbr_access, .resetvalue = 0 },
316
- REGINFO_SENTINEL
317
};
318
319
static const ARMCPRegInfo v6k_cp_reginfo[] = {
320
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
321
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrprw_s),
322
offsetoflow32(CPUARMState, cp15.tpidrprw_ns) },
323
.resetvalue = 0 },
324
- REGINFO_SENTINEL
325
};
326
327
#ifndef CONFIG_USER_ONLY
328
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
329
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cval),
330
.writefn = gt_sec_cval_write, .raw_writefn = raw_write,
331
},
332
- REGINFO_SENTINEL
333
};
334
335
static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
336
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
337
.access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
338
.readfn = gt_virt_cnt_read,
339
},
340
- REGINFO_SENTINEL
341
};
342
343
#endif
344
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vapa_cp_reginfo[] = {
345
.access = PL1_W, .accessfn = ats_access,
346
.writefn = ats_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
347
#endif
348
- REGINFO_SENTINEL
349
};
350
351
/* Return basic MPU access permission bits. */
352
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
353
.fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]),
354
.writefn = pmsav7_rgnr_write,
355
.resetfn = arm_cp_reset_ignore },
356
- REGINFO_SENTINEL
357
};
358
359
static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
360
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
361
{ .name = "946_PRBS7", .cp = 15, .crn = 6, .crm = 7, .opc1 = 0,
362
.opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
363
.fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
364
- REGINFO_SENTINEL
365
};
366
367
static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
368
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
369
.access = PL1_RW, .accessfn = access_tvm_trvm,
370
.fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
371
.resetvalue = 0, },
372
- REGINFO_SENTINEL
373
};
374
375
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
376
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
377
/* No offsetoflow32 -- pass the entire TCR to writefn/raw_writefn. */
378
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.tcr_el[3]),
379
offsetof(CPUARMState, cp15.tcr_el[1])} },
380
- REGINFO_SENTINEL
381
};
382
383
/* Note that unlike TTBCR, writing to TTBCR2 does not require flushing
384
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo omap_cp_reginfo[] = {
385
{ .name = "C9", .cp = 15, .crn = 9,
386
.crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
387
.type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
388
- REGINFO_SENTINEL
389
};
390
391
static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
392
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo xscale_cp_reginfo[] = {
393
{ .name = "XSCALE_UNLOCK_DCACHE",
394
.cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 1,
395
.access = PL1_W, .type = ARM_CP_NOP },
396
- REGINFO_SENTINEL
397
};
398
399
static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
400
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
401
.access = PL1_RW,
402
.type = ARM_CP_CONST | ARM_CP_NO_RAW | ARM_CP_OVERRIDE,
403
.resetvalue = 0 },
404
- REGINFO_SENTINEL
405
};
406
407
static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
408
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
409
{ .name = "CDSR", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 6,
410
.access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
411
.resetvalue = 0 },
412
- REGINFO_SENTINEL
413
};
414
415
static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
416
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
417
.access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
418
{ .name = "CIDCR", .cp = 15, .crm = 14, .opc1 = 0,
419
.access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
420
- REGINFO_SENTINEL
421
};
422
423
static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
424
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
425
{ .name = "TCI_DCACHE", .cp = 15, .crn = 7, .crm = 14, .opc1 = 0, .opc2 = 3,
426
.access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
427
.resetvalue = (1 << 30) },
428
- REGINFO_SENTINEL
429
};
430
431
static const ARMCPRegInfo strongarm_cp_reginfo[] = {
432
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo strongarm_cp_reginfo[] = {
433
.crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
434
.access = PL1_RW, .resetvalue = 0,
435
.type = ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_RAW },
436
- REGINFO_SENTINEL
437
};
438
439
static uint64_t midr_read(CPUARMState *env, const ARMCPRegInfo *ri)
440
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
441
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
442
offsetof(CPUARMState, cp15.ttbr1_ns) },
443
.writefn = vmsa_ttbr_write, },
444
- REGINFO_SENTINEL
445
};
446
447
static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
448
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
449
.access = PL1_RW, .accessfn = access_trap_aa32s_el1,
450
.writefn = sdcr_write,
451
.fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
452
- REGINFO_SENTINEL
453
};
454
455
/* Used to describe the behaviour of EL2 regs when EL2 does not exist. */
456
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
457
.type = ARM_CP_CONST,
458
.cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
459
.access = PL2_RW, .resetvalue = 0 },
460
- REGINFO_SENTINEL
461
};
462
463
/* Ditto, but for registers which exist in ARMv8 but not v7 */
464
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
465
.cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
466
.access = PL2_RW,
467
.type = ARM_CP_CONST, .resetvalue = 0 },
468
- REGINFO_SENTINEL
469
};
470
471
static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
472
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
473
.cp = 15, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
474
.access = PL2_RW,
475
.fieldoffset = offsetof(CPUARMState, cp15.hstr_el2) },
476
- REGINFO_SENTINEL
477
};
478
479
static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
480
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
481
.access = PL2_RW,
482
.fieldoffset = offsetofhigh32(CPUARMState, cp15.hcr_el2),
483
.writefn = hcr_writehigh },
484
- REGINFO_SENTINEL
485
};
486
487
static CPAccessResult sel2_access(CPUARMState *env, const ARMCPRegInfo *ri,
488
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
489
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 6, .opc2 = 2,
490
.access = PL2_RW, .accessfn = sel2_access,
491
.fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
492
- REGINFO_SENTINEL
493
};
494
495
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
496
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
497
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5,
498
.access = PL3_W, .type = ARM_CP_NO_RAW,
499
.writefn = tlbi_aa64_vae3_write },
500
- REGINFO_SENTINEL
501
};
502
503
#ifndef CONFIG_USER_ONLY
504
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
505
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
506
.access = PL1_RW, .accessfn = access_tda,
507
.type = ARM_CP_NOP },
508
- REGINFO_SENTINEL
509
};
510
511
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
512
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
513
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
514
{ .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
515
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
516
- REGINFO_SENTINEL
517
};
518
519
/* Return the exception level to which exceptions should be taken
520
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
521
.fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]),
522
.writefn = dbgbcr_write, .raw_writefn = raw_write
523
},
524
- REGINFO_SENTINEL
525
};
526
define_arm_cp_regs(cpu, dbgregs);
527
}
528
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
529
.fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]),
530
.writefn = dbgwcr_write, .raw_writefn = raw_write
531
},
532
- REGINFO_SENTINEL
533
};
534
define_arm_cp_regs(cpu, dbgregs);
535
}
536
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
537
.type = ARM_CP_IO,
538
.readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
539
.raw_writefn = pmevtyper_rawwrite },
540
- REGINFO_SENTINEL
541
};
542
define_arm_cp_regs(cpu, pmev_regs);
543
g_free(pmevcntr_name);
544
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
545
.cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 5,
546
.access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
547
.resetvalue = extract64(cpu->pmceid1, 32, 32) },
548
- REGINFO_SENTINEL
549
};
550
define_arm_cp_regs(cpu, v81_pmu_regs);
551
}
552
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lor_reginfo[] = {
553
.opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
554
.access = PL1_R, .accessfn = access_lor_ns,
555
.type = ARM_CP_CONST, .resetvalue = 0 },
556
- REGINFO_SENTINEL
557
};
558
559
#ifdef TARGET_AARCH64
560
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pauth_reginfo[] = {
561
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 1, .opc2 = 3,
562
.access = PL1_RW, .accessfn = access_pauth,
563
.fieldoffset = offsetof(CPUARMState, keys.apib.hi) },
564
- REGINFO_SENTINEL
565
};
566
567
static const ARMCPRegInfo tlbirange_reginfo[] = {
568
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
569
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 5,
570
.access = PL3_W, .type = ARM_CP_NO_RAW,
571
.writefn = tlbi_aa64_rvae3_write },
572
- REGINFO_SENTINEL
573
};
574
575
static const ARMCPRegInfo tlbios_reginfo[] = {
576
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = {
577
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5,
578
.access = PL3_W, .type = ARM_CP_NO_RAW,
579
.writefn = tlbi_aa64_vae3is_write },
580
- REGINFO_SENTINEL
581
};
582
583
static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
584
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo rndr_reginfo[] = {
585
.type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO,
586
.opc0 = 3, .opc1 = 3, .crn = 2, .crm = 4, .opc2 = 1,
587
.access = PL0_R, .readfn = rndr_readfn },
588
- REGINFO_SENTINEL
589
};
590
591
#ifndef CONFIG_USER_ONLY
592
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpop_reg[] = {
593
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 1,
594
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
595
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
596
- REGINFO_SENTINEL
597
};
598
599
static const ARMCPRegInfo dcpodp_reg[] = {
600
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpodp_reg[] = {
601
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 1,
602
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
603
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
604
- REGINFO_SENTINEL
605
};
606
#endif /*CONFIG_USER_ONLY*/
607
608
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_reginfo[] = {
609
{ .name = "DC_CIGDSW", .state = ARM_CP_STATE_AA64,
610
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 6,
611
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
612
- REGINFO_SENTINEL
613
};
614
615
static const ARMCPRegInfo mte_tco_ro_reginfo[] = {
616
{ .name = "TCO", .state = ARM_CP_STATE_AA64,
617
.opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
618
.type = ARM_CP_CONST, .access = PL0_RW, },
619
- REGINFO_SENTINEL
620
};
621
622
static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
623
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
624
.accessfn = aa64_zva_access,
625
#endif
626
},
627
- REGINFO_SENTINEL
628
};
629
630
#endif
631
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo predinv_reginfo[] = {
632
{ .name = "CPPRCTX", .state = ARM_CP_STATE_AA32,
633
.cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 7,
634
.type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
635
- REGINFO_SENTINEL
636
};
637
638
static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri)
639
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ccsidr2_reginfo[] = {
640
.access = PL1_R,
641
.accessfn = access_aa64_tid2,
642
.readfn = ccsidr2_read, .type = ARM_CP_NO_RAW },
643
- REGINFO_SENTINEL
644
};
645
646
static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
647
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo jazelle_regs[] = {
648
.cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
649
.accessfn = access_joscr_jmcr,
650
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
651
- REGINFO_SENTINEL
652
};
653
654
static const ARMCPRegInfo vhe_reginfo[] = {
655
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
656
.access = PL2_RW, .accessfn = e2h_access,
657
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
658
#endif
659
- REGINFO_SENTINEL
660
};
661
662
#ifndef CONFIG_USER_ONLY
663
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1e1_reginfo[] = {
664
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
665
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
666
.writefn = ats_write64 },
667
- REGINFO_SENTINEL
668
};
669
670
static const ARMCPRegInfo ats1cp_reginfo[] = {
671
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1cp_reginfo[] = {
672
.cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
673
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
674
.writefn = ats_write },
675
- REGINFO_SENTINEL
676
};
677
#endif
678
679
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
680
.cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
681
.access = PL2_RW, .type = ARM_CP_CONST,
682
.resetvalue = 0 },
683
- REGINFO_SENTINEL
684
};
685
686
void register_cp_regs_for_features(ARMCPU *cpu)
687
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
688
.access = PL1_R, .type = ARM_CP_CONST,
689
.accessfn = access_aa32_tid3,
690
.resetvalue = cpu->isar.id_isar6 },
691
- REGINFO_SENTINEL
692
};
693
define_arm_cp_regs(cpu, v6_idregs);
694
define_arm_cp_regs(cpu, v6_cp_reginfo);
695
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
696
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 7,
697
.access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
698
.resetvalue = cpu->pmceid1 },
699
- REGINFO_SENTINEL
700
};
701
#ifdef CONFIG_USER_ONLY
702
ARMCPRegUserSpaceInfo v8_user_idregs[] = {
703
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
704
.exported_bits = 0x000000f0ffffffff },
705
{ .name = "ID_AA64ISAR*_EL1_RESERVED",
706
.is_glob = true },
707
- REGUSERINFO_SENTINEL
708
};
709
modify_arm_cp_regs(v8_idregs, v8_user_idregs);
710
#endif
711
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
712
.access = PL2_RW,
713
.resetvalue = vmpidr_def,
714
.fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
715
- REGINFO_SENTINEL
716
};
717
define_arm_cp_regs(cpu, vpidr_regs);
718
define_arm_cp_regs(cpu, el2_cp_reginfo);
719
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
720
.access = PL2_RW, .accessfn = access_el3_aa32ns,
721
.type = ARM_CP_NO_RAW,
722
.writefn = arm_cp_write_ignore, .readfn = mpidr_read },
723
- REGINFO_SENTINEL
724
};
725
define_arm_cp_regs(cpu, vpidr_regs);
726
define_arm_cp_regs(cpu, el3_no_el2_cp_reginfo);
727
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
728
.raw_writefn = raw_write, .writefn = sctlr_write,
729
.fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]),
730
.resetvalue = cpu->reset_sctlr },
731
- REGINFO_SENTINEL
732
};
733
734
define_arm_cp_regs(cpu, el3_regs);
735
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
736
{ .name = "DUMMY",
737
.cp = 15, .crn = 0, .crm = 7, .opc1 = 0, .opc2 = CP_ANY,
738
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
739
- REGINFO_SENTINEL
740
};
741
ARMCPRegInfo id_v8_midr_cp_reginfo[] = {
742
{ .name = "MIDR_EL1", .state = ARM_CP_STATE_BOTH,
743
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
744
.access = PL1_R,
745
.accessfn = access_aa64_tid1,
746
.type = ARM_CP_CONST, .resetvalue = cpu->revidr },
747
- REGINFO_SENTINEL
748
};
749
ARMCPRegInfo id_cp_reginfo[] = {
750
/* These are common to v8 and pre-v8 */
751
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
752
.access = PL1_R,
753
.accessfn = access_aa32_tid1,
754
.type = ARM_CP_CONST, .resetvalue = 0 },
755
- REGINFO_SENTINEL
756
};
757
/* TLBTR is specific to VMSA */
758
ARMCPRegInfo id_tlbtr_reginfo = {
759
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
760
{ .name = "MIDR_EL1",
761
.exported_bits = 0x00000000ffffffff },
762
{ .name = "REVIDR_EL1" },
763
- REGUSERINFO_SENTINEL
764
};
765
modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_reginfo);
766
#endif
767
if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
768
arm_feature(env, ARM_FEATURE_STRONGARM)) {
769
- ARMCPRegInfo *r;
770
+ size_t i;
771
/* Register the blanket "writes ignored" value first to cover the
772
* whole space. Then update the specific ID registers to allow write
773
* access, so that they ignore writes rather than causing them to
774
* UNDEF.
775
*/
776
define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
777
- for (r = id_pre_v8_midr_cp_reginfo;
778
- r->type != ARM_CP_SENTINEL; r++) {
779
- r->access = PL1_RW;
780
+ for (i = 0; i < ARRAY_SIZE(id_pre_v8_midr_cp_reginfo); ++i) {
781
+ id_pre_v8_midr_cp_reginfo[i].access = PL1_RW;
782
}
783
- for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
784
- r->access = PL1_RW;
785
+ for (i = 0; i < ARRAY_SIZE(id_cp_reginfo); ++i) {
786
+ id_cp_reginfo[i].access = PL1_RW;
787
}
788
id_mpuir_reginfo.access = PL1_RW;
789
id_tlbtr_reginfo.access = PL1_RW;
790
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
791
{ .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
792
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
793
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
794
- REGINFO_SENTINEL
795
};
796
#ifdef CONFIG_USER_ONLY
797
ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
798
{ .name = "MPIDR_EL1",
799
.fixed_bits = 0x0000000080000000 },
800
- REGUSERINFO_SENTINEL
801
};
802
modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
803
#endif
804
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
805
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 1,
806
.access = PL3_RW, .type = ARM_CP_CONST,
807
.resetvalue = 0 },
808
- REGINFO_SENTINEL
809
};
810
define_arm_cp_regs(cpu, auxcr_reginfo);
811
if (cpu_isar_feature(aa32_ac2, cpu)) {
812
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
813
.type = ARM_CP_CONST,
814
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 0,
815
.access = PL1_R, .resetvalue = cpu->reset_cbar },
816
- REGINFO_SENTINEL
817
};
818
/* We don't implement a r/w 64 bit CBAR currently */
819
assert(arm_feature(env, ARM_FEATURE_CBAR_RO));
820
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
821
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
822
offsetof(CPUARMState, cp15.vbar_ns) },
823
.resetvalue = 0 },
824
- REGINFO_SENTINEL
825
};
826
define_arm_cp_regs(cpu, vbar_cp_reginfo);
827
}
828
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
829
r->writefn);
830
}
831
}
832
- /* Bad type field probably means missing sentinel at end of reg list */
833
- assert(cptype_valid(r->type));
834
+
835
for (crm = crmmin; crm <= crmmax; crm++) {
836
for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
837
for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
838
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
27
}
839
}
28
}
840
}
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
841
30
case USB_ANALOG_DIGPROG:
842
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
31
return "USB_ANALOG_DIGPROG";
843
- const ARMCPRegInfo *regs, void *opaque)
32
default:
844
+/* Define a whole list of registers */
33
- sprintf(unknown, "%d ?", reg);
845
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
34
+ sprintf(unknown, "%u ?", reg);
846
+ void *opaque, size_t len)
35
return unknown;
847
{
848
- /* Define a whole list of registers */
849
- const ARMCPRegInfo *r;
850
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
851
- define_one_arm_cp_reg_with_opaque(cpu, r, opaque);
852
+ size_t i;
853
+ for (i = 0; i < len; ++i) {
854
+ define_one_arm_cp_reg_with_opaque(cpu, regs + i, opaque);
36
}
855
}
37
}
856
}
38
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
857
39
freq *= 20;
858
@@ -XXX,XX +XXX,XX @@ void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
40
}
859
* user-space cannot alter any values and dynamic values pertaining to
41
860
* execution state are hidden from user space view anyway.
42
- DPRINTF("freq = %d\n", (uint32_t)freq);
861
*/
43
+ DPRINTF("freq = %u\n", (uint32_t)freq);
862
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods)
44
863
+void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
45
return freq;
864
+ const ARMCPRegUserSpaceInfo *mods,
46
}
865
+ size_t mods_len)
47
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
866
{
48
freq = imx6_analog_get_pll2_clk(dev) * 18
867
- const ARMCPRegUserSpaceInfo *m;
49
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
868
- ARMCPRegInfo *r;
50
869
-
51
- DPRINTF("freq = %d\n", (uint32_t)freq);
870
- for (m = mods; m->name; m++) {
52
+ DPRINTF("freq = %u\n", (uint32_t)freq);
871
+ for (size_t mi = 0; mi < mods_len; ++mi) {
53
872
+ const ARMCPRegUserSpaceInfo *m = mods + mi;
54
return freq;
873
GPatternSpec *pat = NULL;
55
}
874
+
56
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
875
if (m->is_glob) {
57
freq = imx6_analog_get_pll2_clk(dev) * 18
876
pat = g_pattern_spec_new(m->name);
58
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
877
}
59
878
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
60
- DPRINTF("freq = %d\n", (uint32_t)freq);
879
+ for (size_t ri = 0; ri < regs_len; ++ri) {
61
+ DPRINTF("freq = %u\n", (uint32_t)freq);
880
+ ARMCPRegInfo *r = regs + ri;
62
881
+
63
return freq;
882
if (pat && g_pattern_match_string(pat, r->name)) {
64
}
883
r->type = ARM_CP_CONST;
65
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
884
r->access = PL0U_R;
66
break;
67
}
68
69
- DPRINTF("freq = %d\n", (uint32_t)freq);
70
+ DPRINTF("freq = %u\n", (uint32_t)freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev)
75
freq = imx6_analog_get_periph_clk(dev)
76
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF));
77
78
- DPRINTF("freq = %d\n", (uint32_t)freq);
79
+ DPRINTF("freq = %u\n", (uint32_t)freq);
80
81
return freq;
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev)
84
freq = imx6_ccm_get_ahb_clk(dev)
85
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));
86
87
- DPRINTF("freq = %d\n", (uint32_t)freq);
88
+ DPRINTF("freq = %u\n", (uint32_t)freq);
89
90
return freq;
91
}
92
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
93
freq = imx6_ccm_get_ipg_clk(dev)
94
/ (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF));
95
96
- DPRINTF("freq = %d\n", (uint32_t)freq);
97
+ DPRINTF("freq = %u\n", (uint32_t)freq);
98
99
return freq;
100
}
101
@@ -XXX,XX +XXX,XX @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
102
break;
103
}
104
105
- DPRINTF("Clock = %d) = %d\n", clock, freq);
106
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
107
108
return freq;
109
}
110
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/hw/misc/imx6_src.c
113
+++ b/hw/misc/imx6_src.c
114
@@ -XXX,XX +XXX,XX @@ static const char *imx6_src_reg_name(uint32_t reg)
115
case SRC_GPR10:
116
return "SRC_GPR10";
117
default:
118
- sprintf(unknown, "%d ?", reg);
119
+ sprintf(unknown, "%u ?", reg);
120
return unknown;
121
}
122
}
123
--
885
--
124
2.20.1
886
2.25.1
125
887
126
888
diff view generated by jsdifflib
1
In commit 077d7449100d824a4 we added code to handle the v8M
1
From: Richard Henderson <richard.henderson@linaro.org>
2
requirement that returns from NMI or HardFault forcibly deactivate
3
those exceptions regardless of what interrupt the guest is trying to
4
deactivate. Unfortunately this broke the handling of the "illegal
5
exception return because the returning exception number is not
6
active" check for those cases. In the pseudocode this test is done
7
on the exception the guest asks to return from, but because our
8
implementation was doing this in armv7m_nvic_complete_irq() after the
9
new "deactivate NMI/HardFault regardless" code we ended up doing the
10
test on the VecInfo for that exception instead, which usually meant
11
failing to raise the illegal exception return fault.
12
2
13
In the case for "configurable exception targeting the opposite
3
These particular data structures are not modified at runtime.
14
security state" we detected the illegal-return case but went ahead
15
and deactivated the VecInfo anyway, which is wrong because that is
16
the VecInfo for the other security state.
17
4
18
Rearrange the code so that we first identify the illegal return
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
19
cases, then see if we really need to deactivate NMI or HardFault
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
instead, and finally do the deactivation.
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220501055028.646596-5-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 16 ++++++++--------
12
1 file changed, 8 insertions(+), 8 deletions(-)
21
13
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20201119215617.29887-25-peter.maydell@linaro.org
25
---
26
hw/intc/armv7m_nvic.c | 59 +++++++++++++++++++++++--------------------
27
1 file changed, 32 insertions(+), 27 deletions(-)
28
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
30
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/armv7m_nvic.c
16
--- a/target/arm/helper.c
32
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/target/arm/helper.c
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
18
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
34
{
19
.resetvalue = cpu->pmceid1 },
35
NVICState *s = (NVICState *)opaque;
20
};
36
VecInfo *vec = NULL;
21
#ifdef CONFIG_USER_ONLY
37
- int ret;
22
- ARMCPRegUserSpaceInfo v8_user_idregs[] = {
38
+ int ret = 0;
23
+ static const ARMCPRegUserSpaceInfo v8_user_idregs[] = {
39
24
{ .name = "ID_AA64PFR0_EL1",
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
25
.exported_bits = 0x000f000f00ff0000,
41
26
.fixed_bits = 0x0000000000000011 },
42
+ trace_nvic_complete_irq(irq, secure);
27
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
43
+
28
*/
44
+ if (secure && exc_is_banked(irq)) {
29
if (arm_feature(env, ARM_FEATURE_EL3)) {
45
+ vec = &s->sec_vectors[irq];
30
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
46
+ } else {
31
- ARMCPRegInfo nsacr = {
47
+ vec = &s->vectors[irq];
32
+ static const ARMCPRegInfo nsacr = {
48
+ }
33
.name = "NSACR", .type = ARM_CP_CONST,
49
+
34
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
50
+ /*
35
.access = PL1_RW, .accessfn = nsacr_access,
51
+ * Identify illegal exception return cases. We can't immediately
36
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
52
+ * return at this point because we still need to deactivate
37
};
53
+ * (either this exception or NMI/HardFault) first.
38
define_one_arm_cp_reg(cpu, &nsacr);
54
+ */
39
} else {
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
40
- ARMCPRegInfo nsacr = {
56
+ /*
41
+ static const ARMCPRegInfo nsacr = {
57
+ * Return from a configurable exception targeting the opposite
42
.name = "NSACR",
58
+ * security state from the one we're trying to complete it for.
43
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
59
+ * Clear vec because it's not really the VecInfo for this
44
.access = PL3_RW | PL1_R,
60
+ * (irq, secstate) so we mustn't deactivate it.
45
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
61
+ */
46
}
62
+ ret = -1;
47
} else {
63
+ vec = NULL;
48
if (arm_feature(env, ARM_FEATURE_V8)) {
64
+ } else if (!vec->active) {
49
- ARMCPRegInfo nsacr = {
65
+ /* Return from an inactive interrupt */
50
+ static const ARMCPRegInfo nsacr = {
66
+ ret = -1;
51
.name = "NSACR", .type = ARM_CP_CONST,
67
+ } else {
52
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
53
.access = PL1_R,
69
+ ret = nvic_rettobase(s);
54
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
70
+ }
55
.access = PL1_R, .type = ARM_CP_CONST,
71
+
56
.resetvalue = cpu->pmsav7_dregion << 8
72
/*
57
};
73
* For negative priorities, v8M will forcibly deactivate the appropriate
58
- ARMCPRegInfo crn0_wi_reginfo = {
74
* NMI or HardFault regardless of what interrupt we're being asked to
59
+ static const ARMCPRegInfo crn0_wi_reginfo = {
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
60
.name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
61
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
62
.type = ARM_CP_NOP | ARM_CP_OVERRIDE
63
};
64
#ifdef CONFIG_USER_ONLY
65
- ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
66
+ static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
67
{ .name = "MIDR_EL1",
68
.exported_bits = 0x00000000ffffffff },
69
{ .name = "REVIDR_EL1" },
70
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
71
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
72
};
73
#ifdef CONFIG_USER_ONLY
74
- ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
75
+ static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
76
{ .name = "MPIDR_EL1",
77
.fixed_bits = 0x0000000080000000 },
78
};
79
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
76
}
80
}
77
81
78
if (!vec) {
82
if (arm_feature(env, ARM_FEATURE_VBAR)) {
79
- if (secure && exc_is_banked(irq)) {
83
- ARMCPRegInfo vbar_cp_reginfo[] = {
80
- vec = &s->sec_vectors[irq];
84
+ static const ARMCPRegInfo vbar_cp_reginfo[] = {
81
- } else {
85
{ .name = "VBAR", .state = ARM_CP_STATE_BOTH,
82
- vec = &s->vectors[irq];
86
.opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
83
- }
87
.access = PL1_RW, .writefn = vbar_write,
84
- }
85
-
86
- trace_nvic_complete_irq(irq, secure);
87
-
88
- if (!vec->active) {
89
- /* Tell the caller this was an illegal exception return */
90
- return -1;
91
- }
92
-
93
- /*
94
- * If this is a configurable exception and it is currently
95
- * targeting the opposite security state from the one we're trying
96
- * to complete it for, this counts as an illegal exception return.
97
- * We still need to deactivate whatever vector the logic above has
98
- * selected, though, as it might not be the same as the one for the
99
- * requested exception number.
100
- */
101
- if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
102
- ret = -1;
103
- } else {
104
- ret = nvic_rettobase(s);
105
+ return ret;
106
}
107
108
vec->active = 0;
109
--
88
--
110
2.20.1
89
2.25.1
111
90
112
91
diff view generated by jsdifflib
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the general-purpose registers and APSR. Implement this.
2
3
3
Instead of defining ARM_CP_FLAG_MASK to remove flags,
4
The encoding is a subset of the LDMIA T2 encoding, using what would
4
define ARM_CP_SPECIAL_MASK to isolate special cases.
5
be Rn=0b1111 (which UNDEFs for LDMIA).
5
Sort the specials to the low bits. Use an enum.
6
6
7
Split the large comment block so as to document each
8
value separately.
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20220501055028.646596-6-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
10
---
14
---
11
target/arm/t32.decode | 6 +++++-
15
target/arm/cpregs.h | 130 +++++++++++++++++++++++--------------
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
16
target/arm/cpu.c | 4 +-
13
2 files changed, 43 insertions(+), 1 deletion(-)
17
target/arm/helper.c | 4 +-
14
18
target/arm/translate-a64.c | 6 +-
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
19
target/arm/translate.c | 6 +-
16
index XXXXXXX..XXXXXXX 100644
20
5 files changed, 92 insertions(+), 58 deletions(-)
17
--- a/target/arm/t32.decode
21
18
+++ b/target/arm/t32.decode
22
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
23
index XXXXXXX..XXXXXXX 100644
20
24
--- a/target/arm/cpregs.h
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
25
+++ b/target/arm/cpregs.h
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
26
@@ -XXX,XX +XXX,XX @@
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
27
#define TARGET_ARM_CPREGS_H
24
+{
28
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
29
/*
26
+ CLRM 1110 1000 1001 1111 list:16
30
- * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
31
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
28
+}
32
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
33
- * TCG can assume the value to be constant (ie load at translate time)
30
34
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
31
&rfe !extern rn w pu
35
- * indicates that the TB should not be ended after a write to this register
36
- * (the default is that the TB ends after cp writes). OVERRIDE permits
37
- * a register definition to override a previous definition for the
38
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
39
- * old must have the OVERRIDE bit set.
40
- * ALIAS indicates that this register is an alias view of some underlying
41
- * state which is also visible via another register, and that the other
42
- * register is handling migration and reset; registers marked ALIAS will not be
43
- * migrated but may have their state set by syncing of register state from KVM.
44
- * NO_RAW indicates that this register has no underlying state and does not
45
- * support raw access for state saving/loading; it will not be used for either
46
- * migration or KVM state synchronization. (Typically this is for "registers"
47
- * which are actually used as instructions for cache maintenance and so on.)
48
- * IO indicates that this register does I/O and therefore its accesses
49
- * need to be marked with gen_io_start() and also end the TB. In particular,
50
- * registers which implement clocks or timers require this.
51
- * RAISES_EXC is for when the read or write hook might raise an exception;
52
- * the generated code will synchronize the CPU state before calling the hook
53
- * so that it is safe for the hook to call raise_exception().
54
- * NEWEL is for writes to registers that might change the exception
55
- * level - typically on older ARM chips. For those cases we need to
56
- * re-read the new el when recomputing the translation flags.
57
+ * ARMCPRegInfo type field bits:
58
*/
59
-#define ARM_CP_SPECIAL 0x0001
60
-#define ARM_CP_CONST 0x0002
61
-#define ARM_CP_64BIT 0x0004
62
-#define ARM_CP_SUPPRESS_TB_END 0x0008
63
-#define ARM_CP_OVERRIDE 0x0010
64
-#define ARM_CP_ALIAS 0x0020
65
-#define ARM_CP_IO 0x0040
66
-#define ARM_CP_NO_RAW 0x0080
67
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
68
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
69
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
70
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
71
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
72
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
73
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
74
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
75
-#define ARM_CP_FPU 0x1000
76
-#define ARM_CP_SVE 0x2000
77
-#define ARM_CP_NO_GDB 0x4000
78
-#define ARM_CP_RAISES_EXC 0x8000
79
-#define ARM_CP_NEWEL 0x10000
80
-/* Mask of only the flag bits in a type field */
81
-#define ARM_CP_FLAG_MASK 0x1f0ff
82
+enum {
83
+ /*
84
+ * Register must be handled specially during translation.
85
+ * The method is one of the values below:
86
+ */
87
+ ARM_CP_SPECIAL_MASK = 0x000f,
88
+ /* Special: no change to PE state: writes ignored, reads ignored. */
89
+ ARM_CP_NOP = 0x0001,
90
+ /* Special: sysreg is WFI, for v5 and v6. */
91
+ ARM_CP_WFI = 0x0002,
92
+ /* Special: sysreg is NZCV. */
93
+ ARM_CP_NZCV = 0x0003,
94
+ /* Special: sysreg is CURRENTEL. */
95
+ ARM_CP_CURRENTEL = 0x0004,
96
+ /* Special: sysreg is DC ZVA or similar. */
97
+ ARM_CP_DC_ZVA = 0x0005,
98
+ ARM_CP_DC_GVA = 0x0006,
99
+ ARM_CP_DC_GZVA = 0x0007,
100
+
101
+ /* Flag: reads produce resetvalue; writes ignored. */
102
+ ARM_CP_CONST = 1 << 4,
103
+ /* Flag: For ARM_CP_STATE_AA32, sysreg is 64-bit. */
104
+ ARM_CP_64BIT = 1 << 5,
105
+ /*
106
+ * Flag: TB should not be ended after a write to this register
107
+ * (the default is that the TB ends after cp writes).
108
+ */
109
+ ARM_CP_SUPPRESS_TB_END = 1 << 6,
110
+ /*
111
+ * Flag: Permit a register definition to override a previous definition
112
+ * for the same (cp, is64, crn, crm, opc1, opc2) tuple: either the new
113
+ * or the old must have the ARM_CP_OVERRIDE bit set.
114
+ */
115
+ ARM_CP_OVERRIDE = 1 << 7,
116
+ /*
117
+ * Flag: Register is an alias view of some underlying state which is also
118
+ * visible via another register, and that the other register is handling
119
+ * migration and reset; registers marked ARM_CP_ALIAS will not be migrated
120
+ * but may have their state set by syncing of register state from KVM.
121
+ */
122
+ ARM_CP_ALIAS = 1 << 8,
123
+ /*
124
+ * Flag: Register does I/O and therefore its accesses need to be marked
125
+ * with gen_io_start() and also end the TB. In particular, registers which
126
+ * implement clocks or timers require this.
127
+ */
128
+ ARM_CP_IO = 1 << 9,
129
+ /*
130
+ * Flag: Register has no underlying state and does not support raw access
131
+ * for state saving/loading; it will not be used for either migration or
132
+ * KVM state synchronization. Typically this is for "registers" which are
133
+ * actually used as instructions for cache maintenance and so on.
134
+ */
135
+ ARM_CP_NO_RAW = 1 << 10,
136
+ /*
137
+ * Flag: The read or write hook might raise an exception; the generated
138
+ * code will synchronize the CPU state before calling the hook so that it
139
+ * is safe for the hook to call raise_exception().
140
+ */
141
+ ARM_CP_RAISES_EXC = 1 << 11,
142
+ /*
143
+ * Flag: Writes to the sysreg might change the exception level - typically
144
+ * on older ARM chips. For those cases we need to re-read the new el when
145
+ * recomputing the translation flags.
146
+ */
147
+ ARM_CP_NEWEL = 1 << 12,
148
+ /*
149
+ * Flag: Access check for this sysreg is identical to accessing FPU state
150
+ * from an instruction: use translation fp_access_check().
151
+ */
152
+ ARM_CP_FPU = 1 << 13,
153
+ /*
154
+ * Flag: Access check for this sysreg is identical to accessing SVE state
155
+ * from an instruction: use translation sve_access_check().
156
+ */
157
+ ARM_CP_SVE = 1 << 14,
158
+ /* Flag: Do not expose in gdb sysreg xml. */
159
+ ARM_CP_NO_GDB = 1 << 15,
160
+};
161
162
/*
163
* Valid values for ARMCPRegInfo state field, indicating which of
164
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/cpu.c
167
+++ b/target/arm/cpu.c
168
@@ -XXX,XX +XXX,XX @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
169
ARMCPRegInfo *ri = value;
170
ARMCPU *cpu = opaque;
171
172
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS)) {
173
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS)) {
174
return;
175
}
176
177
@@ -XXX,XX +XXX,XX @@ static void cp_reg_check_reset(gpointer key, gpointer value, gpointer opaque)
178
ARMCPU *cpu = opaque;
179
uint64_t oldvalue, newvalue;
180
181
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
182
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
183
return;
184
}
185
186
diff --git a/target/arm/helper.c b/target/arm/helper.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/target/arm/helper.c
189
+++ b/target/arm/helper.c
190
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
191
* multiple times. Special registers (ie NOP/WFI) are
192
* never migratable and not even raw-accessible.
193
*/
194
- if ((r->type & ARM_CP_SPECIAL)) {
195
+ if (r->type & ARM_CP_SPECIAL_MASK) {
196
r2->type |= ARM_CP_NO_RAW;
197
}
198
if (((r->crm == CP_ANY) && crm != 0) ||
199
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
200
/* Check that the register definition has enough info to handle
201
* reads and writes if they are permitted.
202
*/
203
- if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
204
+ if (!(r->type & (ARM_CP_SPECIAL_MASK | ARM_CP_CONST))) {
205
if (r->access & PL3_R) {
206
assert((r->fieldoffset ||
207
(r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
208
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/target/arm/translate-a64.c
211
+++ b/target/arm/translate-a64.c
212
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
213
}
214
215
/* Handle special cases first */
216
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
217
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
218
+ case 0:
219
+ break;
220
case ARM_CP_NOP:
221
return;
222
case ARM_CP_NZCV:
223
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
224
}
225
return;
226
default:
227
- break;
228
+ g_assert_not_reached();
229
}
230
if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
231
return;
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
232
diff --git a/target/arm/translate.c b/target/arm/translate.c
33
index XXXXXXX..XXXXXXX 100644
233
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate.c
234
--- a/target/arm/translate.c
35
+++ b/target/arm/translate.c
235
+++ b/target/arm/translate.c
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
236
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
37
return do_ldm(s, a, 1);
237
}
38
}
238
39
239
/* Handle special cases first */
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
240
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
41
+{
241
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
42
+ int i;
242
+ case 0:
43
+ TCGv_i32 zero;
243
+ break;
44
+
244
case ARM_CP_NOP:
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
245
return;
46
+ return false;
246
case ARM_CP_WFI:
47
+ }
247
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
48
+
248
s->base.is_jmp = DISAS_WFI;
49
+ if (extract32(a->list, 13, 1)) {
249
return;
50
+ return false;
250
default:
51
+ }
251
- break;
52
+
252
+ g_assert_not_reached();
53
+ if (!a->list) {
253
}
54
+ /* UNPREDICTABLE; we choose to UNDEF */
254
55
+ return false;
255
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
56
+ }
57
+
58
+ zero = tcg_const_i32(0);
59
+ for (i = 0; i < 15; i++) {
60
+ if (extract32(a->list, i, 1)) {
61
+ /* Clear R[i] */
62
+ tcg_gen_mov_i32(cpu_R[i], zero);
63
+ }
64
+ }
65
+ if (extract32(a->list, 15, 1)) {
66
+ /*
67
+ * Clear APSR (by calling the MSR helper with the same argument
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
69
+ */
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
72
+ tcg_temp_free_i32(maskreg);
73
+ }
74
+ tcg_temp_free_i32(zero);
75
+ return true;
76
+}
77
+
78
/*
79
* Branch, branch with link
80
*/
81
--
256
--
82
2.20.1
257
2.25.1
83
84
diff view generated by jsdifflib
1
The constant-expander functions like negate, plus_2, etc, are
1
From: Richard Henderson <richard.henderson@linaro.org>
2
generally useful; move them up in translate.c so we can use them in
3
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
4
2
3
Standardize on g_assert_not_reached() for "should not happen".
4
Retain abort() when preceeded by fprintf or error_report.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-7-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-9-peter.maydell@linaro.org
8
---
10
---
9
target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
11
target/arm/helper.c | 7 +++----
10
1 file changed, 25 insertions(+), 21 deletions(-)
12
target/arm/hvf/hvf.c | 2 +-
13
target/arm/kvm-stub.c | 4 ++--
14
target/arm/kvm.c | 4 ++--
15
target/arm/machine.c | 4 ++--
16
target/arm/translate-a64.c | 4 ++--
17
target/arm/translate-neon.c | 2 +-
18
target/arm/translate.c | 4 ++--
19
8 files changed, 15 insertions(+), 16 deletions(-)
11
20
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
26
break;
27
default:
28
/* broken reginfo with out-of-range opc1 */
29
- assert(false);
30
- break;
31
+ g_assert_not_reached();
32
}
33
/* assert our permissions are not too lax (stricter is fine) */
34
assert((r->access & ~mask) == 0);
35
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
36
break;
37
default:
38
/* Never happens, but compiler isn't smart enough to tell. */
39
- abort();
40
+ g_assert_not_reached();
41
}
42
}
43
*prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
44
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
45
break;
46
default:
47
/* Never happens, but compiler isn't smart enough to tell. */
48
- abort();
49
+ g_assert_not_reached();
50
}
51
}
52
if (domain_prot == 3) {
53
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/hvf/hvf.c
56
+++ b/target/arm/hvf/hvf.c
57
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
58
/* we got kicked, no exit to process */
59
return 0;
60
default:
61
- assert(0);
62
+ g_assert_not_reached();
63
}
64
65
hvf_sync_vtimer(cpu);
66
diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/kvm-stub.c
69
+++ b/target/arm/kvm-stub.c
70
@@ -XXX,XX +XXX,XX @@
71
72
bool write_kvmstate_to_list(ARMCPU *cpu)
73
{
74
- abort();
75
+ g_assert_not_reached();
76
}
77
78
bool write_list_to_kvmstate(ARMCPU *cpu, int level)
79
{
80
- abort();
81
+ g_assert_not_reached();
82
}
83
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/kvm.c
86
+++ b/target/arm/kvm.c
87
@@ -XXX,XX +XXX,XX @@ bool write_kvmstate_to_list(ARMCPU *cpu)
88
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
89
break;
90
default:
91
- abort();
92
+ g_assert_not_reached();
93
}
94
if (ret) {
95
ok = false;
96
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
97
r.addr = (uintptr_t)(cpu->cpreg_values + i);
98
break;
99
default:
100
- abort();
101
+ g_assert_not_reached();
102
}
103
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
104
if (ret) {
105
diff --git a/target/arm/machine.c b/target/arm/machine.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/machine.c
108
+++ b/target/arm/machine.c
109
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
110
if (kvm_enabled()) {
111
if (!write_kvmstate_to_list(cpu)) {
112
/* This should never fail */
113
- abort();
114
+ g_assert_not_reached();
115
}
116
117
/*
118
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
119
} else {
120
if (!write_cpustate_to_list(cpu, false)) {
121
/* This should never fail. */
122
- abort();
123
+ g_assert_not_reached();
124
}
125
}
126
127
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/target/arm/translate-a64.c
130
+++ b/target/arm/translate-a64.c
131
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
132
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
133
break;
134
default:
135
- abort();
136
+ g_assert_not_reached();
137
}
138
139
write_fp_sreg(s, rd, tcg_res);
140
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
141
break;
142
}
143
default:
144
- abort();
145
+ g_assert_not_reached();
146
}
147
}
148
149
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/target/arm/translate-neon.c
152
+++ b/target/arm/translate-neon.c
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
154
}
155
break;
156
default:
157
- abort();
158
+ g_assert_not_reached();
159
}
160
if ((vd + a->stride * (nregs - 1)) > 31) {
161
/*
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
162
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
index XXXXXXX..XXXXXXX 100644
163
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate.c
164
--- a/target/arm/translate.c
15
+++ b/target/arm/translate.c
165
+++ b/target/arm/translate.c
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
166
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
167
offset = 4;
168
break;
169
default:
170
- abort();
171
+ g_assert_not_reached();
17
}
172
}
18
}
173
tcg_gen_addi_i32(addr, addr, offset);
19
174
tmp = load_reg(s, 14);
20
+/*
175
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
21
+ * Constant expanders for the decoders.
176
offset = 0;
22
+ */
177
break;
23
+
178
default:
24
+static int negate(DisasContext *s, int x)
179
- abort();
25
+{
180
+ g_assert_not_reached();
26
+ return -x;
181
}
27
+}
182
tcg_gen_addi_i32(addr, addr, offset);
28
+
183
gen_helper_set_r13_banked(cpu_env, tcg_constant_i32(mode), addr);
29
+static int plus_2(DisasContext *s, int x)
30
+{
31
+ return x + 2;
32
+}
33
+
34
+static int times_2(DisasContext *s, int x)
35
+{
36
+ return x * 2;
37
+}
38
+
39
+static int times_4(DisasContext *s, int x)
40
+{
41
+ return x * 4;
42
+}
43
+
44
/* Flags for the disas_set_da_iss info argument:
45
* lower bits hold the Rt register number, higher bits are flags.
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void arm_skip_unless(DisasContext *s, uint32_t cond)
48
49
50
/*
51
- * Constant expanders for the decoders.
52
+ * Constant expanders used by T16/T32 decode
53
*/
54
55
-static int negate(DisasContext *s, int x)
56
-{
57
- return -x;
58
-}
59
-
60
-static int plus_2(DisasContext *s, int x)
61
-{
62
- return x + 2;
63
-}
64
-
65
-static int times_2(DisasContext *s, int x)
66
-{
67
- return x * 2;
68
-}
69
-
70
-static int times_4(DisasContext *s, int x)
71
-{
72
- return x * 4;
73
-}
74
-
75
/* Return only the rotation part of T32ExpandImm. */
76
static int t32_expandimm_rot(DisasContext *s, int x)
77
{
78
--
184
--
79
2.20.1
185
2.25.1
80
81
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
Create a typedef as well, and use it in ARMCPRegInfo.
4
argument of type "unsigned int".
4
This won't be perfect for debugging, but it'll nicely
5
display the most common cases.
5
6
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-8-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
hw/misc/imx31_ccm.c | 14 +++++++-------
12
target/arm/cpregs.h | 44 +++++++++++++++++++++++---------------------
13
hw/misc/imx_ccm.c | 4 ++--
13
target/arm/helper.c | 2 +-
14
2 files changed, 9 insertions(+), 9 deletions(-)
14
2 files changed, 24 insertions(+), 22 deletions(-)
15
15
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/imx31_ccm.c
18
--- a/target/arm/cpregs.h
19
+++ b/hw/misc/imx31_ccm.c
19
+++ b/target/arm/cpregs.h
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
20
@@ -XXX,XX +XXX,XX @@ enum {
21
case IMX31_CCM_PDR2_REG:
21
* described with these bits, then use a laxer set of restrictions, and
22
return "PDR2";
22
* do the more restrictive/complex check inside a helper function.
23
default:
23
*/
24
- sprintf(unknown, "[%d ?]", reg);
24
-#define PL3_R 0x80
25
+ sprintf(unknown, "[%u ?]", reg);
25
-#define PL3_W 0x40
26
return unknown;
26
-#define PL2_R (0x20 | PL3_R)
27
}
27
-#define PL2_W (0x10 | PL3_W)
28
}
28
-#define PL1_R (0x08 | PL2_R)
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
29
-#define PL1_W (0x04 | PL2_W)
30
freq = CKIH_FREQ;
30
-#define PL0_R (0x02 | PL1_R)
31
}
31
-#define PL0_W (0x01 | PL1_W)
32
32
+typedef enum {
33
- DPRINTF("freq = %d\n", freq);
33
+ PL3_R = 0x80,
34
+ DPRINTF("freq = %u\n", freq);
34
+ PL3_W = 0x40,
35
35
+ PL2_R = 0x20 | PL3_R,
36
return freq;
36
+ PL2_W = 0x10 | PL3_W,
37
}
37
+ PL1_R = 0x08 | PL2_R,
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
38
+ PL1_W = 0x04 | PL2_W,
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
39
+ PL0_R = 0x02 | PL1_R,
40
imx31_ccm_get_pll_ref_clk(dev));
40
+ PL0_W = 0x01 | PL1_W,
41
41
42
- DPRINTF("freq = %d\n", freq);
42
-/*
43
+ DPRINTF("freq = %u\n", freq);
43
- * For user-mode some registers are accessible to EL0 via a kernel
44
44
- * trap-and-emulate ABI. In this case we define the read permissions
45
return freq;
45
- * as actually being PL0_R. However some bits of any given register
46
}
46
- * may still be masked.
47
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
47
- */
48
freq = imx31_ccm_get_mpll_clk(dev);
48
+ /*
49
}
49
+ * For user-mode some registers are accessible to EL0 via a kernel
50
50
+ * trap-and-emulate ABI. In this case we define the read permissions
51
- DPRINTF("freq = %d\n", freq);
51
+ * as actually being PL0_R. However some bits of any given register
52
+ DPRINTF("freq = %u\n", freq);
52
+ * may still be masked.
53
53
+ */
54
return freq;
54
#ifdef CONFIG_USER_ONLY
55
}
55
-#define PL0U_R PL0_R
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
56
+ PL0U_R = PL0_R,
57
freq = imx31_ccm_get_mcu_main_clk(dev)
57
#else
58
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
58
-#define PL0U_R PL1_R
59
59
+ PL0U_R = PL1_R,
60
- DPRINTF("freq = %d\n", freq);
60
#endif
61
+ DPRINTF("freq = %u\n", freq);
61
62
62
-#define PL3_RW (PL3_R | PL3_W)
63
return freq;
63
-#define PL2_RW (PL2_R | PL2_W)
64
}
64
-#define PL1_RW (PL1_R | PL1_W)
65
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
65
-#define PL0_RW (PL0_R | PL0_W)
66
freq = imx31_ccm_get_hclk_clk(dev)
66
+ PL3_RW = PL3_R | PL3_W,
67
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
67
+ PL2_RW = PL2_R | PL2_W,
68
68
+ PL1_RW = PL1_R | PL1_W,
69
- DPRINTF("freq = %d\n", freq);
69
+ PL0_RW = PL0_R | PL0_W,
70
+ DPRINTF("freq = %u\n", freq);
70
+} CPAccessRights;
71
71
72
return freq;
72
typedef enum CPAccessResult {
73
}
73
/* Access is permitted */
74
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
74
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
75
break;
75
/* Register type: ARM_CP_* bits/values */
76
}
76
int type;
77
77
/* Access rights: PL*_[RW] */
78
- DPRINTF("Clock = %d) = %d\n", clock, freq);
78
- int access;
79
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
79
+ CPAccessRights access;
80
80
/* Security state: ARM_CP_SECSTATE_* bits/values */
81
return freq;
81
int secure;
82
}
82
/*
83
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
83
diff --git a/target/arm/helper.c b/target/arm/helper.c
84
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/misc/imx_ccm.c
85
--- a/target/arm/helper.c
86
+++ b/hw/misc/imx_ccm.c
86
+++ b/target/arm/helper.c
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
87
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
88
freq = klass->get_clock_frequency(dev, clock);
88
* to encompass the generic architectural permission check.
89
}
89
*/
90
90
if (r->state != ARM_CP_STATE_AA32) {
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
91
- int mask = 0;
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
92
+ CPAccessRights mask;
93
93
switch (r->opc1) {
94
return freq;
94
case 0:
95
}
95
/* min_EL EL1, but some accessible to EL0 via kernel ABI */
96
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
97
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
98
(mfd * pd)) << 10;
99
100
- DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
101
+ DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq,
102
freq);
103
104
return freq;
105
--
96
--
106
2.20.1
97
2.25.1
107
108
diff view generated by jsdifflib
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
3
Give this enum a name and use in ARMCPRegInfo,
4
Descriptor is 5 bits([4:0]).
4
add_cpreg_to_hashtable and define_one_arm_cp_reg_with_opaque.
5
5
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
8
Message-id: 20201124023711.1184-1-jiangkunkun@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Acked-by: Eric Auger <eric.auger@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-9-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
hw/arm/smmuv3-internal.h | 2 +-
12
target/arm/cpregs.h | 6 +++---
14
1 file changed, 1 insertion(+), 1 deletion(-)
13
target/arm/helper.c | 6 ++++--
14
2 files changed, 7 insertions(+), 5 deletions(-)
15
15
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
18
--- a/target/arm/cpregs.h
19
+++ b/hw/arm/smmuv3-internal.h
19
+++ b/target/arm/cpregs.h
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
20
@@ -XXX,XX +XXX,XX @@ enum {
21
return hi << 32 | lo;
21
* Note that we rely on the values of these enums as we iterate through
22
* the various states in some places.
23
*/
24
-enum {
25
+typedef enum {
26
ARM_CP_STATE_AA32 = 0,
27
ARM_CP_STATE_AA64 = 1,
28
ARM_CP_STATE_BOTH = 2,
29
-};
30
+} CPState;
31
32
/*
33
* ARM CP register secure state flags. These flags identify security state
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
35
uint8_t opc1;
36
uint8_t opc2;
37
/* Execution state in which this register is visible: ARM_CP_STATE_* */
38
- int state;
39
+ CPState state;
40
/* Register type: ARM_CP_* bits/values */
41
int type;
42
/* Access rights: PL*_[RW] */
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
22
}
48
}
23
49
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
51
- void *opaque, int state, int secstate,
26
52
+ void *opaque, CPState state, int secstate,
27
#endif
53
int crm, int opc1, int opc2,
54
const char *name)
55
{
56
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
57
* bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of
58
* the register, if any.
59
*/
60
- int crm, opc1, opc2, state;
61
+ int crm, opc1, opc2;
62
int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
63
int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
64
int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
65
int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
66
int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
67
int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
68
+ CPState state;
69
+
70
/* 64 bit registers have only CRm and Opc1 fields */
71
assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
72
/* op0 only exists in the AArch64 encodings */
28
--
73
--
29
2.20.1
74
2.25.1
30
75
31
76
diff view generated by jsdifflib
1
For v8.1M the architecture mandates that CPUs must provide at
1
From: Richard Henderson <richard.henderson@linaro.org>
2
least the "minimal RAS implementation" from the Reliability,
3
Availability and Serviceability extension. This consists of:
4
* an ESB instruction which is a NOP
5
-- since it is in the HINT space we need only add a comment
6
* an RFSR register which will RAZ/WI
7
* a RAZ/WI AIRCR.IESB bit
8
-- the code which handles writes to AIRCR does not allow setting
9
of RES0 bits, so we already treat this as RAZ/WI; add a comment
10
noting that this is deliberate
11
* minimal implementation of the RAS register block at 0xe0005000
12
-- this will be in a subsequent commit
13
* setting the ID_PFR0.RAS field to 0b0010
14
-- we will do this when we add the Cortex-M55 CPU model
15
2
3
Give this enum a name and use in ARMCPRegInfo and add_cpreg_to_hashtable.
4
Add the enumerator ARM_CP_SECSTATE_BOTH to clarify how 0
5
is handled in define_one_arm_cp_reg_with_opaque.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-10-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20201119215617.29887-26-peter.maydell@linaro.org
19
---
11
---
20
target/arm/cpu.h | 14 ++++++++++++++
12
target/arm/cpregs.h | 7 ++++---
21
target/arm/t32.decode | 4 ++++
13
target/arm/helper.c | 7 +++++--
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
14
2 files changed, 9 insertions(+), 5 deletions(-)
23
3 files changed, 31 insertions(+)
24
15
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
26
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/cpu.h
18
--- a/target/arm/cpregs.h
28
+++ b/target/arm/cpu.h
19
+++ b/target/arm/cpregs.h
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
20
@@ -XXX,XX +XXX,XX @@ typedef enum {
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
21
* registered entry will only have one to identify whether the entry is secure
31
FIELD(ID_MMFR4, EVT, 28, 4)
22
* or non-secure.
32
23
*/
33
+FIELD(ID_PFR0, STATE0, 0, 4)
24
-enum {
34
+FIELD(ID_PFR0, STATE1, 4, 4)
25
+typedef enum {
35
+FIELD(ID_PFR0, STATE2, 8, 4)
26
+ ARM_CP_SECSTATE_BOTH = 0, /* define one cpreg for each secstate */
36
+FIELD(ID_PFR0, STATE3, 12, 4)
27
ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
37
+FIELD(ID_PFR0, CSV2, 16, 4)
28
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
38
+FIELD(ID_PFR0, AMU, 20, 4)
29
-};
39
+FIELD(ID_PFR0, DIT, 24, 4)
30
+} CPSecureState;
40
+FIELD(ID_PFR0, RAS, 28, 4)
31
41
+
32
/*
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
33
* Access rights:
43
FIELD(ID_PFR1, SECURITY, 4, 4)
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
35
/* Access rights: PL*_[RW] */
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
36
CPAccessRights access;
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
37
/* Security state: ARM_CP_SECSTATE_* bits/values */
38
- int secure;
39
+ CPSecureState secure;
40
/*
41
* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
42
* this register was defined: can be used to hand data through to the
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
47
}
48
}
48
49
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
50
+{
51
- void *opaque, CPState state, int secstate,
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
52
+ void *opaque, CPState state,
52
+}
53
+ CPSecureState secstate,
53
+
54
int crm, int opc1, int opc2,
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
55
const char *name)
55
{
56
{
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
57
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
58
r->secure, crm, opc1, opc2,
58
index XXXXXXX..XXXXXXX 100644
59
r->name);
59
--- a/target/arm/t32.decode
60
break;
60
+++ b/target/arm/t32.decode
61
- default:
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
62
+ case ARM_CP_SECSTATE_BOTH:
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
63
name = g_strdup_printf("%s_S", r->name);
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
64
add_cpreg_to_hashtable(cpu, r, opaque, state,
64
65
ARM_CP_SECSTATE_S,
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
66
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
66
+ # default behaviour since it is in the hint space.
67
ARM_CP_SECSTATE_NS,
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
68
crm, opc1, opc2, r->name);
68
+
69
break;
69
# The canonical nop ends in 0000 0000, but the whole rest
70
+ default:
70
# of the space is "reserved hint, behaves as nop".
71
+ g_assert_not_reached();
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
72
}
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
73
} else {
73
index XXXXXXX..XXXXXXX 100644
74
/* AArch64 registers get mapped to non-secure instance
74
--- a/hw/intc/armv7m_nvic.c
75
+++ b/hw/intc/armv7m_nvic.c
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
77
return 0;
78
}
79
return cpu->env.v7m.sfar;
80
+ case 0xf04: /* RFSR */
81
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
82
+ goto bad_offset;
83
+ }
84
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
85
+ return 0;
86
case 0xf34: /* FPCCR */
87
if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
88
return 0;
89
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
90
R_V7M_AIRCR_PRIGROUP_SHIFT,
91
R_V7M_AIRCR_PRIGROUP_LENGTH);
92
}
93
+ /* AIRCR.IESB is RAZ/WI because we implement only minimal RAS */
94
if (attrs.secure) {
95
/* These bits are only writable by secure */
96
cpu->env.v7m.aircr = value &
97
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
98
}
99
break;
100
}
101
+ case 0xf04: /* RFSR */
102
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
103
+ goto bad_offset;
104
+ }
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
106
+ break;
107
case 0xf34: /* FPCCR */
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
109
/* Not all bits here are banked. */
110
--
75
--
111
2.20.1
76
2.25.1
112
113
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
The new_key field is always non-zero -- drop the if.
4
argument of type "unsigned int".
5
4
6
Reported-by: Euler Robot <euler.robot@huawei.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-11-richard.henderson@linaro.org
8
[PMM: reinstated dropped PL3_RW mask]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/misc/imx25_ccm.c | 12 ++++++------
11
target/arm/helper.c | 23 +++++++++++------------
13
1 file changed, 6 insertions(+), 6 deletions(-)
12
1 file changed, 11 insertions(+), 12 deletions(-)
14
13
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/imx25_ccm.c
16
--- a/target/arm/helper.c
18
+++ b/hw/misc/imx25_ccm.c
17
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
18
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
20
case IMX25_CCM_LPIMR1_REG:
19
21
return "lpimr1";
20
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
22
default:
21
const struct E2HAlias *a = &aliases[i];
23
- sprintf(unknown, "[%d ?]", reg);
22
- ARMCPRegInfo *src_reg, *dst_reg;
24
+ sprintf(unknown, "[%u ?]", reg);
23
+ ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
25
return unknown;
24
+ uint32_t *new_key;
26
}
25
+ bool ok;
27
}
26
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
27
if (a->feature && !a->feature(&cpu->isar)) {
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
28
continue;
30
}
29
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
31
30
g_assert(src_reg->opaque == NULL);
32
- DPRINTF("freq = %d\n", freq);
31
33
+ DPRINTF("freq = %u\n", freq);
32
/* Create alias before redirection so we dup the right data. */
34
33
- if (a->new_key) {
35
return freq;
34
- ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
36
}
35
- uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
36
- bool ok;
38
37
+ new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
38
+ new_key = g_memdup(&a->new_key, sizeof(uint32_t));
40
39
41
- DPRINTF("freq = %d\n", freq);
40
- new_reg->name = a->new_name;
42
+ DPRINTF("freq = %u\n", freq);
41
- new_reg->type |= ARM_CP_ALIAS;
43
42
- /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
44
return freq;
43
- new_reg->access &= PL2_RW | PL3_RW;
45
}
44
+ new_reg->name = a->new_name;
46
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
45
+ new_reg->type |= ARM_CP_ALIAS;
47
freq = imx25_ccm_get_mcu_clk(dev)
46
+ /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
48
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
47
+ new_reg->access &= PL2_RW | PL3_RW;
49
48
50
- DPRINTF("freq = %d\n", freq);
49
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
51
+ DPRINTF("freq = %u\n", freq);
50
- g_assert(ok);
52
51
- }
53
return freq;
52
+ ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
54
}
53
+ g_assert(ok);
55
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
54
56
55
src_reg->opaque = dst_reg;
57
freq = imx25_ccm_get_ahb_clk(dev) / 2;
56
src_reg->orig_readfn = src_reg->readfn ?: raw_read;
58
59
- DPRINTF("freq = %d\n", freq);
60
+ DPRINTF("freq = %u\n", freq);
61
62
return freq;
63
}
64
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
65
break;
66
}
67
68
- DPRINTF("Clock = %d) = %d\n", clock, freq);
69
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
70
71
return freq;
72
}
73
--
57
--
74
2.20.1
58
2.25.1
75
76
diff view generated by jsdifflib
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
1
From: Richard Henderson <richard.henderson@linaro.org>
2
gains new fields FZ16 (if half-precision floating point is supported)
3
and LTPSIZE (always reads as 4). Update the reset value and the code
4
that handles writes to this register accordingly.
5
2
3
Cast the uint32_t key into a gpointer directly, which
4
allows us to avoid allocating storage for each key.
5
6
Use g_hash_table_lookup when we already have a gpointer
7
(e.g. for callbacks like count_cpreg), or when using
8
get_arm_cp_reginfo would require casting away const.
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20220501055028.646596-12-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
9
---
14
---
10
target/arm/cpu.h | 5 +++++
15
target/arm/cpu.c | 4 ++--
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
16
target/arm/gdbstub.c | 2 +-
12
target/arm/cpu.c | 3 +++
17
target/arm/helper.c | 41 ++++++++++++++++++-----------------------
13
3 files changed, 16 insertions(+), 1 deletion(-)
18
3 files changed, 21 insertions(+), 26 deletions(-)
14
19
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
27
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
28
#define FPCR_V (1 << 28) /* FP overflow flag */
29
#define FPCR_C (1 << 29) /* FP carry flag */
30
#define FPCR_Z (1 << 30) /* FP zero flag */
31
#define FPCR_N (1 << 31) /* FP negative flag */
32
33
+#define FPCR_LTPSIZE_SHIFT 16 /* LTPSIZE, M-profile only */
34
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
35
+
36
#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
37
#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
38
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
break;
45
case 0xf3c: /* FPDSCR */
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
47
- value &= 0x07c00000;
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
50
+ mask |= FPCR_FZ16;
51
+ }
52
+ value &= mask;
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
55
+ }
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
57
}
58
break;
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
60
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/cpu.c
22
--- a/target/arm/cpu.c
62
+++ b/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
64
* always reset to 4.
25
ARMCPU *cpu = ARM_CPU(obj);
65
*/
26
66
env->v7m.ltpsize = 4;
27
cpu_set_cpustate_pointers(cpu);
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
28
- cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
29
- g_free, cpreg_hashtable_data_destroy);
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
30
+ cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
31
+ NULL, cpreg_hashtable_data_destroy);
32
33
QLIST_INIT(&cpu->pre_el_change_hooks);
34
QLIST_INIT(&cpu->el_change_hooks);
35
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/gdbstub.c
38
+++ b/target/arm/gdbstub.c
39
@@ -XXX,XX +XXX,XX @@ static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
40
static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
41
gpointer p)
42
{
43
- uint32_t ri_key = *(uint32_t *)key;
44
+ uint32_t ri_key = (uintptr_t)key;
45
ARMCPRegInfo *ri = value;
46
RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
47
GString *s = param->s;
48
diff --git a/target/arm/helper.c b/target/arm/helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/helper.c
51
+++ b/target/arm/helper.c
52
@@ -XXX,XX +XXX,XX @@ bool write_list_to_cpustate(ARMCPU *cpu)
53
static void add_cpreg_to_list(gpointer key, gpointer opaque)
54
{
55
ARMCPU *cpu = opaque;
56
- uint64_t regidx;
57
- const ARMCPRegInfo *ri;
58
-
59
- regidx = *(uint32_t *)key;
60
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
61
+ uint32_t regidx = (uintptr_t)key;
62
+ const ARMCPRegInfo *ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
63
64
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
65
cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
66
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_list(gpointer key, gpointer opaque)
67
static void count_cpreg(gpointer key, gpointer opaque)
68
{
69
ARMCPU *cpu = opaque;
70
- uint64_t regidx;
71
const ARMCPRegInfo *ri;
72
73
- regidx = *(uint32_t *)key;
74
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
75
+ ri = g_hash_table_lookup(cpu->cp_regs, key);
76
77
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
78
cpu->cpreg_array_len++;
79
@@ -XXX,XX +XXX,XX @@ static void count_cpreg(gpointer key, gpointer opaque)
80
81
static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
82
{
83
- uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
84
- uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
85
+ uint64_t aidx = cpreg_to_kvm_id((uintptr_t)a);
86
+ uint64_t bidx = cpreg_to_kvm_id((uintptr_t)b);
87
88
if (aidx > bidx) {
89
return 1;
90
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
91
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
92
const struct E2HAlias *a = &aliases[i];
93
ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
94
- uint32_t *new_key;
95
bool ok;
96
97
if (a->feature && !a->feature(&cpu->isar)) {
98
continue;
70
}
99
}
71
100
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
101
- src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
102
- dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
103
+ src_reg = g_hash_table_lookup(cpu->cp_regs,
104
+ (gpointer)(uintptr_t)a->src_key);
105
+ dst_reg = g_hash_table_lookup(cpu->cp_regs,
106
+ (gpointer)(uintptr_t)a->dst_key);
107
g_assert(src_reg != NULL);
108
g_assert(dst_reg != NULL);
109
110
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
111
112
/* Create alias before redirection so we dup the right data. */
113
new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
114
- new_key = g_memdup(&a->new_key, sizeof(uint32_t));
115
116
new_reg->name = a->new_name;
117
new_reg->type |= ARM_CP_ALIAS;
118
/* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
119
new_reg->access &= PL2_RW | PL3_RW;
120
121
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
122
+ ok = g_hash_table_insert(cpu->cp_regs,
123
+ (gpointer)(uintptr_t)a->new_key, new_reg);
124
g_assert(ok);
125
126
src_reg->opaque = dst_reg;
127
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
128
/* Private utility function for define_one_arm_cp_reg_with_opaque():
129
* add a single reginfo struct to the hash table.
130
*/
131
- uint32_t *key = g_new(uint32_t, 1);
132
+ uint32_t key;
133
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
134
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
135
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
136
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
137
if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
138
r2->cp = CP_REG_ARM64_SYSREG_CP;
139
}
140
- *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
141
- r2->opc0, opc1, opc2);
142
+ key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
143
+ r2->opc0, opc1, opc2);
144
} else {
145
- *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
146
+ key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
147
}
148
if (opaque) {
149
r2->opaque = opaque;
150
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
151
* requested.
152
*/
153
if (!(r->type & ARM_CP_OVERRIDE)) {
154
- ARMCPRegInfo *oldreg;
155
- oldreg = g_hash_table_lookup(cpu->cp_regs, key);
156
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
157
if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
158
fprintf(stderr, "Register redefined: cp=%d %d bit "
159
"crn=%d crm=%d opc1=%d opc2=%d, "
160
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
161
g_assert_not_reached();
162
}
163
}
164
- g_hash_table_insert(cpu->cp_regs, key, r2);
165
+ g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
166
}
167
168
169
@@ -XXX,XX +XXX,XX @@ void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
170
171
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
172
{
173
- return g_hash_table_lookup(cpregs, &encoded_cp);
174
+ return g_hash_table_lookup(cpregs, (gpointer)(uintptr_t)encoded_cp);
175
}
176
177
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
73
--
178
--
74
2.20.1
179
2.25.1
75
76
diff view generated by jsdifflib
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
1
From: Richard Henderson <richard.henderson@linaro.org>
2
via the has_el3 CPU object property, which we create if the CPU
3
starts with the ARM_FEATURE_EL3 feature bit. If it is disabled, then
4
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
5
the ID_PFR1 and ID_AA64PFR0 registers.
6
2
7
This codepath was incorrectly being taken for M-profile CPUs, which
3
Simplify freeing cp_regs hash table entries by using a single
8
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
4
allocation for the entire value.
9
the M-profile Security extension and so should have non-zero values
10
in the ID_PFR1.Security field.
11
5
12
Restrict the handling of the feature flag to A/R-profile cores.
6
This fixes a theoretical bug if we were to ever free the entire
7
hash table, because we've been installing string literal constants
8
into the cpreg structure in define_arm_vh_e2h_redirects_aliases.
9
However, at present we only free entries created for AArch32
10
wildcard cpregs which get overwritten by more specific cpregs,
11
so this bug is never exposed.
13
12
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 20220501055028.646596-13-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
17
---
17
---
18
target/arm/cpu.c | 2 +-
18
target/arm/cpu.c | 16 +---------------
19
1 file changed, 1 insertion(+), 1 deletion(-)
19
target/arm/helper.c | 10 ++++++++--
20
2 files changed, 9 insertions(+), 17 deletions(-)
20
21
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.c
24
--- a/target/arm/cpu.c
24
+++ b/target/arm/cpu.c
25
+++ b/target/arm/cpu.c
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
26
@@ -XXX,XX +XXX,XX @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz)
26
}
27
return (Aff1 << ARM_AFF1_SHIFT) | Aff0;
27
}
28
}
28
29
29
- if (!cpu->has_el3) {
30
-static void cpreg_hashtable_data_destroy(gpointer data)
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
31
-{
31
/* If the has_el3 CPU property is disabled then we need to disable the
32
- /*
32
* feature.
33
- * Destroy function for cpu->cp_regs hashtable data entries.
33
*/
34
- * We must free the name string because it was g_strdup()ed in
35
- * add_cpreg_to_hashtable(). It's OK to cast away the 'const'
36
- * from r->name because we know we definitely allocated it.
37
- */
38
- ARMCPRegInfo *r = data;
39
-
40
- g_free((void *)r->name);
41
- g_free(r);
42
-}
43
-
44
static void arm_cpu_initfn(Object *obj)
45
{
46
ARMCPU *cpu = ARM_CPU(obj);
47
48
cpu_set_cpustate_pointers(cpu);
49
cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
50
- NULL, cpreg_hashtable_data_destroy);
51
+ NULL, g_free);
52
53
QLIST_INIT(&cpu->pre_el_change_hooks);
54
QLIST_INIT(&cpu->el_change_hooks);
55
diff --git a/target/arm/helper.c b/target/arm/helper.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/helper.c
58
+++ b/target/arm/helper.c
59
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
60
* add a single reginfo struct to the hash table.
61
*/
62
uint32_t key;
63
- ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
64
+ ARMCPRegInfo *r2;
65
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
66
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
67
+ size_t name_len;
68
+
69
+ /* Combine cpreg and name into one allocation. */
70
+ name_len = strlen(name) + 1;
71
+ r2 = g_malloc(sizeof(*r2) + name_len);
72
+ *r2 = *r;
73
+ r2->name = memcpy(r2 + 1, name, name_len);
74
75
- r2->name = g_strdup(name);
76
/* Reset the secure state to the specific incoming state. This is
77
* necessary as the register may have been defined with both states.
78
*/
34
--
79
--
35
2.20.1
80
2.25.1
36
37
diff view generated by jsdifflib
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
MPU_RLAR registers, which forbids execution of code in the region
3
from a privileged mode.
4
2
5
This is another feature which is just in the generic "in v8.1M" set
3
Move the computation of key to the top of the function.
6
and has no ID register field indicating its presence.
4
Hoist the resolution of cp as well, as an input to the
5
computation of key.
7
6
7
This will be required by a subsequent patch.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20220501055028.646596-14-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
11
---
13
---
12
target/arm/helper.c | 7 ++++++-
14
target/arm/helper.c | 49 +++++++++++++++++++++++++--------------------
13
1 file changed, 6 insertions(+), 1 deletion(-)
15
1 file changed, 27 insertions(+), 22 deletions(-)
14
16
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
19
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
20
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
21
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
20
} else {
22
ARMCPRegInfo *r2;
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
23
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
24
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
23
+ bool pxn = false;
25
+ int cp = r->cp;
26
size_t name_len;
27
28
+ switch (state) {
29
+ case ARM_CP_STATE_AA32:
30
+ /* We assume it is a cp15 register if the .cp field is left unset. */
31
+ if (cp == 0 && r->state == ARM_CP_STATE_BOTH) {
32
+ cp = 15;
33
+ }
34
+ key = ENCODE_CP_REG(cp, is64, ns, r->crn, crm, opc1, opc2);
35
+ break;
36
+ case ARM_CP_STATE_AA64:
37
+ /*
38
+ * To allow abbreviation of ARMCPRegInfo definitions, we treat
39
+ * cp == 0 as equivalent to the value for "standard guest-visible
40
+ * sysreg". STATE_BOTH definitions are also always "standard sysreg"
41
+ * in their AArch64 view (the .cp value may be non-zero for the
42
+ * benefit of the AArch32 view).
43
+ */
44
+ if (cp == 0 || r->state == ARM_CP_STATE_BOTH) {
45
+ cp = CP_REG_ARM64_SYSREG_CP;
46
+ }
47
+ key = ENCODE_AA64_CP_REG(cp, r->crn, crm, r->opc0, opc1, opc2);
48
+ break;
49
+ default:
50
+ g_assert_not_reached();
51
+ }
24
+
52
+
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
53
/* Combine cpreg and name into one allocation. */
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
54
name_len = strlen(name) + 1;
27
+ }
55
r2 = g_malloc(sizeof(*r2) + name_len);
28
56
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
29
if (m_is_system_region(env, address)) {
30
/* System space is always execute never */
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
32
}
57
}
33
58
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
59
if (r->state == ARM_CP_STATE_BOTH) {
35
- if (*prot && !xn) {
60
- /* We assume it is a cp15 register if the .cp field is left unset.
36
+ if (*prot && !xn && !(pxn && !is_user)) {
61
- */
37
*prot |= PAGE_EXEC;
62
- if (r2->cp == 0) {
63
- r2->cp = 15;
64
- }
65
-
66
#if HOST_BIG_ENDIAN
67
if (r2->fieldoffset) {
68
r2->fieldoffset += sizeof(uint32_t);
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
70
#endif
38
}
71
}
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
72
}
73
- if (state == ARM_CP_STATE_AA64) {
74
- /* To allow abbreviation of ARMCPRegInfo
75
- * definitions, we treat cp == 0 as equivalent to
76
- * the value for "standard guest-visible sysreg".
77
- * STATE_BOTH definitions are also always "standard
78
- * sysreg" in their AArch64 view (the .cp value may
79
- * be non-zero for the benefit of the AArch32 view).
80
- */
81
- if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
82
- r2->cp = CP_REG_ARM64_SYSREG_CP;
83
- }
84
- key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
85
- r2->opc0, opc1, opc2);
86
- } else {
87
- key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
88
- }
89
if (opaque) {
90
r2->opaque = opaque;
91
}
92
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
93
/* Make sure reginfo passed to helpers for wildcarded regs
94
* has the correct crm/opc1/opc2 for this reg, not CP_ANY:
95
*/
96
+ r2->cp = cp;
97
r2->crm = crm;
98
r2->opc1 = opc1;
99
r2->opc2 = opc2;
40
--
100
--
41
2.20.1
101
2.25.1
42
43
diff view generated by jsdifflib
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the FPSCR. We have a comment that states this, but the actual logic
3
to forbid accesses for any other register value is missing, so we
4
would end up with A-profile style behaviour. Add the missing check.
5
2
3
Put most of the value writeback to the same place,
4
and improve the comment that goes with them.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-15-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-7-peter.maydell@linaro.org
9
---
10
---
10
target/arm/translate-vfp.c.inc | 5 ++++-
11
target/arm/helper.c | 28 ++++++++++++----------------
11
1 file changed, 4 insertions(+), 1 deletion(-)
12
1 file changed, 12 insertions(+), 16 deletions(-)
12
13
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
--- a/target/arm/helper.c
16
+++ b/target/arm/translate-vfp.c.inc
17
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
19
*r2 = *r;
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
20
r2->name = memcpy(r2 + 1, name, name_len);
20
*/
21
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
22
- /* Reset the secure state to the specific incoming state. This is
22
+ if (a->reg != ARM_VFP_FPSCR) {
23
- * necessary as the register may have been defined with both states.
23
+ return false;
24
+ /*
24
+ }
25
+ * Update fields to match the instantiation, overwiting wildcards
25
+ if (a->rt == 15 && !a->l) {
26
+ * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH.
26
return false;
27
*/
28
+ r2->cp = cp;
29
+ r2->crm = crm;
30
+ r2->opc1 = opc1;
31
+ r2->opc2 = opc2;
32
+ r2->state = state;
33
r2->secure = secstate;
34
+ if (opaque) {
35
+ r2->opaque = opaque;
36
+ }
37
38
if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
39
/* Register is banked (using both entries in array).
40
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
41
#endif
27
}
42
}
28
}
43
}
44
- if (opaque) {
45
- r2->opaque = opaque;
46
- }
47
- /* reginfo passed to helpers is correct for the actual access,
48
- * and is never ARM_CP_STATE_BOTH:
49
- */
50
- r2->state = state;
51
- /* Make sure reginfo passed to helpers for wildcarded regs
52
- * has the correct crm/opc1/opc2 for this reg, not CP_ANY:
53
- */
54
- r2->cp = cp;
55
- r2->crm = crm;
56
- r2->opc1 = opc1;
57
- r2->opc2 = opc2;
58
+
59
/* By convention, for wildcarded registers only the first
60
* entry is used for migration; the others are marked as
61
* ALIAS so we don't try to transfer the register
29
--
62
--
30
2.20.1
63
2.25.1
31
32
diff view generated by jsdifflib
1
Correct a typo in the name we give the NVIC object.
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Bool is a more appropriate type for these variables.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-16-richard.henderson@linaro.org
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
7
---
9
---
8
hw/arm/armv7m.c | 2 +-
10
target/arm/helper.c | 4 ++--
9
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 2 insertions(+), 2 deletions(-)
10
12
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/armv7m.c
15
--- a/target/arm/helper.c
14
+++ b/hw/arm/armv7m.c
16
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
16
18
*/
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
19
uint32_t key;
18
20
ARMCPRegInfo *r2;
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
21
- int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
22
- int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
21
object_property_add_alias(obj, "num-irq",
23
+ bool is64 = r->type & ARM_CP_64BIT;
22
OBJECT(&s->nvic), "num-irq");
24
+ bool ns = secstate & ARM_CP_SECSTATE_NS;
25
int cp = r->cp;
26
size_t name_len;
23
27
24
--
28
--
25
2.20.1
29
2.25.1
26
27
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Dump the collected random data after a randomness test failure.
3
Computing isbanked only once makes the code
4
a bit easier to read.
4
5
5
Note that this relies on the test having called
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
7
assertion failure.
8
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: minor commit message tweak]
8
Message-id: 20220501055028.646596-17-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
tests/qtest/npcm7xx_rng-test.c | 12 ++++++++++++
11
target/arm/helper.c | 6 ++++--
15
1 file changed, 12 insertions(+)
12
1 file changed, 4 insertions(+), 2 deletions(-)
16
13
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qtest/npcm7xx_rng-test.c
16
--- a/target/arm/helper.c
20
+++ b/tests/qtest/npcm7xx_rng-test.c
17
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
22
19
bool is64 = r->type & ARM_CP_64BIT;
23
#include "libqtest-single.h"
20
bool ns = secstate & ARM_CP_SECSTATE_NS;
24
#include "qemu/bitops.h"
21
int cp = r->cp;
25
+#include "qemu-common.h"
22
+ bool isbanked;
26
23
size_t name_len;
27
#define RNG_BASE_ADDR 0xf000b000
24
28
25
switch (state) {
29
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
30
/* Number of bits to collect for randomness tests. */
27
r2->opaque = opaque;
31
#define TEST_INPUT_BITS (128)
32
33
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
34
+{
35
+ if (g_test_failed()) {
36
+ qemu_hexdump(stderr, "", buf, size);
37
+ }
38
+}
39
+
40
static void rng_writeb(unsigned int offset, uint8_t value)
41
{
42
writeb(RNG_BASE_ADDR + offset, value);
43
@@ -XXX,XX +XXX,XX @@ static void test_continuous_monobit(void)
44
}
28
}
45
29
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
30
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
47
+ dump_buf_if_failed(buf, sizeof(buf));
31
+ isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
48
}
32
+ if (isbanked) {
49
33
/* Register is banked (using both entries in array).
50
/*
34
* Overwriting fieldoffset as the array is only used to define
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
35
* banked registers but later only fieldoffset is used.
36
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
52
}
37
}
53
38
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
39
if (state == ARM_CP_STATE_AA32) {
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
40
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
56
}
41
+ if (isbanked) {
57
42
/* If the register is banked then we don't need to migrate or
58
/*
43
* reset the 32-bit instance in certain cases:
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
44
*
60
}
61
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
63
+ dump_buf_if_failed(buf, sizeof(buf));
64
}
65
66
/*
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
68
}
69
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
72
}
73
74
int main(int argc, char **argv)
75
--
45
--
76
2.20.1
46
2.25.1
77
78
diff view generated by jsdifflib
1
The RAS feature has a block of memory-mapped registers at offset
1
From: Richard Henderson <richard.henderson@linaro.org>
2
0x5000 within the PPB. For a "minimal RAS" implementation we provide
3
no error records and so the only registers that exist in the block
4
are ERRIIDR and ERRDEVID.
5
2
6
The "RAZ/WI for privileged, BusFault for nonprivileged" behaviour
3
Perform the override check early, so that it is still done
7
of the "nvic-default" region is actually valid for minimal-RAS,
4
even when we decide to discard an unreachable cpreg.
8
so the main benefit of providing an explicit implementation of
9
the register block is more accurate LOG_UNIMP messages, and a
10
framework for where we could add a real RAS implementation later
11
if necessary.
12
5
6
Use assert not printf+abort.
7
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220501055028.646596-18-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-27-peter.maydell@linaro.org
16
---
12
---
17
include/hw/intc/armv7m_nvic.h | 1 +
13
target/arm/helper.c | 22 ++++++++--------------
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
14
1 file changed, 8 insertions(+), 14 deletions(-)
19
2 files changed, 57 insertions(+)
20
15
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/intc/armv7m_nvic.h
18
--- a/target/arm/helper.c
24
+++ b/include/hw/intc/armv7m_nvic.h
19
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
20
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
26
MemoryRegion sysreg_ns_mem;
21
g_assert_not_reached();
27
MemoryRegion systickmem;
22
}
28
MemoryRegion systick_ns_mem;
23
29
+ MemoryRegion ras_mem;
24
+ /* Overriding of an existing definition must be explicitly requested. */
30
MemoryRegion container;
25
+ if (!(r->type & ARM_CP_OVERRIDE)) {
31
MemoryRegion defaultmem;
26
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
32
27
+ if (oldreg) {
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
+ assert(oldreg->type & ARM_CP_OVERRIDE);
34
index XXXXXXX..XXXXXXX 100644
29
+ }
35
--- a/hw/intc/armv7m_nvic.c
36
+++ b/hw/intc/armv7m_nvic.c
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
38
.endianness = DEVICE_NATIVE_ENDIAN,
39
};
40
41
+
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
43
+ uint64_t *data, unsigned size,
44
+ MemTxAttrs attrs)
45
+{
46
+ if (attrs.user) {
47
+ return MEMTX_ERROR;
48
+ }
30
+ }
49
+
31
+
50
+ switch (addr) {
32
/* Combine cpreg and name into one allocation. */
51
+ case 0xe10: /* ERRIIDR */
33
name_len = strlen(name) + 1;
52
+ /* architect field = Arm; product/variant/revision 0 */
34
r2 = g_malloc(sizeof(*r2) + name_len);
53
+ *data = 0x43b;
35
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
54
+ break;
36
assert(!raw_accessors_invalid(r2));
55
+ case 0xfc8: /* ERRDEVID */
56
+ /* Minimal RAS: we implement 0 error record indexes */
57
+ *data = 0;
58
+ break;
59
+ default:
60
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
61
+ (uint32_t)addr);
62
+ *data = 0;
63
+ break;
64
+ }
65
+ return MEMTX_OK;
66
+}
67
+
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
69
+ uint64_t value, unsigned size,
70
+ MemTxAttrs attrs)
71
+{
72
+ if (attrs.user) {
73
+ return MEMTX_ERROR;
74
+ }
75
+
76
+ switch (addr) {
77
+ default:
78
+ qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
79
+ (uint32_t)addr);
80
+ break;
81
+ }
82
+ return MEMTX_OK;
83
+}
84
+
85
+static const MemoryRegionOps ras_ops = {
86
+ .read_with_attrs = ras_read,
87
+ .write_with_attrs = ras_write,
88
+ .endianness = DEVICE_NATIVE_ENDIAN,
89
+};
90
+
91
/*
92
* Unassigned portions of the PPB space are RAZ/WI for privileged
93
* accesses, and fault for non-privileged accesses.
94
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
95
&s->systick_ns_mem, 1);
96
}
37
}
97
38
98
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
39
- /* Overriding of an existing definition must be explicitly
99
+ memory_region_init_io(&s->ras_mem, OBJECT(s),
40
- * requested.
100
+ &ras_ops, s, "nvic_ras", 0x1000);
41
- */
101
+ memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
42
- if (!(r->type & ARM_CP_OVERRIDE)) {
102
+ }
43
- const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
103
+
44
- if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
104
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
45
- fprintf(stderr, "Register redefined: cp=%d %d bit "
46
- "crn=%d crm=%d opc1=%d opc2=%d, "
47
- "was %s, now %s\n", r2->cp, 32 + 32 * is64,
48
- r2->crn, r2->crm, r2->opc1, r2->opc2,
49
- oldreg->name, r2->name);
50
- g_assert_not_reached();
51
- }
52
- }
53
g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
105
}
54
}
106
55
107
--
56
--
108
2.20.1
57
2.25.1
109
110
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Connect CAN0 and CAN1 on the ZynqMP.
3
Put the block comments into the current coding style.
4
4
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
7
Message-id: 20220501055028.646596-19-richard.henderson@linaro.org
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
10
target/arm/helper.c | 24 +++++++++++++++---------
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
11
1 file changed, 15 insertions(+), 9 deletions(-)
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
14
3 files changed, 62 insertions(+)
15
12
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
15
--- a/target/arm/helper.c
19
+++ b/include/hw/arm/xlnx-zynqmp.h
16
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
21
#include "hw/intc/arm_gic.h"
18
return cpu_list;
22
#include "hw/net/cadence_gem.h"
23
#include "hw/char/cadence_uart.h"
24
+#include "hw/net/xlnx-zynqmp-can.h"
25
#include "hw/ide/ahci.h"
26
#include "hw/sd/sdhci.h"
27
#include "hw/ssi/xilinx_spips.h"
28
@@ -XXX,XX +XXX,XX @@
29
#include "hw/cpu/cluster.h"
30
#include "target/arm/cpu.h"
31
#include "qom/object.h"
32
+#include "net/can_emu.h"
33
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
35
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
38
#define XLNX_ZYNQMP_NUM_GEMS 4
39
#define XLNX_ZYNQMP_NUM_UARTS 2
40
+#define XLNX_ZYNQMP_NUM_CAN 2
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
61
62
#endif
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/xlnx-zcu102.c
66
+++ b/hw/arm/xlnx-zcu102.c
67
@@ -XXX,XX +XXX,XX @@
68
#include "sysemu/qtest.h"
69
#include "sysemu/device_tree.h"
70
#include "qom/object.h"
71
+#include "net/can_emu.h"
72
73
struct XlnxZCU102 {
74
MachineState parent_obj;
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
76
bool secure;
77
bool virt;
78
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
80
+
81
struct arm_boot_info binfo;
82
};
83
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
86
&error_fatal);
87
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
90
+
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
94
+ }
95
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
97
98
/* Create and plug in the SD cards */
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
100
s->secure = false;
101
/* Default to virt (EL2) being disabled */
102
s->virt = false;
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
107
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
109
+ (Object **)&s->canbus[1],
110
+ object_property_allow_set_link,
111
+ 0);
112
}
19
}
113
20
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
21
+/*
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
22
+ * Private utility function for define_one_arm_cp_reg_with_opaque():
116
index XXXXXXX..XXXXXXX 100644
23
+ * add a single reginfo struct to the hash table.
117
--- a/hw/arm/xlnx-zynqmp.c
24
+ */
118
+++ b/hw/arm/xlnx-zynqmp.c
25
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
26
void *opaque, CPState state,
120
21, 22,
27
CPSecureState secstate,
121
};
28
int crm, int opc1, int opc2,
122
29
const char *name)
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
30
{
124
+ 0xFF060000, 0xFF070000,
31
- /* Private utility function for define_one_arm_cp_reg_with_opaque():
125
+};
32
- * add a single reginfo struct to the hash table.
126
+
33
- */
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
34
uint32_t key;
128
+ 23, 24,
35
ARMCPRegInfo *r2;
129
+};
36
bool is64 = r->type & ARM_CP_64BIT;
130
+
37
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
38
132
0xFF160000, 0xFF170000,
39
isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
133
};
40
if (isbanked) {
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
41
- /* Register is banked (using both entries in array).
135
TYPE_CADENCE_UART);
42
+ /*
43
+ * Register is banked (using both entries in array).
44
* Overwriting fieldoffset as the array is only used to define
45
* banked registers but later only fieldoffset is used.
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
48
49
if (state == ARM_CP_STATE_AA32) {
50
if (isbanked) {
51
- /* If the register is banked then we don't need to migrate or
52
+ /*
53
+ * If the register is banked then we don't need to migrate or
54
* reset the 32-bit instance in certain cases:
55
*
56
* 1) If the register has both 32-bit and 64-bit instances then we
57
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
58
r2->type |= ARM_CP_ALIAS;
59
}
60
} else if ((secstate != r->secure) && !ns) {
61
- /* The register is not banked so we only want to allow migration of
62
- * the non-secure instance.
63
+ /*
64
+ * The register is not banked so we only want to allow migration
65
+ * of the non-secure instance.
66
*/
67
r2->type |= ARM_CP_ALIAS;
68
}
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
70
}
136
}
71
}
137
72
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
73
- /* By convention, for wildcarded registers only the first
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
74
+ /*
140
+ TYPE_XLNX_ZYNQMP_CAN);
75
+ * By convention, for wildcarded registers only the first
141
+ }
76
* entry is used for migration; the others are marked as
142
+
77
* ALIAS so we don't try to transfer the register
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
78
* multiple times. Special registers (ie NOP/WFI) are
144
79
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
80
r2->type |= ARM_CP_ALIAS | ARM_CP_NO_GDB;
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
147
gic_spi[uart_intr[i]]);
148
}
81
}
149
82
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
83
- /* Check that raw accesses are either forbidden or handled. Note that
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
84
+ /*
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
85
+ * Check that raw accesses are either forbidden or handled. Note that
153
+
86
* we can't assert this earlier because the setup of fieldoffset for
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
87
* banked registers has to be done first.
155
+ OBJECT(s->canbus[i]), &error_fatal);
88
*/
156
+
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
158
+ if (err) {
159
+ error_propagate(errp, err);
160
+ return;
161
+ }
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
164
+ gic_spi[can_intr[i]]);
165
+ }
166
+
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
168
&error_abort);
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
173
MemoryRegion *),
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
175
+ CanBusState *),
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
177
+ CanBusState *),
178
DEFINE_PROP_END_OF_LIST()
179
};
180
181
--
89
--
182
2.20.1
90
2.25.1
183
184
diff view generated by jsdifflib
Deleted patch
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
1
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
6
Message-id: 1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
MAINTAINERS | 8 ++++++++
10
1 file changed, 8 insertions(+)
11
12
diff --git a/MAINTAINERS b/MAINTAINERS
13
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
15
+++ b/MAINTAINERS
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
17
18
Devices
19
-------
20
+Xilinx CAN
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
23
+S: Maintained
24
+F: hw/net/can/xlnx-*
25
+F: include/hw/net/xlnx-*
26
+F: tests/qtest/xlnx-can-test*
27
+
28
EDU
29
M: Jiri Slaby <jslaby@suse.cz>
30
S: Maintained
31
--
32
2.20.1
33
34
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
3
Since e03b56863d2bc, our host endian indicator is unconditionally
4
it for QEMU as well. A53 was already enabled there.
4
set, which means that we can use a normal C condition.
5
5
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
8
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201120141705.246690-1-marcin.juszkiewicz@linaro.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-20-richard.henderson@linaro.org
9
[PMM: quote correct git hash in commit message]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
12
target/arm/helper.c | 9 +++------
15
1 file changed, 20 insertions(+), 3 deletions(-)
13
1 file changed, 3 insertions(+), 6 deletions(-)
16
14
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/sbsa-ref.c
17
--- a/target/arm/helper.c
20
+++ b/hw/arm/sbsa-ref.c
18
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
19
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
22
[SBSA_GWDT] = 16,
20
r2->type |= ARM_CP_ALIAS;
23
};
21
}
24
22
25
+static const char * const valid_cpus[] = {
23
- if (r->state == ARM_CP_STATE_BOTH) {
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
24
-#if HOST_BIG_ENDIAN
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
25
- if (r2->fieldoffset) {
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
26
- r2->fieldoffset += sizeof(uint32_t);
29
+};
27
- }
30
+
28
-#endif
31
+static bool cpu_type_valid(const char *cpu)
29
+ if (HOST_BIG_ENDIAN &&
32
+{
30
+ r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
33
+ int i;
31
+ r2->fieldoffset += sizeof(uint32_t);
34
+
32
}
35
+ for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
36
+ if (strcmp(cpu, valid_cpus[i]) == 0) {
37
+ return true;
38
+ }
39
+ }
40
+ return false;
41
+}
42
+
43
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
44
{
45
uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
46
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
47
const CPUArchIdList *possible_cpus;
48
int n, sbsa_max_cpus;
49
50
- if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
51
- error_report("sbsa-ref: CPU type other than the built-in "
52
- "cortex-a57 not supported");
53
+ if (!cpu_type_valid(machine->cpu_type)) {
54
+ error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
55
exit(1);
56
}
33
}
57
34
58
--
35
--
59
2.20.1
36
2.25.1
60
61
diff view generated by jsdifflib
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
1
From: Richard Henderson <richard.henderson@linaro.org>
2
registers if there is an active floating point context.
3
This requires support in write_neon_element32() for the MO_32
4
element size, so add it.
5
2
6
Because we want to use arm_gen_condlabel(), we need to move
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
the definition of that function up in translate.c so it is
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
before the #include of translate-vfp.c.inc.
5
Message-id: 20220501055028.646596-24-richard.henderson@linaro.org
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
13
---
7
---
14
target/arm/cpu.h | 9 ++++
8
target/arm/cpu.h | 15 +++++++++++++++
15
target/arm/m-nocp.decode | 8 +++-
9
1 file changed, 15 insertions(+)
16
target/arm/translate.c | 21 +++++----
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
18
4 files changed, 111 insertions(+), 11 deletions(-)
19
10
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
13
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
14
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
15
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
16
return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
26
}
17
}
27
18
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
19
+static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
29
+{
20
+{
30
+ /*
21
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8;
31
+ * Return true if M-profile state handling insns
32
+ * (VSCCLRM, CLRM, FPCTX access insns) are implemented
33
+ */
34
+ return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
35
+}
22
+}
36
+
23
+
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
24
/*
38
{
25
* 64-bit feature tests via id registers.
39
/* Sadly this is encoded differently for A-profile and M-profile */
26
*/
40
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
27
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
41
index XXXXXXX..XXXXXXX 100644
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
42
--- a/target/arm/m-nocp.decode
43
+++ b/target/arm/m-nocp.decode
44
@@ -XXX,XX +XXX,XX @@
45
# If the coprocessor is not present or disabled then we will generate
46
# the NOCP exception; otherwise we let the insn through to the main decode.
47
48
+%vd_dp 22:1 12:4
49
+%vd_sp 12:4 22:1
50
+
51
&nocp cp
52
53
{
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
58
+ # VSCCLRM (new in v8.1M) is similar:
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
61
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
69
a64_translate_init();
70
}
29
}
71
30
72
+/* Generate a label used for skipping this instruction */
31
+static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
73
+static void arm_gen_condlabel(DisasContext *s)
74
+{
32
+{
75
+ if (!s->condjmp) {
33
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8;
76
+ s->condlabel = gen_new_label();
77
+ s->condjmp = 1;
78
+ }
79
+}
34
+}
80
+
35
+
81
/* Flags for the disas_set_da_iss info argument:
36
static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
82
* lower bits hold the Rt register number, higher bits are flags.
37
{
83
*/
38
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0;
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
39
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
85
long off = neon_element_offset(reg, ele, memop);
40
return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
86
87
switch (memop) {
88
+ case MO_32:
89
+ tcg_gen_st32_i64(src, cpu_env, off);
90
+ break;
91
case MO_64:
92
tcg_gen_st_i64(src, cpu_env, off);
93
break;
94
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
95
s->base.is_jmp = DISAS_UPDATE_EXIT;
96
}
41
}
97
42
98
-/* Generate a label used for skipping this instruction */
43
+static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
99
-static void arm_gen_condlabel(DisasContext *s)
100
-{
101
- if (!s->condjmp) {
102
- s->condlabel = gen_new_label();
103
- s->condjmp = 1;
104
- }
105
-}
106
-
107
/* Skip this instruction if the ARM condition is false */
108
static void arm_skip_unless(DisasContext *s, uint32_t cond)
109
{
110
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
111
index XXXXXXX..XXXXXXX 100644
112
--- a/target/arm/translate-vfp.c.inc
113
+++ b/target/arm/translate-vfp.c.inc
114
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
115
return true;
116
}
117
118
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
119
+{
44
+{
120
+ int btmreg, topreg;
45
+ return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
121
+ TCGv_i64 zero;
122
+ TCGv_i32 aspen, sfpa;
123
+
124
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
125
+ /* Before v8.1M, fall through in decode to NOCP check */
126
+ return false;
127
+ }
128
+
129
+ /* Explicitly UNDEF because this takes precedence over NOCP */
130
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
131
+ unallocated_encoding(s);
132
+ return true;
133
+ }
134
+
135
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
136
+ /* NOP if we have neither FP nor MVE */
137
+ return true;
138
+ }
139
+
140
+ /*
141
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
142
+ * active floating point context so we must NOP (without doing
143
+ * any lazy state preservation or the NOCP check).
144
+ */
145
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
146
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
147
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
148
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
149
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
150
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
151
+ arm_gen_condlabel(s);
152
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
153
+
154
+ if (s->fp_excp_el != 0) {
155
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
156
+ syn_uncategorized(), s->fp_excp_el);
157
+ return true;
158
+ }
159
+
160
+ topreg = a->vd + a->imm - 1;
161
+ btmreg = a->vd;
162
+
163
+ /* Convert to Sreg numbers if the insn specified in Dregs */
164
+ if (a->size == 3) {
165
+ topreg = topreg * 2 + 1;
166
+ btmreg *= 2;
167
+ }
168
+
169
+ if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
170
+ /* UNPREDICTABLE: we choose to undef */
171
+ unallocated_encoding(s);
172
+ return true;
173
+ }
174
+
175
+ /* Silently ignore requests to clear D16-D31 if they don't exist */
176
+ if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
177
+ topreg = 31;
178
+ }
179
+
180
+ if (!vfp_access_check(s)) {
181
+ return true;
182
+ }
183
+
184
+ /* Zero the Sregs from btmreg to topreg inclusive. */
185
+ zero = tcg_const_i64(0);
186
+ if (btmreg & 1) {
187
+ write_neon_element64(zero, btmreg >> 1, 1, MO_32);
188
+ btmreg++;
189
+ }
190
+ for (; btmreg + 1 <= topreg; btmreg += 2) {
191
+ write_neon_element64(zero, btmreg >> 1, 0, MO_64);
192
+ }
193
+ if (btmreg == topreg) {
194
+ write_neon_element64(zero, btmreg >> 1, 0, MO_32);
195
+ btmreg++;
196
+ }
197
+ assert(btmreg == topreg + 1);
198
+ /* TODO: when MVE is implemented, zero VPR here */
199
+ return true;
200
+}
46
+}
201
+
47
+
202
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
48
/*
203
{
49
* Forward to the above feature tests given an ARMCPU pointer.
204
/*
50
*/
205
--
51
--
206
2.20.1
52
2.25.1
207
208
diff view generated by jsdifflib
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
1
From: Richard Henderson <richard.henderson@linaro.org>
2
(access to the FP system registers), because all it needs to support
3
is the FPSCR. In v8.1M things become significantly more complicated
4
in two ways:
5
2
6
* there are several new FP system registers; some have side effects
3
Add the aa64 predicate for detecting RAS support from id registers.
7
on read, and one (FPCXT_NS) needs to avoid the usual
4
We already have the aa32 version from the M-profile work.
8
vfp_access_check() and the "only if FPU implemented" check
5
Add the 'any' predicate for testing both aa64 and aa32.
9
6
10
* all sysregs are now accessible both by VMRS/VMSR (which
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
reads/writes a general purpose register) and also by VLDR/VSTR
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
(which reads/writes them directly to memory)
9
Message-id: 20220501055028.646596-34-richard.henderson@linaro.org
13
14
Refactor the structure of how we handle VMSR/VMRS to cope with this:
15
16
* keep the M-profile code entirely separate from the A-profile code
17
18
* abstract out the "read or write the general purpose register" part
19
of the code into a loadfn or storefn function pointer, so we can
20
reuse it for VLDR/VSTR.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20201119215617.29887-8-peter.maydell@linaro.org
25
---
11
---
26
target/arm/cpu.h | 3 +
12
target/arm/cpu.h | 10 ++++++++++
27
target/arm/translate-vfp.c.inc | 182 ++++++++++++++++++++++++++++++---
13
1 file changed, 10 insertions(+)
28
2 files changed, 171 insertions(+), 14 deletions(-)
29
14
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
33
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
19
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
35
#define ARM_VFP_FPINST 9
20
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
36
#define ARM_VFP_FPINST2 10
37
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
40
+
41
/* iwMMXt coprocessor control registers. */
42
#define ARM_IWMMXT_wCID 0
43
#define ARM_IWMMXT_wCon 1
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/translate-vfp.c.inc
47
+++ b/target/arm/translate-vfp.c.inc
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
49
return true;
50
}
21
}
51
22
52
+/*
23
+static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
53
+ * M-profile provides two different sets of instructions that can
54
+ * access floating point system registers: VMSR/VMRS (which move
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
56
+ * move directly to/from memory). In some cases there are also side
57
+ * effects which must happen after any write to memory (which could
58
+ * cause an exception). So we implement the common logic for the
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
60
+ * which take pointers to callback functions which will perform the
61
+ * actual "read/write general purpose register" and "read/write
62
+ * memory" operations.
63
+ */
64
+
65
+/*
66
+ * Emit code to store the sysreg to its final destination; frees the
67
+ * TCG temp 'value' it is passed.
68
+ */
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
70
+/*
71
+ * Emit code to load the value to be copied to the sysreg; returns
72
+ * a new TCG temporary
73
+ */
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
75
+
76
+/* Common decode/access checks for fp sysreg read/write */
77
+typedef enum FPSysRegCheckResult {
78
+ FPSysRegCheckFailed, /* caller should return false */
79
+ FPSysRegCheckDone, /* caller should return true */
80
+ FPSysRegCheckContinue, /* caller should continue generating code */
81
+} FPSysRegCheckResult;
82
+
83
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
84
+{
24
+{
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
25
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
86
+ return FPSysRegCheckFailed;
87
+ }
88
+
89
+ switch (regno) {
90
+ case ARM_VFP_FPSCR:
91
+ case QEMU_VFP_FPSCR_NZCV:
92
+ break;
93
+ default:
94
+ return FPSysRegCheckFailed;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return FPSysRegCheckDone;
99
+ }
100
+
101
+ return FPSysRegCheckContinue;
102
+}
26
+}
103
+
27
+
104
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
28
static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
105
+
29
{
106
+ fp_sysreg_loadfn *loadfn,
30
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
107
+ void *opaque)
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
32
return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
33
}
34
35
+static inline bool isar_feature_any_ras(const ARMISARegisters *id)
108
+{
36
+{
109
+ /* Do a write to an M-profile floating point system register */
37
+ return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id);
110
+ TCGv_i32 tmp;
111
+
112
+ switch (fp_sysreg_checks(s, regno)) {
113
+ case FPSysRegCheckFailed:
114
+ return false;
115
+ case FPSysRegCheckDone:
116
+ return true;
117
+ case FPSysRegCheckContinue:
118
+ break;
119
+ }
120
+
121
+ switch (regno) {
122
+ case ARM_VFP_FPSCR:
123
+ tmp = loadfn(s, opaque);
124
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
125
+ tcg_temp_free_i32(tmp);
126
+ gen_lookup_tb(s);
127
+ break;
128
+ default:
129
+ g_assert_not_reached();
130
+ }
131
+ return true;
132
+}
38
+}
133
+
39
+
134
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
40
/*
135
+ fp_sysreg_storefn *storefn,
41
* Forward to the above feature tests given an ARMCPU pointer.
136
+ void *opaque)
42
*/
137
+{
138
+ /* Do a read from an M-profile floating point system register */
139
+ TCGv_i32 tmp;
140
+
141
+ switch (fp_sysreg_checks(s, regno)) {
142
+ case FPSysRegCheckFailed:
143
+ return false;
144
+ case FPSysRegCheckDone:
145
+ return true;
146
+ case FPSysRegCheckContinue:
147
+ break;
148
+ }
149
+
150
+ switch (regno) {
151
+ case ARM_VFP_FPSCR:
152
+ tmp = tcg_temp_new_i32();
153
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
154
+ storefn(s, opaque, tmp);
155
+ break;
156
+ case QEMU_VFP_FPSCR_NZCV:
157
+ /*
158
+ * Read just NZCV; this is a special case to avoid the
159
+ * helper call for the "VMRS to CPSR.NZCV" insn.
160
+ */
161
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
162
+ tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
163
+ storefn(s, opaque, tmp);
164
+ break;
165
+ default:
166
+ g_assert_not_reached();
167
+ }
168
+ return true;
169
+}
170
+
171
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
172
+{
173
+ arg_VMSR_VMRS *a = opaque;
174
+
175
+ if (a->rt == 15) {
176
+ /* Set the 4 flag bits in the CPSR */
177
+ gen_set_nzcv(value);
178
+ tcg_temp_free_i32(value);
179
+ } else {
180
+ store_reg(s, a->rt, value);
181
+ }
182
+}
183
+
184
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
185
+{
186
+ arg_VMSR_VMRS *a = opaque;
187
+
188
+ return load_reg(s, a->rt);
189
+}
190
+
191
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
192
+{
193
+ /*
194
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
195
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
196
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
197
+ * we only care about the top 4 bits of FPSCR there.
198
+ */
199
+ if (a->rt == 15) {
200
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
201
+ a->reg = QEMU_VFP_FPSCR_NZCV;
202
+ } else {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ if (a->l) {
208
+ /* VMRS, move FP system register to gp register */
209
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
210
+ } else {
211
+ /* VMSR, move gp register to FP system register */
212
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
213
+ }
214
+}
215
+
216
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
217
{
218
TCGv_i32 tmp;
219
bool ignore_vfp_enabled = false;
220
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
222
- return false;
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
224
+ return gen_M_VMSR_VMRS(s, a);
225
}
226
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
228
- /*
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
232
- */
233
- if (a->reg != ARM_VFP_FPSCR) {
234
- return false;
235
- }
236
- if (a->rt == 15 && !a->l) {
237
- return false;
238
- }
239
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
240
+ return false;
241
}
242
243
switch (a->reg) {
244
--
43
--
245
2.20.1
44
2.25.1
246
247
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Alex Zuepke <alex.zuepke@tum.de>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
The ARMv8 manual defines that PMUSERENR_EL0.ER enables read-access
4
argument of type "unsigned int".
4
to both PMXEVCNTR_EL0 and PMEVCNTR<n>_EL0 registers, however,
5
we only use it for PMXEVCNTR_EL0. Extend to PMEVCNTR<n>_EL0 as well.
5
6
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Zuepke <alex.zuepke@tum.de>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
9
Message-id: 20220428132717.84190-1-alex.zuepke@tum.de
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
hw/misc/imx6ul_ccm.c | 4 ++--
12
target/arm/helper.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
14
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/imx6ul_ccm.c
17
--- a/target/arm/helper.c
18
+++ b/hw/misc/imx6ul_ccm.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
19
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
20
case CCM_CMEOR:
20
.crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
21
return "CMEOR";
21
.access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
22
default:
22
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
23
- sprintf(unknown, "%d ?", reg);
23
- .accessfn = pmreg_access },
24
+ sprintf(unknown, "%u ?", reg);
24
+ .accessfn = pmreg_access_xevcntr },
25
return unknown;
25
{ .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
26
}
26
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
27
}
27
- .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
28
+ .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access_xevcntr,
29
case USB_ANALOG_DIGPROG:
29
.type = ARM_CP_IO,
30
return "USB_ANALOG_DIGPROG";
30
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
31
default:
31
.raw_readfn = pmevcntr_rawread,
32
- sprintf(unknown, "%d ?", reg);
33
+ sprintf(unknown, "%u ?", reg);
34
return unknown;
35
}
36
}
37
--
32
--
38
2.20.1
33
2.25.1
39
40
diff view generated by jsdifflib
Deleted patch
1
For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
2
Private Peripheral Bus range, which includes all of the memory mapped
3
devices and registers that are part of the CPU itself, including the
4
NVIC, systick timer, and debug and trace components like the Data
5
Watchpoint and Trace unit (DWT). Within this large region, the range
6
0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
7
registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
8
alias.
9
1
10
The architecture is clear that within the SCS unimplemented registers
11
should be RES0 for privileged accesses and generate BusFault for
12
unprivileged accesses, and we currently implement this.
13
14
It is less clear about how to handle accesses to unimplemented
15
regions of the wider PPB. Unprivileged accesses should definitely
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
17
not given as a general rule. However, the register definitions of
18
individual registers for components like the DWT all state that they
19
are RES0 if the relevant component is not implemented, so the
20
simplest way to provide that is to provide RAZ/WI for the whole range
21
for privileged accesses. (The v7M Arm ARM does say that reserved
22
registers should be UNK/SBZP.)
23
24
Expand the container MemoryRegion that the NVIC exposes so that
25
it covers the whole PPB space. This means:
26
* moving the address that the ARMV7M device maps it to down by
27
0xe000 bytes
28
* moving the off and the offsets within the container of all the
29
subregions forward by 0xe000 bytes
30
* adding a new default MemoryRegion that covers the whole container
31
at a lower priority than anything else and which provides the
32
RAZWI/BusFault behaviour
33
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
37
---
38
include/hw/intc/armv7m_nvic.h | 1 +
39
hw/arm/armv7m.c | 2 +-
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
41
3 files changed, 69 insertions(+), 12 deletions(-)
42
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
44
index XXXXXXX..XXXXXXX 100644
45
--- a/include/hw/intc/armv7m_nvic.h
46
+++ b/include/hw/intc/armv7m_nvic.h
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
48
MemoryRegion systickmem;
49
MemoryRegion systick_ns_mem;
50
MemoryRegion container;
51
+ MemoryRegion defaultmem;
52
53
uint32_t num_irq;
54
qemu_irq excpout;
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/armv7m.c
58
+++ b/hw/arm/armv7m.c
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
60
sysbus_connect_irq(sbd, 0,
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
62
63
- memory_region_add_subregion(&s->container, 0xe000e000,
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
65
sysbus_mmio_get_region(sbd, 0));
66
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/armv7m_nvic.c
71
+++ b/hw/intc/armv7m_nvic.c
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
73
.endianness = DEVICE_NATIVE_ENDIAN,
74
};
75
76
+/*
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
78
+ * accesses, and fault for non-privileged accesses.
79
+ */
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
81
+ uint64_t *data, unsigned size,
82
+ MemTxAttrs attrs)
83
+{
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
85
+ (uint32_t)addr);
86
+ if (attrs.user) {
87
+ return MEMTX_ERROR;
88
+ }
89
+ *data = 0;
90
+ return MEMTX_OK;
91
+}
92
+
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
94
+ uint64_t value, unsigned size,
95
+ MemTxAttrs attrs)
96
+{
97
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
98
+ (uint32_t)addr);
99
+ if (attrs.user) {
100
+ return MEMTX_ERROR;
101
+ }
102
+ return MEMTX_OK;
103
+}
104
+
105
+static const MemoryRegionOps ppb_default_ops = {
106
+ .read_with_attrs = ppb_default_read,
107
+ .write_with_attrs = ppb_default_write,
108
+ .endianness = DEVICE_NATIVE_ENDIAN,
109
+ .valid.min_access_size = 1,
110
+ .valid.max_access_size = 8,
111
+};
112
+
113
static int nvic_post_load(void *opaque, int version_id)
114
{
115
NVICState *s = opaque;
116
@@ -XXX,XX +XXX,XX @@ static void nvic_systick_trigger(void *opaque, int n, int level)
117
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
118
{
119
NVICState *s = NVIC(dev);
120
- int regionlen;
121
122
/* The armv7m container object will have set our CPU pointer */
123
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
124
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
125
M_REG_S));
126
}
127
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
129
+ /*
130
+ * This device provides a single sysbus memory region which
131
+ * represents the whole of the "System PPB" space. This is the
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
133
+ * the System Control Space (system registers), the systick timer,
134
+ * and for CPUs with the Security extension an NS banked version
135
+ * of all of these.
136
+ *
137
+ * The default behaviour for unimplemented registers/ranges
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
140
+ * access.
141
+ *
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
143
* and looks like this:
144
* 0x004 - ICTR
145
* 0x010 - 0xff - systick
146
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
147
* generally code determining which banked register to use should
148
* use attrs.secure; code determining actual behaviour of the system
149
* should use env->v7m.secure.
150
+ *
151
+ * The container covers the whole PPB space. Within it the priority
152
+ * of overlapping regions is:
153
+ * - default region (for RAZ/WI and BusFault) : -1
154
+ * - system register regions : 0
155
+ * - systick : 1
156
+ * This is because the systick device is a small block of registers
157
+ * in the middle of the other system control registers.
158
*/
159
- regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
160
- memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
161
- /* The system register region goes at the bottom of the priority
162
- * stack as it covers the whole page.
163
- */
164
+ memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
165
+ memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
166
+ "nvic-default", 0x100000);
167
+ memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
168
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
169
"nvic_sysregs", 0x1000);
170
- memory_region_add_subregion(&s->container, 0, &s->sysregmem);
171
+ memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
172
173
memory_region_init_io(&s->systickmem, OBJECT(s),
174
&nvic_systick_ops, s,
175
"nvic_systick", 0xe0);
176
177
- memory_region_add_subregion_overlap(&s->container, 0x10,
178
+ memory_region_add_subregion_overlap(&s->container, 0xe010,
179
&s->systickmem, 1);
180
181
if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
182
memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
183
&nvic_sysreg_ns_ops, &s->sysregmem,
184
"nvic_sysregs_ns", 0x1000);
185
- memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
186
+ memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
187
memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
188
&nvic_sysreg_ns_ops, &s->systickmem,
189
"nvic_systick_ns", 0xe0);
190
- memory_region_add_subregion_overlap(&s->container, 0x20010,
191
+ memory_region_add_subregion_overlap(&s->container, 0x2e010,
192
&s->systick_ns_mem, 1);
193
}
194
195
--
196
2.20.1
197
198
diff view generated by jsdifflib
Deleted patch
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
2
read or write FP system registers to memory.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
7
---
8
target/arm/vfp.decode | 14 ++++++
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
10
2 files changed, 105 insertions(+)
11
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/vfp.decode
15
+++ b/target/arm/vfp.decode
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
19
20
+# M-profile VLDR/VSTR to sysreg
21
+%vldr_sysreg 22:1 13:3
22
+%imm7_0x4 0:7 !function=times_4
23
+
24
+&vldr_sysreg rn reg imm a w p
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
27
+
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
33
+
34
# We split the load/store multiple up into two patterns to avoid
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
36
# grouping:
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-vfp.c.inc
40
+++ b/target/arm/translate-vfp.c.inc
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
42
return true;
43
}
44
45
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
46
+{
47
+ arg_vldr_sysreg *a = opaque;
48
+ uint32_t offset = a->imm;
49
+ TCGv_i32 addr;
50
+
51
+ if (!a->a) {
52
+ offset = - offset;
53
+ }
54
+
55
+ addr = load_reg(s, a->rn);
56
+ if (a->p) {
57
+ tcg_gen_addi_i32(addr, addr, offset);
58
+ }
59
+
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
62
+ }
63
+
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
65
+ MO_UL | MO_ALIGN | s->be_data);
66
+ tcg_temp_free_i32(value);
67
+
68
+ if (a->w) {
69
+ /* writeback */
70
+ if (!a->p) {
71
+ tcg_gen_addi_i32(addr, addr, offset);
72
+ }
73
+ store_reg(s, a->rn, addr);
74
+ } else {
75
+ tcg_temp_free_i32(addr);
76
+ }
77
+}
78
+
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
80
+{
81
+ arg_vldr_sysreg *a = opaque;
82
+ uint32_t offset = a->imm;
83
+ TCGv_i32 addr;
84
+ TCGv_i32 value = tcg_temp_new_i32();
85
+
86
+ if (!a->a) {
87
+ offset = - offset;
88
+ }
89
+
90
+ addr = load_reg(s, a->rn);
91
+ if (a->p) {
92
+ tcg_gen_addi_i32(addr, addr, offset);
93
+ }
94
+
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
97
+ }
98
+
99
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
100
+ MO_UL | MO_ALIGN | s->be_data);
101
+
102
+ if (a->w) {
103
+ /* writeback */
104
+ if (!a->p) {
105
+ tcg_gen_addi_i32(addr, addr, offset);
106
+ }
107
+ store_reg(s, a->rn, addr);
108
+ } else {
109
+ tcg_temp_free_i32(addr);
110
+ }
111
+ return value;
112
+}
113
+
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
115
+{
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
117
+ return false;
118
+ }
119
+ if (a->rn == 15) {
120
+ return false;
121
+ }
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
123
+}
124
+
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
126
+{
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
128
+ return false;
129
+ }
130
+ if (a->rn == 15) {
131
+ return false;
132
+ }
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
134
+}
135
+
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
137
{
138
TCGv_i32 tmp;
139
--
140
2.20.1
141
142
diff view generated by jsdifflib
Deleted patch
1
v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
2
like the existing FPSCR, except that it reads and writes only bits
3
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits). (Unlike the
4
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
5
permitted.)
6
1
7
Implement the register. Since we don't yet implement MVE, we handle
8
the QC bit as RES0, with todo comments for where we will need to add
9
support later.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
14
---
15
target/arm/cpu.h | 13 +++++++++++++
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
17
2 files changed, 40 insertions(+)
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
28
+#define FPCR_C (1 << 29) /* FP carry flag */
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
30
+#define FPCR_N (1 << 31) /* FP negative flag */
31
+
32
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
33
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
34
35
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
36
{
37
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
38
#define ARM_VFP_FPEXC 8
39
#define ARM_VFP_FPINST 9
40
#define ARM_VFP_FPINST2 10
41
+/* These ones are M-profile only */
42
+#define ARM_VFP_FPSCR_NZCVQC 2
43
+#define ARM_VFP_VPR 12
44
+#define ARM_VFP_P0 13
45
+#define ARM_VFP_FPCXT_NS 14
46
+#define ARM_VFP_FPCXT_S 15
47
48
/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
49
#define QEMU_VFP_FPSCR_NZCV 0xffff
50
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-vfp.c.inc
53
+++ b/target/arm/translate-vfp.c.inc
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
55
case ARM_VFP_FPSCR:
56
case QEMU_VFP_FPSCR_NZCV:
57
break;
58
+ case ARM_VFP_FPSCR_NZCVQC:
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
60
+ return false;
61
+ }
62
+ break;
63
default:
64
return FPSysRegCheckFailed;
65
}
66
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
67
tcg_temp_free_i32(tmp);
68
gen_lookup_tb(s);
69
break;
70
+ case ARM_VFP_FPSCR_NZCVQC:
71
+ {
72
+ TCGv_i32 fpscr;
73
+ tmp = loadfn(s, opaque);
74
+ /*
75
+ * TODO: when we implement MVE, write the QC bit.
76
+ * For non-MVE, QC is RES0.
77
+ */
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
82
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
83
+ tcg_temp_free_i32(tmp);
84
+ break;
85
+ }
86
default:
87
g_assert_not_reached();
88
}
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
91
storefn(s, opaque, tmp);
92
break;
93
+ case ARM_VFP_FPSCR_NZCVQC:
94
+ /*
95
+ * TODO: MVE has a QC bit, which we probably won't store
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
97
+ * we can just fall through to the FPSCR_NZCV case.
98
+ */
99
case QEMU_VFP_FPSCR_NZCV:
100
/*
101
* Read just NZCV; this is a special case to avoid the
102
--
103
2.20.1
104
105
diff view generated by jsdifflib
Deleted patch
1
We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
2
in the previous commit; use it in a couple of places in existing code,
3
where we're masking out everything except NZCV for the "load to Rt=15
4
sets CPSR.NZCV" special case.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-12-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
18
* helper call for the "VMRS to CPSR.NZCV" insn.
19
*/
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
storefn(s, opaque, tmp);
24
break;
25
default:
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
27
case ARM_VFP_FPSCR:
28
if (a->rt == 15) {
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
31
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
32
} else {
33
tmp = tcg_temp_new_i32();
34
gen_helper_vfp_get_fpscr(tmp, cpu_env);
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
Factor out the code which handles M-profile lazy FP state preservation
2
from full_vfp_access_check(); accesses to the FPCXT_NS register are
3
a special case which need to do just this part (corresponding in the
4
pseudocode to the PreserveFPState() function), and not the full
5
set of actions matching the pseudocode ExecuteFPCheck() which
6
normal FP instructions need to do.
7
1
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
12
---
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
14
1 file changed, 27 insertions(+), 18 deletions(-)
15
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-vfp.c.inc
19
+++ b/target/arm/translate-vfp.c.inc
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
21
return offs;
22
}
23
24
+/*
25
+ * Generate code for M-profile lazy FP state preservation if needed;
26
+ * this corresponds to the pseudocode PreserveFPState() function.
27
+ */
28
+static void gen_preserve_fp_state(DisasContext *s)
29
+{
30
+ if (s->v7m_lspact) {
31
+ /*
32
+ * Lazy state saving affects external memory and also the NVIC,
33
+ * so we must mark it as an IO operation for icount (and cause
34
+ * this to be the last insn in the TB).
35
+ */
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
38
+ gen_io_start();
39
+ }
40
+ gen_helper_v7m_preserve_fp_state(cpu_env);
41
+ /*
42
+ * If the preserve_fp_state helper doesn't throw an exception
43
+ * then it will clear LSPACT; we don't need to repeat this for
44
+ * any further FP insns in this TB.
45
+ */
46
+ s->v7m_lspact = false;
47
+ }
48
+}
49
+
50
/*
51
* Check that VFP access is enabled. If it is, do the necessary
52
* M-profile lazy-FP handling and then return true.
53
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
54
/* Handle M-profile lazy FP state mechanics */
55
56
/* Trigger lazy-state preservation if necessary */
57
- if (s->v7m_lspact) {
58
- /*
59
- * Lazy state saving affects external memory and also the NVIC,
60
- * so we must mark it as an IO operation for icount (and cause
61
- * this to be the last insn in the TB).
62
- */
63
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
64
- s->base.is_jmp = DISAS_UPDATE_EXIT;
65
- gen_io_start();
66
- }
67
- gen_helper_v7m_preserve_fp_state(cpu_env);
68
- /*
69
- * If the preserve_fp_state helper doesn't throw an exception
70
- * then it will clear LSPACT; we don't need to repeat this for
71
- * any further FP insns in this TB.
72
- */
73
- s->v7m_lspact = false;
74
- }
75
+ gen_preserve_fp_state(s);
76
77
/* Update ownership of FP context: set FPCCR.S to match current state */
78
if (s->v8m_fpccr_s_wrong) {
79
--
80
2.20.1
81
82
diff view generated by jsdifflib
Deleted patch
1
In v8.0M, on exception entry the registers R0-R3, R12, APSR and EPSR
2
are zeroed for an exception taken to Non-secure state; for an
3
exception taken to Secure state they become UNKNOWN, and we chose to
4
leave them at their previous values.
5
1
6
In v8.1M the behaviour is specified more tightly and these registers
7
are always zeroed regardless of the security state that the exception
8
targets (see rule R_KPZV). Implement this.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-17-peter.maydell@linaro.org
13
---
14
target/arm/m_helper.c | 16 ++++++++++++----
15
1 file changed, 12 insertions(+), 4 deletions(-)
16
17
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/m_helper.c
20
+++ b/target/arm/m_helper.c
21
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
22
* Clear registers if necessary to prevent non-secure exception
23
* code being able to see register values from secure code.
24
* Where register values become architecturally UNKNOWN we leave
25
- * them with their previous values.
26
+ * them with their previous values. v8.1M is tighter than v8.0M
27
+ * here and always zeroes the caller-saved registers regardless
28
+ * of the security state the exception is targeting.
29
*/
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
31
- if (!targets_secure) {
32
+ if (!targets_secure || arm_feature(env, ARM_FEATURE_V8_1M)) {
33
/*
34
* Always clear the caller-saved registers (they have been
35
* pushed to the stack earlier in v7m_push_stack()).
36
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
37
* v7m_push_callee_stack()).
38
*/
39
int i;
40
+ /*
41
+ * r4..r11 are callee-saves, zero only if background
42
+ * state was Secure (EXCRET.S == 1) and exception
43
+ * targets Non-secure state
44
+ */
45
+ bool zero_callee_saves = !targets_secure &&
46
+ (lr & R_V7M_EXCRET_S_MASK);
47
48
for (i = 0; i < 13; i++) {
49
- /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
50
- if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
51
+ if (i < 4 || i > 11 || zero_callee_saves) {
52
env->regs[i] = 0;
53
}
54
}
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
Deleted patch
1
In v8.1M, vector table fetch failures don't set HFSR.FORCED (see rule
2
R_LLRP). (In previous versions of the architecture this was either
3
required or IMPDEF.)
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-18-peter.maydell@linaro.org
8
---
9
target/arm/m_helper.c | 6 +++++-
10
1 file changed, 5 insertions(+), 1 deletion(-)
11
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
15
+++ b/target/arm/m_helper.c
16
@@ -XXX,XX +XXX,XX @@ load_fail:
17
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
18
* secure); otherwise it targets the same security state as the
19
* underlying exception.
20
+ * In v8.1M HardFaults from vector table fetch fails don't set FORCED.
21
*/
22
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
23
exc_secure = true;
24
}
25
- env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
26
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK;
27
+ if (!arm_feature(env, ARM_FEATURE_V8_1M)) {
28
+ env->v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
29
+ }
30
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
31
return false;
32
}
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
2
and is a read-only IMPDEF register providing implementation specific
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-19-peter.maydell@linaro.org
8
---
9
hw/intc/armv7m_nvic.c | 5 +++++
10
1 file changed, 5 insertions(+)
11
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
15
+++ b/hw/intc/armv7m_nvic.c
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
17
}
18
return val;
19
}
20
+ case 0xcfc:
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
22
+ goto bad_offset;
23
+ }
24
+ return cpu->revidr;
25
case 0xd00: /* CPUID Base. */
26
return cpu->midr;
27
case 0xd04: /* Interrupt Control State (ICSR) */
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
Deleted patch
1
In v8.1M a new exception return check is added which may cause a NOCP
2
UsageFault (see rule R_XLTP): before we clear s0..s15 and the FPSCR
3
we must check whether access to CP10 from the Security state of the
4
returning exception is disabled; if it is then we must take a fault.
5
1
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
7
never cause CP10 accesses to fail.)
8
9
The other v8.1M change to this register-clearing code is that if MVE
10
is implemented VPR must also be cleared, so add a TODO comment to
11
that effect.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
16
---
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
18
1 file changed, 21 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m_helper.c
23
+++ b/target/arm/m_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
25
v7m_exception_taken(cpu, excret, true, false);
26
return;
27
} else {
28
- /* Clear s0..s15 and FPSCR */
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
30
+ /* v8.1M adds this NOCP check */
31
+ bool nsacr_pass = exc_secure ||
32
+ extract32(env->v7m.nsacr, 10, 1);
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
34
+ if (!nsacr_pass) {
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
39
+ v7m_exception_taken(cpu, excret, true, false);
40
+ } else if (!cpacr_pass) {
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
42
+ exc_secure);
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
46
+ v7m_exception_taken(cpu, excret, true, false);
47
+ }
48
+ }
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
50
int i;
51
52
for (i = 0; i < 16; i += 2) {
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
2
The only difference is that:
3
* the old T1 encodings UNDEF if the implementation implements 32
4
Dregs (this is currently architecturally impossible for M-profile)
5
* the new T2 encodings have the implementation-defined option to
6
read from memory (discarding the data) or write UNKNOWN values to
7
memory for the stack slots that would be D16-D31
8
1
9
We choose not to make those accesses, so for us the two
10
instructions behave identically assuming they don't UNDEF.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20201119215617.29887-21-peter.maydell@linaro.org
15
---
16
target/arm/m-nocp.decode | 2 +-
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
18
2 files changed, 26 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m-nocp.decode
23
+++ b/target/arm/m-nocp.decode
24
@@ -XXX,XX +XXX,XX @@
25
26
{
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
30
# VSCCLRM (new in v8.1M) is similar:
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-vfp.c.inc
36
+++ b/target/arm/translate-vfp.c.inc
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
39
return false;
40
}
41
+
42
+ if (a->op) {
43
+ /*
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
45
+ * to take the IMPDEF option to make memory accesses to the stack
46
+ * slots that correspond to the D16-D31 registers (discarding
47
+ * read data and writing UNKNOWN values), so for us the T2
48
+ * encoding behaves identically to the T1 encoding.
49
+ */
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
51
+ return false;
52
+ }
53
+ } else {
54
+ /*
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
56
+ * This is currently architecturally impossible, but we add the
57
+ * check to stay in line with the pseudocode. Note that we must
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
59
+ */
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
61
+ unallocated_encoding(s);
62
+ return true;
63
+ }
64
+ }
65
+
66
/*
67
* If not secure, UNDEF. We must emit code for this
68
* rather than returning false so that this takes
69
--
70
2.20.1
71
72
diff view generated by jsdifflib
Deleted patch
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
checking for stack frame integrity signatures on SG instructions.
3
This bit is not banked, and is always RAZ/WI to Non-secure code.
4
Adjust the code for handling CCR reads and writes to handle this.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-23-peter.maydell@linaro.org
9
---
10
target/arm/cpu.h | 2 ++
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
12
2 files changed, 20 insertions(+), 8 deletions(-)
13
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
19
FIELD(V7M_CCR, DC, 16, 1)
20
FIELD(V7M_CCR, IC, 17, 1)
21
FIELD(V7M_CCR, BP, 18, 1)
22
+FIELD(V7M_CCR, LOB, 19, 1)
23
+FIELD(V7M_CCR, TRD, 20, 1)
24
25
/* V7M SCR bits */
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
30
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
32
}
33
return cpu->env.v7m.scr[attrs.secure];
34
case 0xd14: /* Configuration Control. */
35
- /* The BFHFNMIGN bit is the only non-banked bit; we
36
- * keep it in the non-secure copy of the register.
37
+ /*
38
+ * Non-banked bits: BFHFNMIGN (stored in the NS copy of the register)
39
+ * and TRD (stored in the S copy of the register)
40
*/
41
val = cpu->env.v7m.ccr[attrs.secure];
42
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
cpu->env.v7m.scr[attrs.secure] = value;
45
break;
46
case 0xd14: /* Configuration Control. */
47
+ {
48
+ uint32_t mask;
49
+
50
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
51
goto bad_offset;
52
}
53
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
56
- R_V7M_CCR_BFHFNMIGN_MASK |
57
- R_V7M_CCR_DIV_0_TRP_MASK |
58
- R_V7M_CCR_UNALIGN_TRP_MASK |
59
- R_V7M_CCR_USERSETMPEND_MASK |
60
- R_V7M_CCR_NONBASETHRDENA_MASK);
61
+ mask = R_V7M_CCR_STKALIGN_MASK |
62
+ R_V7M_CCR_BFHFNMIGN_MASK |
63
+ R_V7M_CCR_DIV_0_TRP_MASK |
64
+ R_V7M_CCR_UNALIGN_TRP_MASK |
65
+ R_V7M_CCR_USERSETMPEND_MASK |
66
+ R_V7M_CCR_NONBASETHRDENA_MASK;
67
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && attrs.secure) {
68
+ /* TRD is always RAZ/WI from NS */
69
+ mask |= R_V7M_CCR_TRD_MASK;
70
+ }
71
+ value &= mask;
72
73
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
74
/* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
76
77
cpu->env.v7m.ccr[attrs.secure] = value;
78
break;
79
+ }
80
case 0xd24: /* System Handler Control and State (SHCSR) */
81
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
82
goto bad_offset;
83
--
84
2.20.1
85
86
diff view generated by jsdifflib
Deleted patch
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
checking for stack frame integrity signatures on SG instructions.
3
Add the code in the SG insn implementation for the new behaviour.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
8
---
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 86 insertions(+)
11
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
15
+++ b/target/arm/m_helper.c
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
17
return true;
18
}
19
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
21
+ uint32_t addr, uint32_t *spdata)
22
+{
23
+ /*
24
+ * Read a word of data from the stack for the SG instruction,
25
+ * writing the value into *spdata. If the load succeeds, return
26
+ * true; otherwise pend an appropriate exception and return false.
27
+ * (We can't use data load helpers here that throw an exception
28
+ * because of the context we're called in, which is halfway through
29
+ * arm_v7m_cpu_do_interrupt().)
30
+ */
31
+ CPUState *cs = CPU(cpu);
32
+ CPUARMState *env = &cpu->env;
33
+ MemTxAttrs attrs = {};
34
+ MemTxResult txres;
35
+ target_ulong page_size;
36
+ hwaddr physaddr;
37
+ int prot;
38
+ ARMMMUFaultInfo fi = {};
39
+ ARMCacheAttrs cacheattrs = {};
40
+ uint32_t value;
41
+
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
43
+ &attrs, &prot, &page_size, &fi, &cacheattrs)) {
44
+ /* MPU/SAU lookup failed */
45
+ if (fi.type == ARMFault_QEMU_SFault) {
46
+ qemu_log_mask(CPU_LOG_INT,
47
+ "...SecureFault during stack word read\n");
48
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
49
+ env->v7m.sfar = addr;
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
51
+ } else {
52
+ qemu_log_mask(CPU_LOG_INT,
53
+ "...MemManageFault during stack word read\n");
54
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_DACCVIOL_MASK |
55
+ R_V7M_CFSR_MMARVALID_MASK;
56
+ env->v7m.mmfar[M_REG_S] = addr;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, false);
58
+ }
59
+ return false;
60
+ }
61
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to read the data */
65
+ qemu_log_mask(CPU_LOG_INT,
66
+ "...BusFault during stack word read\n");
67
+ env->v7m.cfsr[M_REG_NS] |=
68
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
69
+ env->v7m.bfar = addr;
70
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
71
+ return false;
72
+ }
73
+
74
+ *spdata = value;
75
+ return true;
76
+}
77
+
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
79
{
80
/*
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
82
*/
83
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
84
", executing it\n", env->regs[15]);
85
+
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
87
+ !arm_v7m_is_handler_mode(env)) {
88
+ /*
89
+ * v8.1M exception stack frame integrity check. Note that we
90
+ * must perform the memory access even if CCR_S.TRD is zero
91
+ * and we aren't going to check what the data loaded is.
92
+ */
93
+ uint32_t spdata, sp;
94
+
95
+ /*
96
+ * We know we are currently NS, so the S stack pointers must be
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
98
+ */
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
101
+ /* Stack access failed and an exception has been pended */
102
+ return false;
103
+ }
104
+
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
106
+ if (((spdata & ~1) == 0xfefa125a) ||
107
+ !(env->v7m.control[M_REG_S] & 1)) {
108
+ goto gen_invep;
109
+ }
110
+ }
111
+ }
112
+
113
env->regs[14] &= ~1;
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
115
switch_v7m_security_state(env, true);
116
--
117
2.20.1
118
119
diff view generated by jsdifflib