1
Second ARM pull request of this week; this one has my next
1
First pullreq for 6.0: mostly my v8.1M work, plus some other
2
set of v8M patches and a handful of more minor stuff from
2
bits and pieces. (I still have a lot of stuff in my to-review
3
other people.
3
folder, which I may or may not get to before the Christmas break...)
4
4
5
thanks
5
thanks
6
-- PMM
6
-- PMM
7
7
8
The following changes since commit 8ee5f9b3ecc94e3eb7a8235f4b2c3ec9024807f6:
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
9
9
10
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2017-09-07 10:45:18 +0100)
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +0000)
11
11
12
are available in the git repository at:
12
are available in the Git repository at:
13
13
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170907
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
15
15
16
for you to fetch changes up to c99a55d38dd5b5131f3fcbbaf41828a09ee62544:
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
17
17
18
target/arm: Add Jazelle feature (2017-09-07 13:54:55 +0100)
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
19
19
20
----------------------------------------------------------------
20
----------------------------------------------------------------
21
target-arm:
21
target-arm queue:
22
* cleanups converting to DEFINE_PROP_LINK
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
23
* allwinner-a10: mark as not user-creatable
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
24
* initial patches working towards ARMv8M support
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
25
* implement generating aborts on memory transaction failures
25
* Various minor code cleanups
26
* make BXJ behave correctly (ie not UNDEF) on ARMv6-and-later
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
27
* Implement more pieces of ARMv8.1M support
27
28
28
----------------------------------------------------------------
29
----------------------------------------------------------------
29
Fam Zheng (6):
30
Alex Chen (4):
30
armv7m: Convert bitband.source-memory to DEFINE_PROP_LINK
31
i.MX25: Fix bad printf format specifiers
31
armv7m: Convert armv7m.memory to DEFINE_PROP_LINK
32
i.MX31: Fix bad printf format specifiers
32
gicv3: Convert to DEFINE_PROP_LINK
33
i.MX6: Fix bad printf format specifiers
33
xlnx_zynqmp: Convert to DEFINE_PROP_LINK
34
i.MX6ul: Fix bad printf format specifiers
34
xilinx_axienet: Convert to DEFINE_PROP_LINK
35
xilinx_axidma: Convert to DEFINE_PROP_LINK
36
35
37
Peter Maydell (23):
36
Havard Skinnemoen (1):
38
target/arm: Implement ARMv8M's PMSAv8 registers
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
39
target/arm: Implement new PMSAv8 behaviour
40
target/arm: Add state field, feature bit and migration for v8M secure state
41
target/arm: Register second AddressSpace for secure v8M CPUs
42
target/arm: Add MMU indexes for secure v8M
43
target/arm: Make BASEPRI register banked for v8M
44
target/arm: Make PRIMASK register banked for v8M
45
target/arm: Make FAULTMASK register banked for v8M
46
target/arm: Make CONTROL register banked for v8M
47
nvic: Add NS alias SCS region
48
target/arm: Make VTOR register banked for v8M
49
target/arm: Make MPU_MAIR0, MPU_MAIR1 registers banked for v8M
50
target/arm: Make MPU_RBAR, MPU_RLAR banked for v8M
51
target/arm: Make MPU_RNR register banked for v8M
52
target/arm: Make MPU_CTRL register banked for v8M
53
target/arm: Make CCR register banked for v8M
54
target/arm: Make MMFAR banked for v8M
55
target/arm: Make CFSR register banked for v8M
56
target/arm: Move regime_is_secure() to target/arm/internals.h
57
target/arm: Implement BXNS, and banked stack pointers
58
boards.h: Define new flag ignore_memory_transaction_failures
59
hw/arm: Set ignore_memory_transaction_failures for most ARM boards
60
target/arm: Implement new do_transaction_failed hook
61
38
62
Portia Stephens (1):
39
Kunkun Jiang (1):
63
target/arm: Add Jazelle feature
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
64
41
65
Thomas Huth (1):
42
Marcin Juszkiewicz (1):
66
hw/arm/allwinner-a10: Mark the allwinner-a10 device with user_creatable = false
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
67
44
68
include/hw/boards.h | 11 ++
45
Peter Maydell (25):
69
include/hw/intc/armv7m_nvic.h | 1 +
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
70
include/qom/cpu.h | 7 +-
47
target/arm: Implement v8.1M PXN extension
71
target/arm/cpu.h | 101 ++++++++++++--
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
72
target/arm/helper.h | 2 +
49
target/arm: Implement VSCCLRM insn
73
target/arm/internals.h | 36 +++++
50
target/arm: Implement CLRM instruction
74
target/arm/translate.h | 1 +
51
target/arm: Enforce M-profile VMRS/VMSR register restrictions
75
hw/arm/allwinner-a10.c | 2 +
52
target/arm: Refactor M-profile VMSR/VMRS handling
76
hw/arm/armv7m.c | 16 +--
53
target/arm: Move general-use constant expanders up in translate.c
77
hw/arm/aspeed.c | 3 +
54
target/arm: Implement VLDR/VSTR system register
78
hw/arm/collie.c | 1 +
55
target/arm: Implement M-profile FPSCR_nzcvqc
79
hw/arm/cubieboard.c | 1 +
56
target/arm: Use new FPCR_NZCV_MASK constant
80
hw/arm/digic_boards.c | 1 +
57
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
81
hw/arm/exynos4_boards.c | 2 +
58
target/arm: Implement FPCXT_S fp system register
82
hw/arm/gumstix.c | 2 +
59
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
83
hw/arm/highbank.c | 2 +
60
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
84
hw/arm/imx25_pdk.c | 1 +
61
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
85
hw/arm/integratorcp.c | 1 +
62
target/arm: Implement v8.1M REVIDR register
86
hw/arm/kzm.c | 1 +
63
target/arm: Implement new v8.1M NOCP check for exception return
87
hw/arm/mainstone.c | 1 +
64
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
88
hw/arm/musicpal.c | 1 +
65
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
89
hw/arm/netduino2.c | 1 +
66
target/arm: Implement CCR_S.TRD behaviour for SG insns
90
hw/arm/nseries.c | 2 +
67
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
91
hw/arm/omap_sx1.c | 2 +
68
target/arm: Implement M-profile "minimal RAS implementation"
92
hw/arm/palm.c | 1 +
69
hw/intc/armv7m_nvic: Implement read/write for RAS register block
93
hw/arm/raspi.c | 1 +
70
hw/arm/armv7m: Correct typo in QOM object name
94
hw/arm/realview.c | 4 +
95
hw/arm/sabrelite.c | 1 +
96
hw/arm/spitz.c | 4 +
97
hw/arm/stellaris.c | 2 +
98
hw/arm/tosa.c | 1 +
99
hw/arm/versatilepb.c | 2 +
100
hw/arm/vexpress.c | 1 +
101
hw/arm/xilinx_zynq.c | 1 +
102
hw/arm/xlnx-ep108.c | 2 +
103
hw/arm/xlnx-zynqmp.c | 7 +-
104
hw/arm/z2.c | 1 +
105
hw/dma/xilinx_axidma.c | 16 +--
106
hw/intc/arm_gicv3_its_kvm.c | 19 +--
107
hw/intc/armv7m_nvic.c | 291 ++++++++++++++++++++++++++++++++------
108
hw/net/xilinx_axienet.c | 16 +--
109
qom/cpu.c | 16 +++
110
target/arm/cpu.c | 88 +++++++++---
111
target/arm/helper.c | 315 +++++++++++++++++++++++++++++++++---------
112
target/arm/machine.c | 105 ++++++++++++--
113
target/arm/op_helper.c | 43 ++++++
114
target/arm/translate.c | 54 +++++++-
115
scripts/device-crash-test | 1 -
116
48 files changed, 978 insertions(+), 213 deletions(-)
117
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
New patch
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
1
2
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
4
Descriptor is 5 bits([4:0]).
5
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
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>
10
Acked-by: Eric Auger <eric.auger@redhat.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/smmuv3-internal.h | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
19
+++ b/hw/arm/smmuv3-internal.h
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
21
return hi << 32 | lo;
22
}
23
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
26
27
#endif
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
4
Message-id: 20170905131149.10669-4-famz@redhat.com
4
implementation. Bus connection and socketCAN connection for each CAN module
5
can be set through command lines.
6
7
Example for using single CAN:
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
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
26
---
8
hw/intc/arm_gicv3_its_kvm.c | 19 +++++++------------
27
meson.build | 1 +
9
1 file changed, 7 insertions(+), 12 deletions(-)
28
hw/net/can/trace.h | 1 +
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
31
hw/Kconfig | 1 +
32
hw/net/can/meson.build | 1 +
33
hw/net/can/trace-events | 9 +
34
7 files changed, 1252 insertions(+)
35
create mode 100644 hw/net/can/trace.h
36
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
37
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
38
create mode 100644 hw/net/can/trace-events
10
39
11
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
40
diff --git a/meson.build b/meson.build
12
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/arm_gicv3_its_kvm.c
42
--- a/meson.build
14
+++ b/hw/intc/arm_gicv3_its_kvm.c
43
+++ b/meson.build
15
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
44
@@ -XXX,XX +XXX,XX @@ if have_system
16
qemu_add_vm_change_state_handler(vm_change_state_handler, s);
45
'hw/misc',
17
}
46
'hw/misc/macio',
18
47
'hw/net',
19
-static void kvm_arm_its_init(Object *obj)
48
+ 'hw/net/can',
20
-{
49
'hw/nvram',
21
- GICv3ITSState *s = KVM_ARM_ITS(obj);
50
'hw/pci',
22
-
51
'hw/pci-host',
23
- object_property_add_link(obj, "parent-gicv3",
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
24
- "kvm-arm-gicv3", (Object **)&s->gicv3,
53
new file mode 100644
25
- object_property_allow_set_link,
54
index XXXXXXX..XXXXXXX
26
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
55
--- /dev/null
27
- &error_abort);
56
+++ b/hw/net/can/trace.h
28
-}
57
@@ -0,0 +1 @@
29
-
58
+#include "trace/trace-hw_net_can.h"
30
/**
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
31
* kvm_arm_its_pre_save - handles the saving of ITS registers.
60
new file mode 100644
32
* ITS tables are flushed into guest RAM separately and earlier,
61
index XXXXXXX..XXXXXXX
33
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_post_load(GICv3ITSState *s)
62
--- /dev/null
34
GITS_CTLR, &s->ctlr, true, &error_abort);
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
35
}
64
@@ -XXX,XX +XXX,XX @@
36
65
+/*
37
+static Property kvm_arm_its_props[] = {
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
38
+ DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "kvm-arm-gicv3",
67
+ *
39
+ GICv3State *),
68
+ * Copyright (c) 2020 Xilinx Inc.
69
+ *
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
71
+ *
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
73
+ * Pavel Pisa.
74
+ *
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
76
+ * of this software and associated documentation files (the "Software"), to deal
77
+ * in the Software without restriction, including without limitation the rights
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
+ * copies of the Software, and to permit persons to whom the Software is
80
+ * furnished to do so, subject to the following conditions:
81
+ *
82
+ * The above copyright notice and this permission notice shall be included in
83
+ * all copies or substantial portions of the Software.
84
+ *
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91
+ * THE SOFTWARE.
92
+ */
93
+
94
+#ifndef XLNX_ZYNQMP_CAN_H
95
+#define XLNX_ZYNQMP_CAN_H
96
+
97
+#include "hw/register.h"
98
+#include "net/can_emu.h"
99
+#include "net/can_host.h"
100
+#include "qemu/fifo32.h"
101
+#include "hw/ptimer.h"
102
+#include "hw/qdev-clock.h"
103
+
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
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
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
144
new file mode 100644
145
index XXXXXXX..XXXXXXX
146
--- /dev/null
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
148
@@ -XXX,XX +XXX,XX @@
149
+/*
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
151
+ * This implementation is based on the following datasheet:
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
153
+ *
154
+ * Copyright (c) 2020 Xilinx Inc.
155
+ *
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
157
+ *
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
159
+ * Pavel Pisa
160
+ *
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
162
+ * of this software and associated documentation files (the "Software"), to deal
163
+ * in the Software without restriction, including without limitation the rights
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
165
+ * copies of the Software, and to permit persons to whom the Software is
166
+ * furnished to do so, subject to the following conditions:
167
+ *
168
+ * The above copyright notice and this permission notice shall be included in
169
+ * all copies or substantial portions of the Software.
170
+ *
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
177
+ * THE SOFTWARE.
178
+ */
179
+
180
+#include "qemu/osdep.h"
181
+#include "hw/sysbus.h"
182
+#include "hw/register.h"
183
+#include "hw/irq.h"
184
+#include "qapi/error.h"
185
+#include "qemu/bitops.h"
186
+#include "qemu/log.h"
187
+#include "qemu/cutils.h"
188
+#include "sysemu/sysemu.h"
189
+#include "migration/vmstate.h"
190
+#include "hw/qdev-properties.h"
191
+#include "net/can_emu.h"
192
+#include "net/can_host.h"
193
+#include "qemu/event_notifier.h"
194
+#include "qom/object_interfaces.h"
195
+#include "hw/net/xlnx-zynqmp-can.h"
196
+#include "trace.h"
197
+
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
200
+#endif
201
+
202
+#define MAX_DLC 8
203
+#undef ERROR
204
+
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
208
+REG32(MODE_SELECT_REGISTER, 0x4)
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
227
+REG32(STATUS_REGISTER, 0x18)
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
288
+REG32(TIMESTAMP_REGISTER, 0x28)
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
290
+REG32(WIR, 0x2c)
291
+ FIELD(WIR, EW, 8, 8)
292
+ FIELD(WIR, FW, 0, 8)
293
+REG32(TXFIFO_ID, 0x30)
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
299
+REG32(TXFIFO_DLC, 0x34)
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
301
+REG32(TXFIFO_DATA1, 0x38)
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
304
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
305
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
306
+REG32(TXFIFO_DATA2, 0x3c)
307
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
308
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
309
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
310
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
311
+REG32(TXHPB_ID, 0x40)
312
+ FIELD(TXHPB_ID, IDH, 21, 11)
313
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
314
+ FIELD(TXHPB_ID, IDE, 19, 1)
315
+ FIELD(TXHPB_ID, IDL, 1, 18)
316
+ FIELD(TXHPB_ID, RTR, 0, 1)
317
+REG32(TXHPB_DLC, 0x44)
318
+ FIELD(TXHPB_DLC, DLC, 28, 4)
319
+REG32(TXHPB_DATA1, 0x48)
320
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
321
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
322
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
323
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
324
+REG32(TXHPB_DATA2, 0x4c)
325
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
326
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
327
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
328
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
329
+REG32(RXFIFO_ID, 0x50)
330
+ FIELD(RXFIFO_ID, IDH, 21, 11)
331
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
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
+{
404
+ uint32_t irq;
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
+}
442
+
443
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val)
444
+{
445
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
446
+
447
+ can_update_irq(s);
448
+}
449
+
450
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val)
451
+{
452
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
453
+
454
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
455
+ can_update_irq(s);
456
+
457
+ return 0;
458
+}
459
+
460
+static void can_config_reset(XlnxZynqMPCANState *s)
461
+{
462
+ /* Reset all the configuration registers. */
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
+}
474
+
475
+static void can_config_mode(XlnxZynqMPCANState *s)
476
+{
477
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
478
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
479
+
480
+ /* Put XlnxZynqMPCAN in configuration mode. */
481
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
482
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
483
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
484
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
485
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
486
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
487
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
488
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
489
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
490
+
491
+ can_update_irq(s);
492
+}
493
+
494
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
495
+{
496
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
497
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
498
+ /* Wake up interrupt bit. */
499
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
500
+ /* Sleep interrupt bit. */
501
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
502
+
503
+ /* Clear previous core mode status bits. */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
505
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
506
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
507
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
508
+
509
+ /* set current mode bit and generate irqs accordingly. */
510
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
511
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
512
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
513
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
514
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
515
+ sleep_irq_val);
516
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
517
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
518
+ } else {
519
+ /*
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
521
+ */
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
523
+ /* Set wakeup interrupt bit. */
524
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
525
+ wakeup_irq_val);
526
+ }
527
+
528
+ can_update_irq(s);
529
+}
530
+
531
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
532
+{
533
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
534
+ update_status_register_mode_bits(s);
535
+}
536
+
537
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
538
+{
539
+ frame->can_id = data[0];
540
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
541
+
542
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
543
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
544
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
545
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
546
+
547
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
548
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
549
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
550
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
551
+}
552
+
553
+static bool tx_ready_check(XlnxZynqMPCANState *s)
554
+{
555
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
556
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
557
+
558
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
559
+ " data while controller is in reset mode.\n",
560
+ path);
561
+ return false;
562
+ }
563
+
564
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
565
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
566
+
567
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
568
+ " data while controller is in configuration mode. Reset"
569
+ " the core so operations can start fresh.\n",
570
+ path);
571
+ return false;
572
+ }
573
+
574
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
575
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
576
+
577
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
578
+ " data while controller is in SNOOP MODE.\n",
579
+ path);
580
+ return false;
581
+ }
582
+
583
+ return true;
584
+}
585
+
586
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
587
+{
588
+ qemu_can_frame frame;
589
+ uint32_t data[CAN_FRAME_SIZE];
590
+ int i;
591
+ bool can_tx = tx_ready_check(s);
592
+
593
+ if (!can_tx) {
594
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
595
+
596
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for data"
597
+ " transfer.\n", path);
598
+ can_update_irq(s);
599
+ return;
600
+ }
601
+
602
+ while (!fifo32_is_empty(fifo)) {
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
604
+ data[i] = fifo32_pop(fifo);
605
+ }
606
+
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
608
+ /*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
611
+ * Any message transmitted is looped back to the RX line and
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
613
+ * that it transmits.
614
+ */
615
+ if (fifo32_is_full(&s->rx_fifo)) {
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
617
+ } else {
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
619
+ fifo32_push(&s->rx_fifo, data[i]);
620
+ }
621
+
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
623
+ }
624
+ } else {
625
+ /* Normal mode Tx. */
626
+ generate_frame(&frame, data);
627
+
628
+ trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc,
629
+ frame.data[0], frame.data[1],
630
+ frame.data[2], frame.data[3],
631
+ frame.data[4], frame.data[5],
632
+ frame.data[6], frame.data[7]);
633
+ can_bus_client_send(&s->bus_client, &frame, 1);
634
+ }
635
+ }
636
+
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
639
+
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
641
+ can_exit_sleep_mode(s);
642
+ }
643
+
644
+ can_update_irq(s);
645
+}
646
+
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
648
+{
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
650
+
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
653
+
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
655
+ trace_xlnx_can_reset(val);
656
+
657
+ /* First, core will do software reset then will enter in config mode. */
658
+ can_config_reset(s);
659
+ }
660
+
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
662
+ can_config_mode(s);
663
+ } else {
664
+ /*
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
667
+ * register states.
668
+ */
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
670
+
671
+ ptimer_transaction_begin(s->can_timer);
672
+ ptimer_set_count(s->can_timer, 0);
673
+ ptimer_transaction_commit(s->can_timer);
674
+
675
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
676
+ transfer_fifo(s, &s->txhpb_fifo);
677
+ transfer_fifo(s, &s->tx_fifo);
678
+ }
679
+
680
+ update_status_register_mode_bits(s);
681
+
682
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
683
+}
684
+
685
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val)
686
+{
687
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
688
+ uint8_t multi_mode;
689
+
690
+ /*
691
+ * Multiple mode set check. This is done to make sure user doesn't set
692
+ * multiple modes.
693
+ */
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
697
+
698
+ if (multi_mode > 1) {
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
700
+
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
702
+ " several modes simultaneously. One mode will be selected"
703
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
704
+ path);
705
+ }
706
+
707
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
708
+ /* We are in configuration mode, any mode can be selected. */
709
+ s->regs[R_MODE_SELECT_REGISTER] = val;
710
+ } else {
711
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
712
+
713
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
714
+
715
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
716
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
717
+
718
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
719
+ " LBACK mode without setting CEN bit as 0.\n",
720
+ path);
721
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
722
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
723
+
724
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
725
+ " SNOOP mode without setting CEN bit as 0.\n",
726
+ path);
727
+ }
728
+
729
+ update_status_register_mode_bits(s);
730
+ }
731
+
732
+ return s->regs[R_MODE_SELECT_REGISTER];
733
+}
734
+
735
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val)
736
+{
737
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
738
+
739
+ /* Only allow writes when in config mode. */
740
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
741
+ return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
742
+ }
743
+
744
+ return val;
745
+}
746
+
747
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val)
748
+{
749
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
750
+
751
+ /* Only allow writes when in config mode. */
752
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
753
+ return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
754
+ }
755
+
756
+ return val;
757
+}
758
+
759
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val)
760
+{
761
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
762
+
763
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
764
+ ptimer_transaction_begin(s->can_timer);
765
+ ptimer_set_count(s->can_timer, 0);
766
+ ptimer_transaction_commit(s->can_timer);
767
+ }
768
+
769
+ return 0;
770
+}
771
+
772
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
773
+{
774
+ bool filter_pass = false;
775
+ uint16_t timestamp = 0;
776
+
777
+ /* If no filter is enabled. Message will be stored in FIFO. */
778
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
779
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
780
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
781
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
782
+ filter_pass = true;
783
+ }
784
+
785
+ /*
786
+ * Messages that pass any of the acceptance filters will be stored in
787
+ * the RX FIFO.
788
+ */
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
790
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
799
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
808
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
809
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
810
+
811
+ if (filter_id_masked == id_masked) {
812
+ filter_pass = true;
813
+ }
814
+ }
815
+
816
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
817
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
818
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
819
+
820
+ if (filter_id_masked == id_masked) {
821
+ filter_pass = true;
822
+ }
823
+ }
824
+
825
+ if (!filter_pass) {
826
+ trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc);
827
+ return;
828
+ }
829
+
830
+ /* Store the message in fifo if it passed through any of the filters. */
831
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
832
+
833
+ if (fifo32_is_full(&s->rx_fifo)) {
834
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
835
+ } else {
836
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
837
+
838
+ fifo32_push(&s->rx_fifo, frame->can_id);
839
+
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
841
+ R_RXFIFO_DLC_DLC_LENGTH,
842
+ frame->can_dlc) |
843
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
844
+ R_RXFIFO_DLC_RXT_LENGTH,
845
+ timestamp));
846
+
847
+ /* First 32 bit of the data. */
848
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
849
+ R_TXFIFO_DATA1_DB3_LENGTH,
850
+ frame->data[0]) |
851
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
852
+ R_TXFIFO_DATA1_DB2_LENGTH,
853
+ frame->data[1]) |
854
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
855
+ R_TXFIFO_DATA1_DB1_LENGTH,
856
+ frame->data[2]) |
857
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
858
+ R_TXFIFO_DATA1_DB0_LENGTH,
859
+ frame->data[3]));
860
+ /* Last 32 bit of the data. */
861
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
862
+ R_TXFIFO_DATA2_DB7_LENGTH,
863
+ frame->data[4]) |
864
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
865
+ R_TXFIFO_DATA2_DB6_LENGTH,
866
+ frame->data[5]) |
867
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
868
+ R_TXFIFO_DATA2_DB5_LENGTH,
869
+ frame->data[6]) |
870
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
871
+ R_TXFIFO_DATA2_DB4_LENGTH,
872
+ frame->data[7]));
873
+
874
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
875
+ trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc,
876
+ frame->data[0], frame->data[1],
877
+ frame->data[2], frame->data[3],
878
+ frame->data[4], frame->data[5],
879
+ frame->data[6], frame->data[7]);
880
+ }
881
+
882
+ can_update_irq(s);
883
+ }
884
+}
885
+
886
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
887
+{
888
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
889
+
890
+ if (!fifo32_is_empty(&s->rx_fifo)) {
891
+ val = fifo32_pop(&s->rx_fifo);
892
+ } else {
893
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
894
+ }
895
+
896
+ can_update_irq(s);
897
+ return val;
898
+}
899
+
900
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val)
901
+{
902
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
903
+
904
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
905
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
906
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
907
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
909
+ } else {
910
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
911
+ }
912
+}
913
+
914
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val)
915
+{
916
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
917
+ uint32_t reg_idx = (reg->access->addr) / 4;
918
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
919
+
920
+ /* modify an acceptance filter, the corresponding UAF bit should be '0'. */
921
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
922
+ s->regs[reg_idx] = val;
923
+
924
+ trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_idx]);
925
+ } else {
926
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
927
+
928
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
929
+ " mask is not set as corresponding UAF bit is not 0.\n",
930
+ path, filter_number + 1);
931
+ }
932
+
933
+ return s->regs[reg_idx];
934
+}
935
+
936
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val)
937
+{
938
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
939
+ uint32_t reg_idx = (reg->access->addr) / 4;
940
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
941
+
942
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
943
+ s->regs[reg_idx] = val;
944
+
945
+ trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]);
946
+ } else {
947
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
948
+
949
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
950
+ " id is not set as corresponding UAF bit is not 0.\n",
951
+ path, filter_number + 1);
952
+ }
953
+
954
+ return s->regs[reg_idx];
955
+}
956
+
957
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val)
958
+{
959
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
960
+
961
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
962
+
963
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
964
+ (reg->access->addr == A_TXHPB_DATA2);
965
+
966
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
967
+
968
+ if (!fifo32_is_full(f)) {
969
+ fifo32_push(f, val);
970
+ } else {
971
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
972
+
973
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
974
+ }
975
+
976
+ /* Initiate the message send if TX register is written. */
977
+ if (initiate_transfer &&
978
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
979
+ transfer_fifo(s, f);
980
+ }
981
+
982
+ can_update_irq(s);
983
+}
984
+
985
+static const RegisterAccessInfo can_regs_info[] = {
986
+ { .name = "SOFTWARE_RESET_REGISTER",
987
+ .addr = A_SOFTWARE_RESET_REGISTER,
988
+ .rsvd = 0xfffffffc,
989
+ .pre_write = can_srr_pre_write,
990
+ },{ .name = "MODE_SELECT_REGISTER",
991
+ .addr = A_MODE_SELECT_REGISTER,
992
+ .rsvd = 0xfffffff8,
993
+ .pre_write = can_msr_pre_write,
994
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
995
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
996
+ .rsvd = 0xffffff00,
997
+ .pre_write = can_brpr_pre_write,
998
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
999
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
1000
+ .rsvd = 0xfffffe00,
1001
+ .pre_write = can_btr_pre_write,
1002
+ },{ .name = "ERROR_COUNTER_REGISTER",
1003
+ .addr = A_ERROR_COUNTER_REGISTER,
1004
+ .rsvd = 0xffff0000,
1005
+ .ro = 0xffffffff,
1006
+ },{ .name = "ERROR_STATUS_REGISTER",
1007
+ .addr = A_ERROR_STATUS_REGISTER,
1008
+ .rsvd = 0xffffffe0,
1009
+ .w1c = 0x1f,
1010
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
1011
+ .reset = 0x1,
1012
+ .rsvd = 0xffffe000,
1013
+ .ro = 0x1fff,
1014
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
1015
+ .addr = A_INTERRUPT_STATUS_REGISTER,
1016
+ .reset = 0x6000,
1017
+ .rsvd = 0xffff8000,
1018
+ .ro = 0x7fff,
1019
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1020
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1021
+ .rsvd = 0xffff8000,
1022
+ .post_write = can_ier_post_write,
1023
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1024
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1025
+ .rsvd = 0xffff8000,
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 *),
40
+ DEFINE_PROP_END_OF_LIST(),
1281
+ DEFINE_PROP_END_OF_LIST(),
41
+};
1282
+};
42
+
1283
+
43
static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
44
{
1285
+{
45
DeviceClass *dc = DEVICE_CLASS(klass);
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
46
GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
47
1288
+
48
dc->realize = kvm_arm_its_realize;
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
49
+ dc->props = kvm_arm_its_props;
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
50
icc->send_msi = kvm_its_send_msi;
1291
+ dc->realize = xlnx_zynqmp_can_realize;
51
icc->pre_save = kvm_arm_its_pre_save;
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
52
icc->post_load = kvm_arm_its_post_load;
1293
+ dc->vmsd = &vmstate_can;
53
@@ -XXX,XX +XXX,XX @@ static const TypeInfo kvm_arm_its_info = {
1294
+}
54
.name = TYPE_KVM_ARM_ITS,
1295
+
55
.parent = TYPE_ARM_GICV3_ITS_COMMON,
1296
+static const TypeInfo can_info = {
56
.instance_size = sizeof(GICv3ITSState),
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
57
- .instance_init = kvm_arm_its_init,
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
58
.class_init = kvm_arm_its_class_init,
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
59
};
1300
+ .class_init = xlnx_zynqmp_can_class_init,
60
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"
61
--
1343
--
62
2.7.4
1344
2.20.1
63
1345
64
1346
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
Connect CAN0 and CAN1 on the ZynqMP.
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
5
Message-id: 20170905131149.10669-5-famz@redhat.com
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
hw/arm/xlnx-zynqmp.c | 7 ++-----
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
10
1 file changed, 2 insertions(+), 5 deletions(-)
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
14
3 files changed, 62 insertions(+)
11
15
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/intc/arm_gic.h"
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
}
113
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
12
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
13
index XXXXXXX..XXXXXXX 100644
116
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/xlnx-zynqmp.c
117
--- a/hw/arm/xlnx-zynqmp.c
15
+++ b/hw/arm/xlnx-zynqmp.c
118
+++ b/hw/arm/xlnx-zynqmp.c
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
120
21, 22,
121
};
122
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
124
+ 0xFF060000, 0xFF070000,
125
+};
126
+
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
128
+ 23, 24,
129
+};
130
+
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
132
0xFF160000, 0xFF170000,
133
};
16
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
17
&error_abort);
135
TYPE_CADENCE_UART);
18
}
136
}
19
137
20
- object_property_add_link(obj, "ddr-ram", TYPE_MEMORY_REGION,
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
21
- (Object **)&s->ddr_ram,
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
22
- qdev_prop_allow_set_link_before_realize,
140
+ TYPE_XLNX_ZYNQMP_CAN);
23
- OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
141
+ }
24
-
142
+
25
object_initialize(&s->gic, sizeof(s->gic), gic_class_name());
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
26
qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
144
27
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
147
gic_spi[uart_intr[i]]);
148
}
149
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
153
+
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
155
+ OBJECT(s->canbus[i]), &error_fatal);
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)) {
28
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
29
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
30
DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
31
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
32
+ DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
33
+ MemoryRegion *),
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 *),
34
DEFINE_PROP_END_OF_LIST()
178
DEFINE_PROP_END_OF_LIST()
35
};
179
};
36
180
37
--
181
--
38
2.7.4
182
2.20.1
39
183
40
184
diff view generated by jsdifflib
New patch
1
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
4
Tests the CAN controller in loopback, sleep and snoop mode.
5
Tests filtering of incoming CAN messages.
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
14
tests/qtest/meson.build | 1 +
15
2 files changed, 361 insertions(+)
16
create mode 100644 tests/qtest/xlnx-can-test.c
17
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qtest/xlnx-can-test.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QTests for the Xilinx ZynqMP CAN controller.
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
+ */
49
+
50
+#include "qemu/osdep.h"
51
+#include "libqos/libqtest.h"
52
+
53
+/* Base address. */
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
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
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
+}
111
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
113
+{
114
+ uint32_t int_status;
115
+
116
+ /* Read the interrupt on CAN rx. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
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
+}
130
+
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
386
--- a/tests/qtest/meson.build
387
+++ b/tests/qtest/meson.build
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
389
['arm-cpu-features',
390
'numa-test',
391
'boot-serial-test',
392
+ 'xlnx-can-test',
393
'migration-test']
394
395
qtests_s390x = \
396
--
397
2.20.1
398
399
diff view generated by jsdifflib
New patch
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
2
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: Fam Zheng <famz@redhat.com>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
it for QEMU as well. A53 was already enabled there.
5
Message-id: 20170905131149.10669-2-famz@redhat.com
5
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
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
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
13
---
9
hw/arm/armv7m.c | 8 ++------
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
10
1 file changed, 2 insertions(+), 6 deletions(-)
15
1 file changed, 20 insertions(+), 3 deletions(-)
11
16
12
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/armv7m.c
19
--- a/hw/arm/sbsa-ref.c
15
+++ b/hw/arm/armv7m.c
20
+++ b/hw/arm/sbsa-ref.c
16
@@ -XXX,XX +XXX,XX @@ static void bitband_init(Object *obj)
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
17
BitBandState *s = BITBAND(obj);
22
[SBSA_GWDT] = 16,
18
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
19
20
- object_property_add_link(obj, "source-memory",
21
- TYPE_MEMORY_REGION,
22
- (Object **)&s->source_memory,
23
- qdev_prop_allow_set_link_before_realize,
24
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
25
- &error_abort);
26
memory_region_init_io(&s->iomem, obj, &bitband_ops, s,
27
"bitband", 0x02000000);
28
sysbus_init_mmio(dev, &s->iomem);
29
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
30
31
static Property bitband_properties[] = {
32
DEFINE_PROP_UINT32("base", BitBandState, base, 0),
33
+ DEFINE_PROP_LINK("source-memory", BitBandState, source_memory,
34
+ TYPE_MEMORY_REGION, MemoryRegion *),
35
DEFINE_PROP_END_OF_LIST(),
36
};
23
};
37
24
25
+static const char * const valid_cpus[] = {
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
29
+};
30
+
31
+static bool cpu_type_valid(const char *cpu)
32
+{
33
+ int i;
34
+
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
}
57
38
--
58
--
39
2.7.4
59
2.20.1
40
60
41
61
diff view generated by jsdifflib
1
Set the MachineClass flag ignore_memory_transaction_failures
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
for almost all ARM boards. This means they retain the legacy
3
behaviour that accesses to unimplemented addresses will RAZ/WI
4
rather than aborting, when a subsequent commit adds support
5
for external aborts.
6
2
7
The exceptions are:
3
Dump the collected random data after a randomness test failure.
8
* virt -- we know that guests won't try to prod devices
9
that we don't describe in the device tree or ACPI tables
10
* mps2 -- this board was written to use unimplemented-device
11
for all the ranges with devices we don't yet handle
12
4
13
New boards should not set the flag, but instead be written
5
Note that this relies on the test having called
14
like the mps2.
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
7
assertion failure.
15
8
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: minor commit message tweak]
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
18
Message-id: 1504626814-23124-3-git-send-email-peter.maydell@linaro.org
19
For the Xilinx boards:
20
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
21
---
13
---
22
hw/arm/aspeed.c | 3 +++
14
tests/qtest/npcm7xx_rng-test.c | 12 ++++++++++++
23
hw/arm/collie.c | 1 +
15
1 file changed, 12 insertions(+)
24
hw/arm/cubieboard.c | 1 +
25
hw/arm/digic_boards.c | 1 +
26
hw/arm/exynos4_boards.c | 2 ++
27
hw/arm/gumstix.c | 2 ++
28
hw/arm/highbank.c | 2 ++
29
hw/arm/imx25_pdk.c | 1 +
30
hw/arm/integratorcp.c | 1 +
31
hw/arm/kzm.c | 1 +
32
hw/arm/mainstone.c | 1 +
33
hw/arm/musicpal.c | 1 +
34
hw/arm/netduino2.c | 1 +
35
hw/arm/nseries.c | 2 ++
36
hw/arm/omap_sx1.c | 2 ++
37
hw/arm/palm.c | 1 +
38
hw/arm/raspi.c | 1 +
39
hw/arm/realview.c | 4 ++++
40
hw/arm/sabrelite.c | 1 +
41
hw/arm/spitz.c | 4 ++++
42
hw/arm/stellaris.c | 2 ++
43
hw/arm/tosa.c | 1 +
44
hw/arm/versatilepb.c | 2 ++
45
hw/arm/vexpress.c | 1 +
46
hw/arm/xilinx_zynq.c | 1 +
47
hw/arm/xlnx-ep108.c | 2 ++
48
hw/arm/z2.c | 1 +
49
27 files changed, 43 insertions(+)
50
16
51
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
52
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/aspeed.c
19
--- a/tests/qtest/npcm7xx_rng-test.c
54
+++ b/hw/arm/aspeed.c
20
+++ b/tests/qtest/npcm7xx_rng-test.c
55
@@ -XXX,XX +XXX,XX @@ static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
21
@@ -XXX,XX +XXX,XX @@
56
mc->no_floppy = 1;
22
57
mc->no_cdrom = 1;
23
#include "libqtest-single.h"
58
mc->no_parallel = 1;
24
#include "qemu/bitops.h"
59
+ mc->ignore_memory_transaction_failures = true;
25
+#include "qemu-common.h"
26
27
#define RNG_BASE_ADDR 0xf000b000
28
29
@@ -XXX,XX +XXX,XX @@
30
/* Number of bits to collect for randomness tests. */
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
}
45
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
47
+ dump_buf_if_failed(buf, sizeof(buf));
60
}
48
}
61
49
62
static const TypeInfo palmetto_bmc_type = {
50
/*
63
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_class_init(ObjectClass *oc, void *data)
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
64
mc->no_floppy = 1;
52
}
65
mc->no_cdrom = 1;
53
66
mc->no_parallel = 1;
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
67
+ mc->ignore_memory_transaction_failures = true;
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
68
}
56
}
69
57
70
static const TypeInfo ast2500_evb_type = {
58
/*
71
@@ -XXX,XX +XXX,XX @@ static void romulus_bmc_class_init(ObjectClass *oc, void *data)
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
72
mc->no_floppy = 1;
60
}
73
mc->no_cdrom = 1;
61
74
mc->no_parallel = 1;
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
75
+ mc->ignore_memory_transaction_failures = true;
63
+ dump_buf_if_failed(buf, sizeof(buf));
76
}
64
}
77
65
78
static const TypeInfo romulus_bmc_type = {
66
/*
79
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
80
index XXXXXXX..XXXXXXX 100644
68
}
81
--- a/hw/arm/collie.c
69
82
+++ b/hw/arm/collie.c
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
83
@@ -XXX,XX +XXX,XX @@ static void collie_machine_init(MachineClass *mc)
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
84
{
85
mc->desc = "Sharp SL-5500 (Collie) PDA (SA-1110)";
86
mc->init = collie_init;
87
+ mc->ignore_memory_transaction_failures = true;
88
}
72
}
89
73
90
DEFINE_MACHINE("collie", collie_machine_init)
74
int main(int argc, char **argv)
91
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/hw/arm/cubieboard.c
94
+++ b/hw/arm/cubieboard.c
95
@@ -XXX,XX +XXX,XX @@ static void cubieboard_machine_init(MachineClass *mc)
96
mc->init = cubieboard_init;
97
mc->block_default_type = IF_IDE;
98
mc->units_per_default_bus = 1;
99
+ mc->ignore_memory_transaction_failures = true;
100
}
101
102
DEFINE_MACHINE("cubieboard", cubieboard_machine_init)
103
diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/hw/arm/digic_boards.c
106
+++ b/hw/arm/digic_boards.c
107
@@ -XXX,XX +XXX,XX @@ static void canon_a1100_machine_init(MachineClass *mc)
108
{
109
mc->desc = "Canon PowerShot A1100 IS";
110
mc->init = &canon_a1100_init;
111
+ mc->ignore_memory_transaction_failures = true;
112
}
113
114
DEFINE_MACHINE("canon-a1100", canon_a1100_machine_init)
115
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/arm/exynos4_boards.c
118
+++ b/hw/arm/exynos4_boards.c
119
@@ -XXX,XX +XXX,XX @@ static void nuri_class_init(ObjectClass *oc, void *data)
120
mc->desc = "Samsung NURI board (Exynos4210)";
121
mc->init = nuri_init;
122
mc->max_cpus = EXYNOS4210_NCPUS;
123
+ mc->ignore_memory_transaction_failures = true;
124
}
125
126
static const TypeInfo nuri_type = {
127
@@ -XXX,XX +XXX,XX @@ static void smdkc210_class_init(ObjectClass *oc, void *data)
128
mc->desc = "Samsung SMDKC210 board (Exynos4210)";
129
mc->init = smdkc210_init;
130
mc->max_cpus = EXYNOS4210_NCPUS;
131
+ mc->ignore_memory_transaction_failures = true;
132
}
133
134
static const TypeInfo smdkc210_type = {
135
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/arm/gumstix.c
138
+++ b/hw/arm/gumstix.c
139
@@ -XXX,XX +XXX,XX @@ static void connex_class_init(ObjectClass *oc, void *data)
140
141
mc->desc = "Gumstix Connex (PXA255)";
142
mc->init = connex_init;
143
+ mc->ignore_memory_transaction_failures = true;
144
}
145
146
static const TypeInfo connex_type = {
147
@@ -XXX,XX +XXX,XX @@ static void verdex_class_init(ObjectClass *oc, void *data)
148
149
mc->desc = "Gumstix Verdex (PXA270)";
150
mc->init = verdex_init;
151
+ mc->ignore_memory_transaction_failures = true;
152
}
153
154
static const TypeInfo verdex_type = {
155
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/hw/arm/highbank.c
158
+++ b/hw/arm/highbank.c
159
@@ -XXX,XX +XXX,XX @@ static void highbank_class_init(ObjectClass *oc, void *data)
160
mc->block_default_type = IF_IDE;
161
mc->units_per_default_bus = 1;
162
mc->max_cpus = 4;
163
+ mc->ignore_memory_transaction_failures = true;
164
}
165
166
static const TypeInfo highbank_type = {
167
@@ -XXX,XX +XXX,XX @@ static void midway_class_init(ObjectClass *oc, void *data)
168
mc->block_default_type = IF_IDE;
169
mc->units_per_default_bus = 1;
170
mc->max_cpus = 4;
171
+ mc->ignore_memory_transaction_failures = true;
172
}
173
174
static const TypeInfo midway_type = {
175
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/hw/arm/imx25_pdk.c
178
+++ b/hw/arm/imx25_pdk.c
179
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_machine_init(MachineClass *mc)
180
{
181
mc->desc = "ARM i.MX25 PDK board (ARM926)";
182
mc->init = imx25_pdk_init;
183
+ mc->ignore_memory_transaction_failures = true;
184
}
185
186
DEFINE_MACHINE("imx25-pdk", imx25_pdk_machine_init)
187
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/hw/arm/integratorcp.c
190
+++ b/hw/arm/integratorcp.c
191
@@ -XXX,XX +XXX,XX @@ static void integratorcp_machine_init(MachineClass *mc)
192
{
193
mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
194
mc->init = integratorcp_init;
195
+ mc->ignore_memory_transaction_failures = true;
196
}
197
198
DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
199
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/arm/kzm.c
202
+++ b/hw/arm/kzm.c
203
@@ -XXX,XX +XXX,XX @@ static void kzm_machine_init(MachineClass *mc)
204
{
205
mc->desc = "ARM KZM Emulation Baseboard (ARM1136)";
206
mc->init = kzm_init;
207
+ mc->ignore_memory_transaction_failures = true;
208
}
209
210
DEFINE_MACHINE("kzm", kzm_machine_init)
211
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/hw/arm/mainstone.c
214
+++ b/hw/arm/mainstone.c
215
@@ -XXX,XX +XXX,XX @@ static void mainstone2_machine_init(MachineClass *mc)
216
{
217
mc->desc = "Mainstone II (PXA27x)";
218
mc->init = mainstone_init;
219
+ mc->ignore_memory_transaction_failures = true;
220
}
221
222
DEFINE_MACHINE("mainstone", mainstone2_machine_init)
223
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/hw/arm/musicpal.c
226
+++ b/hw/arm/musicpal.c
227
@@ -XXX,XX +XXX,XX @@ static void musicpal_machine_init(MachineClass *mc)
228
{
229
mc->desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)";
230
mc->init = musicpal_init;
231
+ mc->ignore_memory_transaction_failures = true;
232
}
233
234
DEFINE_MACHINE("musicpal", musicpal_machine_init)
235
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
236
index XXXXXXX..XXXXXXX 100644
237
--- a/hw/arm/netduino2.c
238
+++ b/hw/arm/netduino2.c
239
@@ -XXX,XX +XXX,XX @@ static void netduino2_machine_init(MachineClass *mc)
240
{
241
mc->desc = "Netduino 2 Machine";
242
mc->init = netduino2_init;
243
+ mc->ignore_memory_transaction_failures = true;
244
}
245
246
DEFINE_MACHINE("netduino2", netduino2_machine_init)
247
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/arm/nseries.c
250
+++ b/hw/arm/nseries.c
251
@@ -XXX,XX +XXX,XX @@ static void n800_class_init(ObjectClass *oc, void *data)
252
mc->desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)";
253
mc->init = n800_init;
254
mc->default_boot_order = "";
255
+ mc->ignore_memory_transaction_failures = true;
256
}
257
258
static const TypeInfo n800_type = {
259
@@ -XXX,XX +XXX,XX @@ static void n810_class_init(ObjectClass *oc, void *data)
260
mc->desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)";
261
mc->init = n810_init;
262
mc->default_boot_order = "";
263
+ mc->ignore_memory_transaction_failures = true;
264
}
265
266
static const TypeInfo n810_type = {
267
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
268
index XXXXXXX..XXXXXXX 100644
269
--- a/hw/arm/omap_sx1.c
270
+++ b/hw/arm/omap_sx1.c
271
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v2_class_init(ObjectClass *oc, void *data)
272
273
mc->desc = "Siemens SX1 (OMAP310) V2";
274
mc->init = sx1_init_v2;
275
+ mc->ignore_memory_transaction_failures = true;
276
}
277
278
static const TypeInfo sx1_machine_v2_type = {
279
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v1_class_init(ObjectClass *oc, void *data)
280
281
mc->desc = "Siemens SX1 (OMAP310) V1";
282
mc->init = sx1_init_v1;
283
+ mc->ignore_memory_transaction_failures = true;
284
}
285
286
static const TypeInfo sx1_machine_v1_type = {
287
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
288
index XXXXXXX..XXXXXXX 100644
289
--- a/hw/arm/palm.c
290
+++ b/hw/arm/palm.c
291
@@ -XXX,XX +XXX,XX @@ static void palmte_machine_init(MachineClass *mc)
292
{
293
mc->desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)";
294
mc->init = palmte_init;
295
+ mc->ignore_memory_transaction_failures = true;
296
}
297
298
DEFINE_MACHINE("cheetah", palmte_machine_init)
299
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
300
index XXXXXXX..XXXXXXX 100644
301
--- a/hw/arm/raspi.c
302
+++ b/hw/arm/raspi.c
303
@@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc)
304
mc->no_cdrom = 1;
305
mc->max_cpus = BCM2836_NCPUS;
306
mc->default_ram_size = 1024 * 1024 * 1024;
307
+ mc->ignore_memory_transaction_failures = true;
308
};
309
DEFINE_MACHINE("raspi2", raspi2_machine_init)
310
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
311
index XXXXXXX..XXXXXXX 100644
312
--- a/hw/arm/realview.c
313
+++ b/hw/arm/realview.c
314
@@ -XXX,XX +XXX,XX @@ static void realview_eb_class_init(ObjectClass *oc, void *data)
315
mc->desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)";
316
mc->init = realview_eb_init;
317
mc->block_default_type = IF_SCSI;
318
+ mc->ignore_memory_transaction_failures = true;
319
}
320
321
static const TypeInfo realview_eb_type = {
322
@@ -XXX,XX +XXX,XX @@ static void realview_eb_mpcore_class_init(ObjectClass *oc, void *data)
323
mc->init = realview_eb_mpcore_init;
324
mc->block_default_type = IF_SCSI;
325
mc->max_cpus = 4;
326
+ mc->ignore_memory_transaction_failures = true;
327
}
328
329
static const TypeInfo realview_eb_mpcore_type = {
330
@@ -XXX,XX +XXX,XX @@ static void realview_pb_a8_class_init(ObjectClass *oc, void *data)
331
332
mc->desc = "ARM RealView Platform Baseboard for Cortex-A8";
333
mc->init = realview_pb_a8_init;
334
+ mc->ignore_memory_transaction_failures = true;
335
}
336
337
static const TypeInfo realview_pb_a8_type = {
338
@@ -XXX,XX +XXX,XX @@ static void realview_pbx_a9_class_init(ObjectClass *oc, void *data)
339
mc->desc = "ARM RealView Platform Baseboard Explore for Cortex-A9";
340
mc->init = realview_pbx_a9_init;
341
mc->max_cpus = 4;
342
+ mc->ignore_memory_transaction_failures = true;
343
}
344
345
static const TypeInfo realview_pbx_a9_type = {
346
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
347
index XXXXXXX..XXXXXXX 100644
348
--- a/hw/arm/sabrelite.c
349
+++ b/hw/arm/sabrelite.c
350
@@ -XXX,XX +XXX,XX @@ static void sabrelite_machine_init(MachineClass *mc)
351
mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)";
352
mc->init = sabrelite_init;
353
mc->max_cpus = FSL_IMX6_NUM_CPUS;
354
+ mc->ignore_memory_transaction_failures = true;
355
}
356
357
DEFINE_MACHINE("sabrelite", sabrelite_machine_init)
358
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
359
index XXXXXXX..XXXXXXX 100644
360
--- a/hw/arm/spitz.c
361
+++ b/hw/arm/spitz.c
362
@@ -XXX,XX +XXX,XX @@ static void akitapda_class_init(ObjectClass *oc, void *data)
363
364
mc->desc = "Sharp SL-C1000 (Akita) PDA (PXA270)";
365
mc->init = akita_init;
366
+ mc->ignore_memory_transaction_failures = true;
367
}
368
369
static const TypeInfo akitapda_type = {
370
@@ -XXX,XX +XXX,XX @@ static void spitzpda_class_init(ObjectClass *oc, void *data)
371
mc->desc = "Sharp SL-C3000 (Spitz) PDA (PXA270)";
372
mc->init = spitz_init;
373
mc->block_default_type = IF_IDE;
374
+ mc->ignore_memory_transaction_failures = true;
375
}
376
377
static const TypeInfo spitzpda_type = {
378
@@ -XXX,XX +XXX,XX @@ static void borzoipda_class_init(ObjectClass *oc, void *data)
379
mc->desc = "Sharp SL-C3100 (Borzoi) PDA (PXA270)";
380
mc->init = borzoi_init;
381
mc->block_default_type = IF_IDE;
382
+ mc->ignore_memory_transaction_failures = true;
383
}
384
385
static const TypeInfo borzoipda_type = {
386
@@ -XXX,XX +XXX,XX @@ static void terrierpda_class_init(ObjectClass *oc, void *data)
387
mc->desc = "Sharp SL-C3200 (Terrier) PDA (PXA270)";
388
mc->init = terrier_init;
389
mc->block_default_type = IF_IDE;
390
+ mc->ignore_memory_transaction_failures = true;
391
}
392
393
static const TypeInfo terrierpda_type = {
394
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
395
index XXXXXXX..XXXXXXX 100644
396
--- a/hw/arm/stellaris.c
397
+++ b/hw/arm/stellaris.c
398
@@ -XXX,XX +XXX,XX @@ static void lm3s811evb_class_init(ObjectClass *oc, void *data)
399
400
mc->desc = "Stellaris LM3S811EVB";
401
mc->init = lm3s811evb_init;
402
+ mc->ignore_memory_transaction_failures = true;
403
}
404
405
static const TypeInfo lm3s811evb_type = {
406
@@ -XXX,XX +XXX,XX @@ static void lm3s6965evb_class_init(ObjectClass *oc, void *data)
407
408
mc->desc = "Stellaris LM3S6965EVB";
409
mc->init = lm3s6965evb_init;
410
+ mc->ignore_memory_transaction_failures = true;
411
}
412
413
static const TypeInfo lm3s6965evb_type = {
414
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
415
index XXXXXXX..XXXXXXX 100644
416
--- a/hw/arm/tosa.c
417
+++ b/hw/arm/tosa.c
418
@@ -XXX,XX +XXX,XX @@ static void tosapda_machine_init(MachineClass *mc)
419
mc->desc = "Sharp SL-6000 (Tosa) PDA (PXA255)";
420
mc->init = tosa_init;
421
mc->block_default_type = IF_IDE;
422
+ mc->ignore_memory_transaction_failures = true;
423
}
424
425
DEFINE_MACHINE("tosa", tosapda_machine_init)
426
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
427
index XXXXXXX..XXXXXXX 100644
428
--- a/hw/arm/versatilepb.c
429
+++ b/hw/arm/versatilepb.c
430
@@ -XXX,XX +XXX,XX @@ static void versatilepb_class_init(ObjectClass *oc, void *data)
431
mc->desc = "ARM Versatile/PB (ARM926EJ-S)";
432
mc->init = vpb_init;
433
mc->block_default_type = IF_SCSI;
434
+ mc->ignore_memory_transaction_failures = true;
435
}
436
437
static const TypeInfo versatilepb_type = {
438
@@ -XXX,XX +XXX,XX @@ static void versatileab_class_init(ObjectClass *oc, void *data)
439
mc->desc = "ARM Versatile/AB (ARM926EJ-S)";
440
mc->init = vab_init;
441
mc->block_default_type = IF_SCSI;
442
+ mc->ignore_memory_transaction_failures = true;
443
}
444
445
static const TypeInfo versatileab_type = {
446
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
447
index XXXXXXX..XXXXXXX 100644
448
--- a/hw/arm/vexpress.c
449
+++ b/hw/arm/vexpress.c
450
@@ -XXX,XX +XXX,XX @@ static void vexpress_class_init(ObjectClass *oc, void *data)
451
mc->desc = "ARM Versatile Express";
452
mc->init = vexpress_common_init;
453
mc->max_cpus = 4;
454
+ mc->ignore_memory_transaction_failures = true;
455
}
456
457
static void vexpress_a9_class_init(ObjectClass *oc, void *data)
458
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
459
index XXXXXXX..XXXXXXX 100644
460
--- a/hw/arm/xilinx_zynq.c
461
+++ b/hw/arm/xilinx_zynq.c
462
@@ -XXX,XX +XXX,XX @@ static void zynq_machine_init(MachineClass *mc)
463
mc->init = zynq_init;
464
mc->max_cpus = 1;
465
mc->no_sdcard = 1;
466
+ mc->ignore_memory_transaction_failures = true;
467
}
468
469
DEFINE_MACHINE("xilinx-zynq-a9", zynq_machine_init)
470
diff --git a/hw/arm/xlnx-ep108.c b/hw/arm/xlnx-ep108.c
471
index XXXXXXX..XXXXXXX 100644
472
--- a/hw/arm/xlnx-ep108.c
473
+++ b/hw/arm/xlnx-ep108.c
474
@@ -XXX,XX +XXX,XX @@ static void xlnx_ep108_machine_init(MachineClass *mc)
475
mc->init = xlnx_ep108_init;
476
mc->block_default_type = IF_IDE;
477
mc->units_per_default_bus = 1;
478
+ mc->ignore_memory_transaction_failures = true;
479
}
480
481
DEFINE_MACHINE("xlnx-ep108", xlnx_ep108_machine_init)
482
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_init(MachineClass *mc)
483
mc->init = xlnx_ep108_init;
484
mc->block_default_type = IF_IDE;
485
mc->units_per_default_bus = 1;
486
+ mc->ignore_memory_transaction_failures = true;
487
}
488
489
DEFINE_MACHINE("xlnx-zcu102", xlnx_zcu102_machine_init)
490
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
491
index XXXXXXX..XXXXXXX 100644
492
--- a/hw/arm/z2.c
493
+++ b/hw/arm/z2.c
494
@@ -XXX,XX +XXX,XX @@ static void z2_machine_init(MachineClass *mc)
495
{
496
mc->desc = "Zipit Z2 (PXA27x)";
497
mc->init = z2_init;
498
+ mc->ignore_memory_transaction_failures = true;
499
}
500
501
DEFINE_MACHINE("z2", z2_machine_init)
502
--
75
--
503
2.7.4
76
2.20.1
504
77
505
78
diff view generated by jsdifflib
1
From: Portia Stephens <portia.stephens@xilinx.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
This adds a feature bit indicating support of the (trivial) Jazelle
3
We should use printf format specifier "%u" instead of "%d" for
4
implementation if ARM_FEATURE_V6 is set or if the processor is arm926
4
argument of type "unsigned int".
5
or arm1026. This fixes the issue that any BXJ instruction will
6
result in an illegal_op. BXJ instructions will now check if the
7
architecture supports ARM_FEATURE_JAZELLE.
8
5
9
Signed-off-by: Portia Stephens <portia.stephens@xilinx.com>
6
Reported-by: Euler Robot <euler.robot@huawei.com>
10
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
11
Message-id: 20170905211232.11092-1-portia.stephens@xilinx.com
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
12
[PMM: edited commit message and comment text a bit]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
target/arm/cpu.h | 1 +
12
hw/misc/imx25_ccm.c | 12 ++++++------
17
target/arm/cpu.c | 3 +++
13
1 file changed, 6 insertions(+), 6 deletions(-)
18
target/arm/translate.c | 2 +-
19
3 files changed, 5 insertions(+), 1 deletion(-)
20
14
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
17
--- a/hw/misc/imx25_ccm.c
24
+++ b/target/arm/cpu.h
18
+++ b/hw/misc/imx25_ccm.c
25
@@ -XXX,XX +XXX,XX @@ enum arm_features {
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
26
ARM_FEATURE_PMU, /* has PMU support */
20
case IMX25_CCM_LPIMR1_REG:
27
ARM_FEATURE_VBAR, /* has cp15 VBAR */
21
return "lpimr1";
28
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
22
default:
29
+ ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
23
- sprintf(unknown, "[%d ?]", reg);
30
};
24
+ sprintf(unknown, "[%u ?]", reg);
31
25
return unknown;
32
static inline int arm_feature(CPUARMState *env, int feature)
33
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/cpu.c
36
+++ b/target/arm/cpu.c
37
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
38
}
26
}
39
if (arm_feature(env, ARM_FEATURE_V6)) {
27
}
40
set_feature(env, ARM_FEATURE_V5);
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
41
+ set_feature(env, ARM_FEATURE_JAZELLE);
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
42
if (!arm_feature(env, ARM_FEATURE_M)) {
30
}
43
set_feature(env, ARM_FEATURE_AUXCR);
31
44
}
32
- DPRINTF("freq = %d\n", freq);
45
@@ -XXX,XX +XXX,XX @@ static void arm926_initfn(Object *obj)
33
+ DPRINTF("freq = %u\n", freq);
46
set_feature(&cpu->env, ARM_FEATURE_VFP);
34
47
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
35
return freq;
48
set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
36
}
49
+ set_feature(&cpu->env, ARM_FEATURE_JAZELLE);
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
50
cpu->midr = 0x41069265;
38
51
cpu->reset_fpsid = 0x41011090;
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
52
cpu->ctr = 0x1dd20d2;
40
53
@@ -XXX,XX +XXX,XX @@ static void arm1026_initfn(Object *obj)
41
- DPRINTF("freq = %d\n", freq);
54
set_feature(&cpu->env, ARM_FEATURE_AUXCR);
42
+ DPRINTF("freq = %u\n", freq);
55
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
43
56
set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
44
return freq;
57
+ set_feature(&cpu->env, ARM_FEATURE_JAZELLE);
45
}
58
cpu->midr = 0x4106a262;
46
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
59
cpu->reset_fpsid = 0x410110a0;
47
freq = imx25_ccm_get_mcu_clk(dev)
60
cpu->ctr = 0x1dd20d2;
48
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
61
diff --git a/target/arm/translate.c b/target/arm/translate.c
49
62
index XXXXXXX..XXXXXXX 100644
50
- DPRINTF("freq = %d\n", freq);
63
--- a/target/arm/translate.c
51
+ DPRINTF("freq = %u\n", freq);
64
+++ b/target/arm/translate.c
52
65
@@ -XXX,XX +XXX,XX @@
53
return freq;
66
#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
54
}
67
/* currently all emulated v5 cores are also v5TE, so don't bother */
55
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
68
#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
56
69
-#define ENABLE_ARCH_5J 0
57
freq = imx25_ccm_get_ahb_clk(dev) / 2;
70
+#define ENABLE_ARCH_5J arm_dc_feature(s, ARM_FEATURE_JAZELLE)
58
71
#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
59
- DPRINTF("freq = %d\n", freq);
72
#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
60
+ DPRINTF("freq = %u\n", freq);
73
#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
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
}
74
--
73
--
75
2.7.4
74
2.20.1
76
75
77
76
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
QEMU currently exits unexpectedly when the user accidentially
3
We should use printf format specifier "%u" instead of "%d" for
4
tries to do something like this:
4
argument of type "unsigned int".
5
5
6
$ aarch64-softmmu/qemu-system-aarch64 -S -M integratorcp -nographic
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
QEMU 2.9.93 monitor - type 'help' for more information
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
(qemu) device_add allwinner-a10
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
9
Unsupported NIC model: smc91c111
10
11
Exiting just due to a "device_add" should not happen. Looking closer
12
at the the realize and instance_init function of this device also
13
reveals that it is using serial_hds and nd_table directly there, so
14
this device is clearly not creatable by the user and should be marked
15
accordingly.
16
17
Signed-off-by: Thomas Huth <thuth@redhat.com>
18
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
19
Message-id: 1503416789-32080-1-git-send-email-thuth@redhat.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
11
---
23
hw/arm/allwinner-a10.c | 2 ++
12
hw/misc/imx31_ccm.c | 14 +++++++-------
24
scripts/device-crash-test | 1 -
13
hw/misc/imx_ccm.c | 4 ++--
25
2 files changed, 2 insertions(+), 1 deletion(-)
14
2 files changed, 9 insertions(+), 9 deletions(-)
26
15
27
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
28
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/allwinner-a10.c
18
--- a/hw/misc/imx31_ccm.c
30
+++ b/hw/arm/allwinner-a10.c
19
+++ b/hw/misc/imx31_ccm.c
31
@@ -XXX,XX +XXX,XX @@ static void aw_a10_class_init(ObjectClass *oc, void *data)
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
32
DeviceClass *dc = DEVICE_CLASS(oc);
21
case IMX31_CCM_PDR2_REG:
33
22
return "PDR2";
34
dc->realize = aw_a10_realize;
23
default:
35
+ /* Reason: Uses serial_hds in realize and nd_table in instance_init */
24
- sprintf(unknown, "[%d ?]", reg);
36
+ dc->user_creatable = false;
25
+ sprintf(unknown, "[%u ?]", reg);
26
return unknown;
27
}
37
}
28
}
38
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
39
static const TypeInfo aw_a10_type_info = {
30
freq = CKIH_FREQ;
40
diff --git a/scripts/device-crash-test b/scripts/device-crash-test
31
}
41
index XXXXXXX..XXXXXXX 100755
32
42
--- a/scripts/device-crash-test
33
- DPRINTF("freq = %d\n", freq);
43
+++ b/scripts/device-crash-test
34
+ DPRINTF("freq = %u\n", freq);
44
@@ -XXX,XX +XXX,XX @@ ERROR_WHITELIST = [
35
45
{'log':r"Device [\w.,-]+ can not be dynamically instantiated"},
36
return freq;
46
{'log':r"Platform Bus: Can not fit MMIO region of size "},
37
}
47
# other more specific errors we will ignore:
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
48
- {'device':'allwinner-a10', 'log':"Unsupported NIC model:"},
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
49
{'device':'.*-spapr-cpu-core', 'log':r"CPU core type should be"},
40
imx31_ccm_get_pll_ref_clk(dev));
50
{'log':r"MSI(-X)? is not supported by interrupt controller"},
41
51
{'log':r"pxb-pcie? devices cannot reside on a PCIe? bus"},
42
- DPRINTF("freq = %d\n", freq);
43
+ DPRINTF("freq = %u\n", freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
48
freq = imx31_ccm_get_mpll_clk(dev);
49
}
50
51
- DPRINTF("freq = %d\n", freq);
52
+ DPRINTF("freq = %u\n", freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
57
freq = imx31_ccm_get_mcu_main_clk(dev)
58
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
59
60
- DPRINTF("freq = %d\n", freq);
61
+ DPRINTF("freq = %u\n", freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
66
freq = imx31_ccm_get_hclk_clk(dev)
67
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
68
69
- DPRINTF("freq = %d\n", freq);
70
+ DPRINTF("freq = %u\n", freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
75
break;
76
}
77
78
- DPRINTF("Clock = %d) = %d\n", clock, freq);
79
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
80
81
return freq;
82
}
83
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/misc/imx_ccm.c
86
+++ b/hw/misc/imx_ccm.c
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
88
freq = klass->get_clock_frequency(dev, clock);
89
}
90
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
93
94
return freq;
95
}
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;
52
--
105
--
53
2.7.4
106
2.20.1
54
107
55
108
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
We should use printf format specifier "%u" instead of "%d" for
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
argument of type "unsigned int".
5
Message-id: 20170905131149.10669-7-famz@redhat.com
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-4-alex.chen@huawei.com
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
hw/dma/xilinx_axidma.c | 16 ++++------------
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
10
1 file changed, 4 insertions(+), 12 deletions(-)
13
hw/misc/imx6_src.c | 2 +-
14
2 files changed, 11 insertions(+), 11 deletions(-)
11
15
12
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/dma/xilinx_axidma.c
18
--- a/hw/misc/imx6_ccm.c
15
+++ b/hw/dma/xilinx_axidma.c
19
+++ b/hw/misc/imx6_ccm.c
16
@@ -XXX,XX +XXX,XX @@ static void xilinx_axidma_init(Object *obj)
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
17
XilinxAXIDMA *s = XILINX_AXI_DMA(obj);
21
case CCM_CMEOR:
18
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
22
return "CMEOR";
19
23
default:
20
- object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
24
- sprintf(unknown, "%d ?", reg);
21
- (Object **)&s->tx_data_dev,
25
+ sprintf(unknown, "%u ?", reg);
22
- qdev_prop_allow_set_link_before_realize,
26
return unknown;
23
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
27
}
24
- &error_abort);
28
}
25
- object_property_add_link(obj, "axistream-control-connected",
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
26
- TYPE_STREAM_SLAVE,
30
case USB_ANALOG_DIGPROG:
27
- (Object **)&s->tx_control_dev,
31
return "USB_ANALOG_DIGPROG";
28
- qdev_prop_allow_set_link_before_realize,
32
default:
29
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
33
- sprintf(unknown, "%d ?", reg);
30
- &error_abort);
34
+ sprintf(unknown, "%u ?", reg);
31
-
35
return unknown;
32
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
36
}
33
TYPE_XILINX_AXI_DMA_DATA_STREAM);
37
}
34
object_initialize(&s->rx_control_dev, sizeof(s->rx_control_dev),
38
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
35
@@ -XXX,XX +XXX,XX @@ static void xilinx_axidma_init(Object *obj)
39
freq *= 20;
36
40
}
37
static Property axidma_properties[] = {
41
38
DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000),
42
- DPRINTF("freq = %d\n", (uint32_t)freq);
39
+ DEFINE_PROP_LINK("axistream-connected", XilinxAXIDMA,
43
+ DPRINTF("freq = %u\n", (uint32_t)freq);
40
+ tx_data_dev, TYPE_STREAM_SLAVE, StreamSlave *),
44
41
+ DEFINE_PROP_LINK("axistream-control-connected", XilinxAXIDMA,
45
return freq;
42
+ tx_control_dev, TYPE_STREAM_SLAVE, StreamSlave *),
46
}
43
DEFINE_PROP_END_OF_LIST(),
47
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
44
};
48
freq = imx6_analog_get_pll2_clk(dev) * 18
45
49
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
50
51
- DPRINTF("freq = %d\n", (uint32_t)freq);
52
+ DPRINTF("freq = %u\n", (uint32_t)freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
57
freq = imx6_analog_get_pll2_clk(dev) * 18
58
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
59
60
- DPRINTF("freq = %d\n", (uint32_t)freq);
61
+ DPRINTF("freq = %u\n", (uint32_t)freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
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
}
46
--
123
--
47
2.7.4
124
2.20.1
48
125
49
126
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
We should use printf format specifier "%u" instead of "%d" for
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
argument of type "unsigned int".
5
Message-id: 20170905131149.10669-6-famz@redhat.com
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
hw/net/xilinx_axienet.c | 16 ++++------------
12
hw/misc/imx6ul_ccm.c | 4 ++--
10
1 file changed, 4 insertions(+), 12 deletions(-)
13
1 file changed, 2 insertions(+), 2 deletions(-)
11
14
12
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/net/xilinx_axienet.c
17
--- a/hw/misc/imx6ul_ccm.c
15
+++ b/hw/net/xilinx_axienet.c
18
+++ b/hw/misc/imx6ul_ccm.c
16
@@ -XXX,XX +XXX,XX @@ static void xilinx_enet_init(Object *obj)
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
17
XilinxAXIEnet *s = XILINX_AXI_ENET(obj);
20
case CCM_CMEOR:
18
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
21
return "CMEOR";
19
22
default:
20
- object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
23
- sprintf(unknown, "%d ?", reg);
21
- (Object **) &s->tx_data_dev,
24
+ sprintf(unknown, "%u ?", reg);
22
- qdev_prop_allow_set_link_before_realize,
25
return unknown;
23
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
26
}
24
- &error_abort);
27
}
25
- object_property_add_link(obj, "axistream-control-connected",
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
26
- TYPE_STREAM_SLAVE,
29
case USB_ANALOG_DIGPROG:
27
- (Object **) &s->tx_control_dev,
30
return "USB_ANALOG_DIGPROG";
28
- qdev_prop_allow_set_link_before_realize,
31
default:
29
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
32
- sprintf(unknown, "%d ?", reg);
30
- &error_abort);
33
+ sprintf(unknown, "%u ?", reg);
31
-
34
return unknown;
32
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
35
}
33
TYPE_XILINX_AXI_ENET_DATA_STREAM);
36
}
34
object_initialize(&s->rx_control_dev, sizeof(s->rx_control_dev),
35
@@ -XXX,XX +XXX,XX @@ static Property xilinx_enet_properties[] = {
36
DEFINE_PROP_UINT32("rxmem", XilinxAXIEnet, c_rxmem, 0x1000),
37
DEFINE_PROP_UINT32("txmem", XilinxAXIEnet, c_txmem, 0x1000),
38
DEFINE_NIC_PROPERTIES(XilinxAXIEnet, conf),
39
+ DEFINE_PROP_LINK("axistream-connected", XilinxAXIEnet,
40
+ tx_data_dev, TYPE_STREAM_SLAVE, StreamSlave *),
41
+ DEFINE_PROP_LINK("axistream-control-connected", XilinxAXIEnet,
42
+ tx_control_dev, TYPE_STREAM_SLAVE, StreamSlave *),
43
DEFINE_PROP_END_OF_LIST(),
44
};
45
46
--
37
--
47
2.7.4
38
2.20.1
48
39
49
40
diff view generated by jsdifflib
1
Make the FAULTMASK register banked if v8M security extensions are enabled.
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.
2
9
3
Note that we do not yet implement the functionality of the new
10
The architecture is clear that within the SCS unimplemented registers
4
AIRCR.PRIS bit (which allows the effect of the NS copy of FAULTMASK to
11
should be RES0 for privileged accesses and generate BusFault for
5
be restricted).
12
unprivileged accesses, and we currently implement this.
6
13
7
This patch includes the code to determine for v8M which copy
14
It is less clear about how to handle accesses to unimplemented
8
of FAULTMASK should be updated on exception exit; further
15
regions of the wider PPB. Unprivileged accesses should definitely
9
changes will be required to the exception exit code in general
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
10
to support v8M, so this is just a small piece of that.
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.)
11
23
12
The v8M ARM ARM introduces a notation where individual paragraphs
24
Expand the container MemoryRegion that the NVIC exposes so that
13
are labelled with R (for rule) or I (for information) followed
25
it covers the whole PPB space. This means:
14
by a random group of subscript letters. In comments where we want
26
* moving the address that the ARMV7M device maps it to down by
15
to refer to a particular part of the manual we use this convention,
27
0xe000 bytes
16
which should be more stable across document revisions than using
28
* moving the off and the offsets within the container of all the
17
section or page numbers.
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
18
33
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 1503414539-28762-9-git-send-email-peter.maydell@linaro.org
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
22
---
37
---
23
target/arm/cpu.h | 14 ++++++++++++--
38
include/hw/intc/armv7m_nvic.h | 1 +
24
hw/intc/armv7m_nvic.c | 9 ++++++++-
39
hw/arm/armv7m.c | 2 +-
25
target/arm/helper.c | 20 ++++++++++++++++----
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
26
target/arm/machine.c | 5 +++--
41
3 files changed, 69 insertions(+), 12 deletions(-)
27
4 files changed, 39 insertions(+), 9 deletions(-)
28
42
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
30
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.h
45
--- a/include/hw/intc/armv7m_nvic.h
32
+++ b/target/arm/cpu.h
46
+++ b/include/hw/intc/armv7m_nvic.h
33
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
34
unsigned mpu_ctrl; /* MPU_CTRL */
48
MemoryRegion systickmem;
35
int exception;
49
MemoryRegion systick_ns_mem;
36
uint32_t primask[2];
50
MemoryRegion container;
37
- uint32_t faultmask;
51
+ MemoryRegion defaultmem;
38
+ uint32_t faultmask[2];
52
39
uint32_t secure; /* Is CPU in Secure state? (not guest visible) */
53
uint32_t num_irq;
40
} v7m;
54
qemu_irq excpout;
41
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
42
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque);
56
index XXXXXXX..XXXXXXX 100644
43
* (Ignoring -1, this is the same as the RETTOBASE value before completion.)
57
--- a/hw/arm/armv7m.c
44
*/
58
+++ b/hw/arm/armv7m.c
45
int armv7m_nvic_complete_irq(void *opaque, int irq);
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
46
+/**
60
sysbus_connect_irq(sbd, 0,
47
+ * armv7m_nvic_raw_execution_priority: return the raw execution priority
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
48
+ * @opaque: the NVIC
62
49
+ *
63
- memory_region_add_subregion(&s->container, 0xe000e000,
50
+ * Returns: the raw execution priority as defined by the v8M architecture.
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
51
+ * This is the execution priority minus the effects of AIRCR.PRIS,
65
sysbus_mmio_get_region(sbd, 0));
52
+ * and minus any PRIMASK/FAULTMASK/BASEPRI priority boosting.
66
53
+ * (v8M ARM ARM I_PKLD.)
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
54
+ */
55
+int armv7m_nvic_raw_execution_priority(void *opaque);
56
57
/* Interface for defining coprocessor registers.
58
* Registers are defined in tables of arm_cp_reginfo structs
59
@@ -XXX,XX +XXX,XX @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
60
* we're in a HardFault or NMI handler.
61
*/
62
if ((env->v7m.exception > 0 && env->v7m.exception <= 3)
63
- || env->v7m.faultmask) {
64
+ || env->v7m.faultmask[env->v7m.secure]) {
65
mmu_idx = ARMMMUIdx_MNegPri;
66
}
67
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
69
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/armv7m_nvic.c
70
--- a/hw/intc/armv7m_nvic.c
71
+++ b/hw/intc/armv7m_nvic.c
71
+++ b/hw/intc/armv7m_nvic.c
72
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
73
CPUARMState *env = &s->cpu->env;
73
.endianness = DEVICE_NATIVE_ENDIAN,
74
int running;
74
};
75
75
76
- if (env->v7m.faultmask) {
76
+/*
77
+ if (env->v7m.faultmask[env->v7m.secure]) {
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
78
running = -1;
78
+ * accesses, and fault for non-privileged accesses.
79
} else if (env->v7m.primask[env->v7m.secure]) {
79
+ */
80
running = 0;
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
81
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_can_take_pending_exception(void *opaque)
81
+ uint64_t *data, unsigned size,
82
return nvic_exec_prio(s) > nvic_pending_prio(s);
82
+ MemTxAttrs attrs)
83
}
84
85
+int armv7m_nvic_raw_execution_priority(void *opaque)
86
+{
83
+{
87
+ NVICState *s = opaque;
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
88
+
85
+ (uint32_t)addr);
89
+ return s->exception_prio;
86
+ if (attrs.user) {
87
+ return MEMTX_ERROR;
88
+ }
89
+ *data = 0;
90
+ return MEMTX_OK;
90
+}
91
+}
91
+
92
+
92
/* caller must call nvic_irq_update() after this */
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
93
static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
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)
94
{
114
{
95
diff --git a/target/arm/helper.c b/target/arm/helper.c
115
NVICState *s = opaque;
96
index XXXXXXX..XXXXXXX 100644
116
@@ -XXX,XX +XXX,XX @@ static void nvic_systick_trigger(void *opaque, int n, int level)
97
--- a/target/arm/helper.c
117
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
98
+++ b/target/arm/helper.c
118
{
99
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
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));
100
}
126
}
101
127
102
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
103
- /* Auto-clear FAULTMASK on return from other than NMI */
129
+ /*
104
- env->v7m.faultmask = 0;
130
+ * This device provides a single sysbus memory region which
105
+ /* Auto-clear FAULTMASK on return from other than NMI.
131
+ * represents the whole of the "System PPB" space. This is the
106
+ * If the security extension is implemented then this only
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
107
+ * happens if the raw execution priority is >= 0; the
133
+ * the System Control Space (system registers), the systick timer,
108
+ * value of the ES bit in the exception return value indicates
134
+ * and for CPUs with the Security extension an NS banked version
109
+ * which security state's faultmask to clear. (v8M ARM ARM R_KBNF.)
135
+ * of all of these.
110
+ */
136
+ *
111
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
137
+ * The default behaviour for unimplemented registers/ranges
112
+ int es = type & 1;
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
113
+ if (armv7m_nvic_raw_execution_priority(env->nvic) >= 0) {
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
114
+ env->v7m.faultmask[es] = 0;
140
+ * access.
115
+ }
141
+ *
116
+ } else {
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
117
+ env->v7m.faultmask[M_REG_NS] = 0;
143
* and looks like this:
118
+ }
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);
119
}
193
}
120
194
121
switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
122
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
123
case 18: /* BASEPRI_MAX */
124
return env->v7m.basepri[env->v7m.secure];
125
case 19: /* FAULTMASK */
126
- return env->v7m.faultmask;
127
+ return env->v7m.faultmask[env->v7m.secure];
128
default:
129
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special"
130
" register %d\n", reg);
131
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
132
}
133
break;
134
case 19: /* FAULTMASK */
135
- env->v7m.faultmask = val & 1;
136
+ env->v7m.faultmask[env->v7m.secure] = val & 1;
137
break;
138
case 20: /* CONTROL */
139
/* Writing to the SPSEL bit only has an effect if we are in
140
diff --git a/target/arm/machine.c b/target/arm/machine.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/target/arm/machine.c
143
+++ b/target/arm/machine.c
144
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_faultmask_primask = {
145
.version_id = 1,
146
.minimum_version_id = 1,
147
.fields = (VMStateField[]) {
148
- VMSTATE_UINT32(env.v7m.faultmask, ARMCPU),
149
+ VMSTATE_UINT32(env.v7m.faultmask[M_REG_NS], ARMCPU),
150
VMSTATE_UINT32(env.v7m.primask[M_REG_NS], ARMCPU),
151
VMSTATE_END_OF_LIST()
152
}
153
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
154
VMSTATE_UINT32(env.v7m.secure, ARMCPU),
155
VMSTATE_UINT32(env.v7m.basepri[M_REG_S], ARMCPU),
156
VMSTATE_UINT32(env.v7m.primask[M_REG_S], ARMCPU),
157
+ VMSTATE_UINT32(env.v7m.faultmask[M_REG_S], ARMCPU),
158
VMSTATE_END_OF_LIST()
159
}
160
};
161
@@ -XXX,XX +XXX,XX @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
162
* transferred using the vmstate_m_faultmask_primask subsection.
163
*/
164
if (val & CPSR_F) {
165
- env->v7m.faultmask = 1;
166
+ env->v7m.faultmask[M_REG_NS] = 1;
167
}
168
if (val & CPSR_I) {
169
env->v7m.primask[M_REG_NS] = 1;
170
--
195
--
171
2.7.4
196
2.20.1
172
197
173
198
diff view generated by jsdifflib
1
Make the MPU registers MPU_MAIR0 and MPU_MAIR1 banked if v8M security
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
2
extensions are enabled.
2
MPU_RLAR registers, which forbids execution of code in the region
3
from a privileged mode.
3
4
4
We can freely add more items to vmstate_m_security without
5
This is another feature which is just in the generic "in v8.1M" set
5
breaking migration compatibility, because no CPU currently
6
and has no ID register field indicating its presence.
6
has the ARM_FEATURE_M_SECURITY bit enabled and so this
7
subsection is not yet used by anything.
8
7
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 1503414539-28762-14-git-send-email-peter.maydell@linaro.org
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
12
---
11
---
13
target/arm/cpu.h | 4 ++--
12
target/arm/helper.c | 7 ++++++-
14
hw/intc/armv7m_nvic.c | 8 ++++----
13
1 file changed, 6 insertions(+), 1 deletion(-)
15
target/arm/cpu.c | 26 ++++++++++++++++++++------
16
target/arm/helper.c | 11 ++++++-----
17
target/arm/machine.c | 12 ++++++++----
18
5 files changed, 40 insertions(+), 21 deletions(-)
19
14
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
25
* pmsav7.rnr (region number register)
26
* pmsav7_dregion (number of configured regions)
27
*/
28
- uint32_t *rbar;
29
- uint32_t *rlar;
30
+ uint32_t *rbar[2];
31
+ uint32_t *rlar[2];
32
uint32_t mair0[2];
33
uint32_t mair1[2];
34
} pmsav8;
35
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/intc/armv7m_nvic.c
38
+++ b/hw/intc/armv7m_nvic.c
39
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
40
if (region >= cpu->pmsav7_dregion) {
41
return 0;
42
}
43
- return cpu->env.pmsav8.rbar[region];
44
+ return cpu->env.pmsav8.rbar[attrs.secure][region];
45
}
46
47
if (region >= cpu->pmsav7_dregion) {
48
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
49
if (region >= cpu->pmsav7_dregion) {
50
return 0;
51
}
52
- return cpu->env.pmsav8.rlar[region];
53
+ return cpu->env.pmsav8.rlar[attrs.secure][region];
54
}
55
56
if (region >= cpu->pmsav7_dregion) {
57
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
58
if (region >= cpu->pmsav7_dregion) {
59
return;
60
}
61
- cpu->env.pmsav8.rbar[region] = value;
62
+ cpu->env.pmsav8.rbar[attrs.secure][region] = value;
63
tlb_flush(CPU(cpu));
64
return;
65
}
66
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
67
if (region >= cpu->pmsav7_dregion) {
68
return;
69
}
70
- cpu->env.pmsav8.rlar[region] = value;
71
+ cpu->env.pmsav8.rlar[attrs.secure][region] = value;
72
tlb_flush(CPU(cpu));
73
return;
74
}
75
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/cpu.c
78
+++ b/target/arm/cpu.c
79
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
80
if (arm_feature(env, ARM_FEATURE_PMSA)) {
81
if (cpu->pmsav7_dregion > 0) {
82
if (arm_feature(env, ARM_FEATURE_V8)) {
83
- memset(env->pmsav8.rbar, 0,
84
- sizeof(*env->pmsav8.rbar) * cpu->pmsav7_dregion);
85
- memset(env->pmsav8.rlar, 0,
86
- sizeof(*env->pmsav8.rlar) * cpu->pmsav7_dregion);
87
+ memset(env->pmsav8.rbar[M_REG_NS], 0,
88
+ sizeof(*env->pmsav8.rbar[M_REG_NS])
89
+ * cpu->pmsav7_dregion);
90
+ memset(env->pmsav8.rlar[M_REG_NS], 0,
91
+ sizeof(*env->pmsav8.rlar[M_REG_NS])
92
+ * cpu->pmsav7_dregion);
93
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
94
+ memset(env->pmsav8.rbar[M_REG_S], 0,
95
+ sizeof(*env->pmsav8.rbar[M_REG_S])
96
+ * cpu->pmsav7_dregion);
97
+ memset(env->pmsav8.rlar[M_REG_S], 0,
98
+ sizeof(*env->pmsav8.rlar[M_REG_S])
99
+ * cpu->pmsav7_dregion);
100
+ }
101
} else if (arm_feature(env, ARM_FEATURE_V7)) {
102
memset(env->pmsav7.drbar, 0,
103
sizeof(*env->pmsav7.drbar) * cpu->pmsav7_dregion);
104
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
105
if (nr) {
106
if (arm_feature(env, ARM_FEATURE_V8)) {
107
/* PMSAv8 */
108
- env->pmsav8.rbar = g_new0(uint32_t, nr);
109
- env->pmsav8.rlar = g_new0(uint32_t, nr);
110
+ env->pmsav8.rbar[M_REG_NS] = g_new0(uint32_t, nr);
111
+ env->pmsav8.rlar[M_REG_NS] = g_new0(uint32_t, nr);
112
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
113
+ env->pmsav8.rbar[M_REG_S] = g_new0(uint32_t, nr);
114
+ env->pmsav8.rlar[M_REG_S] = g_new0(uint32_t, nr);
115
+ }
116
} else {
117
env->pmsav7.drbar = g_new0(uint32_t, nr);
118
env->pmsav7.drsr = g_new0(uint32_t, nr);
119
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
120
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
121
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
122
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
123
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
19
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
124
{
125
ARMCPU *cpu = arm_env_get_cpu(env);
126
bool is_user = regime_is_user(env, mmu_idx);
127
+ uint32_t secure = regime_is_secure(env, mmu_idx);
128
int n;
129
int matchregion = -1;
130
bool hit = false;
131
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
132
* with bits [4:0] all zeroes, but the limit address is bits
133
* [31:5] from the register with bits [4:0] all ones.
134
*/
135
- uint32_t base = env->pmsav8.rbar[n] & ~0x1f;
136
- uint32_t limit = env->pmsav8.rlar[n] | 0x1f;
137
+ uint32_t base = env->pmsav8.rbar[secure][n] & ~0x1f;
138
+ uint32_t limit = env->pmsav8.rlar[secure][n] | 0x1f;
139
140
- if (!(env->pmsav8.rlar[n] & 0x1)) {
141
+ if (!(env->pmsav8.rlar[secure][n] & 0x1)) {
142
/* Region disabled */
143
continue;
144
}
145
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
146
/* hit using the background region */
147
get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
148
} else {
20
} else {
149
- uint32_t ap = extract32(env->pmsav8.rbar[matchregion], 1, 2);
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
150
- uint32_t xn = extract32(env->pmsav8.rbar[matchregion], 0, 1);
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
151
+ uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
23
+ bool pxn = false;
152
+ uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
24
+
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
27
+ }
153
28
154
if (m_is_system_region(env, address)) {
29
if (m_is_system_region(env, address)) {
155
/* System space is always execute never */
30
/* System space is always execute never */
156
diff --git a/target/arm/machine.c b/target/arm/machine.c
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
157
index XXXXXXX..XXXXXXX 100644
32
}
158
--- a/target/arm/machine.c
33
159
+++ b/target/arm/machine.c
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
160
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmsav8 = {
35
- if (*prot && !xn) {
161
.minimum_version_id = 1,
36
+ if (*prot && !xn && !(pxn && !is_user)) {
162
.needed = pmsav8_needed,
37
*prot |= PAGE_EXEC;
163
.fields = (VMStateField[]) {
38
}
164
- VMSTATE_VARRAY_UINT32(env.pmsav8.rbar, ARMCPU, pmsav7_dregion, 0,
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
165
- vmstate_info_uint32, uint32_t),
166
- VMSTATE_VARRAY_UINT32(env.pmsav8.rlar, ARMCPU, pmsav7_dregion, 0,
167
- vmstate_info_uint32, uint32_t),
168
+ VMSTATE_VARRAY_UINT32(env.pmsav8.rbar[M_REG_NS], ARMCPU, pmsav7_dregion,
169
+ 0, vmstate_info_uint32, uint32_t),
170
+ VMSTATE_VARRAY_UINT32(env.pmsav8.rlar[M_REG_NS], ARMCPU, pmsav7_dregion,
171
+ 0, vmstate_info_uint32, uint32_t),
172
VMSTATE_UINT32(env.pmsav8.mair0[M_REG_NS], ARMCPU),
173
VMSTATE_UINT32(env.pmsav8.mair1[M_REG_NS], ARMCPU),
174
VMSTATE_END_OF_LIST()
175
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
176
VMSTATE_UINT32(env.v7m.vecbase[M_REG_S], ARMCPU),
177
VMSTATE_UINT32(env.pmsav8.mair0[M_REG_S], ARMCPU),
178
VMSTATE_UINT32(env.pmsav8.mair1[M_REG_S], ARMCPU),
179
+ VMSTATE_VARRAY_UINT32(env.pmsav8.rbar[M_REG_S], ARMCPU, pmsav7_dregion,
180
+ 0, vmstate_info_uint32, uint32_t),
181
+ VMSTATE_VARRAY_UINT32(env.pmsav8.rlar[M_REG_S], ARMCPU, pmsav7_dregion,
182
+ 0, vmstate_info_uint32, uint32_t),
183
VMSTATE_END_OF_LIST()
184
}
185
};
186
--
40
--
187
2.7.4
41
2.20.1
188
42
189
43
diff view generated by jsdifflib
1
If a v8M CPU supports the security extension then we need to
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
2
give it two AddressSpaces, the same way we do already for
2
via the has_el3 CPU object property, which we create if the CPU
3
an A profile core with EL3.
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
7
This codepath was incorrectly being taken for M-profile CPUs, which
8
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
9
the M-profile Security extension and so should have non-zero values
10
in the ID_PFR1.Security field.
11
12
Restrict the handling of the feature flag to A/R-profile cores.
4
13
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 1503414539-28762-5-git-send-email-peter.maydell@linaro.org
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
8
---
17
---
9
target/arm/cpu.c | 13 ++++++-------
18
target/arm/cpu.c | 2 +-
10
1 file changed, 6 insertions(+), 7 deletions(-)
19
1 file changed, 1 insertion(+), 1 deletion(-)
11
20
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
23
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
24
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
17
init_cpreg_list(cpu);
18
19
#ifndef CONFIG_USER_ONLY
20
- if (cpu->has_el3) {
21
- cs->num_ases = 2;
22
- } else {
23
- cs->num_ases = 1;
24
- }
25
-
26
- if (cpu->has_el3) {
27
+ if (cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY)) {
28
AddressSpace *as;
29
30
+ cs->num_ases = 2;
31
+
32
if (!cpu->secure_memory) {
33
cpu->secure_memory = cs->memory;
34
}
26
}
35
as = address_space_init_shareable(cpu->secure_memory,
36
"cpu-secure-memory");
37
cpu_address_space_init(cs, as, ARMASIdx_S);
38
+ } else {
39
+ cs->num_ases = 1;
40
}
27
}
41
+
28
42
cpu_address_space_init(cs,
29
- if (!cpu->has_el3) {
43
address_space_init_shareable(cs->memory,
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
44
"cpu-memory"),
31
/* If the has_el3 CPU property is disabled then we need to disable the
32
* feature.
33
*/
45
--
34
--
46
2.7.4
35
2.20.1
47
36
48
37
diff view generated by jsdifflib
1
Make the CONTROL register banked if v8M security extensions are enabled.
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
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
6
Because we want to use arm_gen_condlabel(), we need to move
7
the definition of that function up in translate.c so it is
8
before the #include of translate-vfp.c.inc.
2
9
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 1503414539-28762-10-git-send-email-peter.maydell@linaro.org
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
6
---
13
---
7
target/arm/cpu.h | 5 +++--
14
target/arm/cpu.h | 9 ++++
8
target/arm/helper.c | 21 +++++++++++----------
15
target/arm/m-nocp.decode | 8 +++-
9
target/arm/machine.c | 3 ++-
16
target/arm/translate.c | 21 +++++----
10
target/arm/translate.c | 2 +-
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
11
4 files changed, 17 insertions(+), 14 deletions(-)
18
4 files changed, 111 insertions(+), 11 deletions(-)
12
19
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
22
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
18
uint32_t other_sp;
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
19
uint32_t vecbase;
26
}
20
uint32_t basepri[2];
27
21
- uint32_t control;
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
22
+ uint32_t control[2];
29
+{
23
uint32_t ccr; /* Configuration and Control */
30
+ /*
24
uint32_t cfsr; /* Configurable Fault Status */
31
+ * Return true if M-profile state handling insns
25
uint32_t hfsr; /* HardFault Status */
32
+ * (VSCCLRM, CLRM, FPCTX access insns) are implemented
26
@@ -XXX,XX +XXX,XX @@ static inline bool arm_v7m_is_handler_mode(CPUARMState *env)
33
+ */
27
static inline int arm_current_el(CPUARMState *env)
34
+ return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
28
{
35
+}
29
if (arm_feature(env, ARM_FEATURE_M)) {
36
+
30
- return arm_v7m_is_handler_mode(env) || !(env->v7m.control & 1);
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
31
+ return arm_v7m_is_handler_mode(env) ||
38
{
32
+ !(env->v7m.control[env->v7m.secure] & 1);
39
/* Sadly this is encoded differently for A-profile and M-profile */
33
}
40
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
34
41
index XXXXXXX..XXXXXXX 100644
35
if (is_a64(env)) {
42
--- a/target/arm/m-nocp.decode
36
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
+++ b/target/arm/m-nocp.decode
37
index XXXXXXX..XXXXXXX 100644
44
@@ -XXX,XX +XXX,XX @@
38
--- a/target/arm/helper.c
45
# If the coprocessor is not present or disabled then we will generate
39
+++ b/target/arm/helper.c
46
# the NOCP exception; otherwise we let the insn through to the main decode.
40
@@ -XXX,XX +XXX,XX @@ static uint32_t v7m_pop(CPUARMState *env)
47
41
static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
48
+%vd_dp 22:1 12:4
42
{
49
+%vd_sp 12:4 22:1
43
uint32_t tmp;
50
+
44
- bool old_spsel = env->v7m.control & R_V7M_CONTROL_SPSEL_MASK;
51
&nocp cp
45
+ uint32_t old_control = env->v7m.control[env->v7m.secure];
52
46
+ bool old_spsel = old_control & R_V7M_CONTROL_SPSEL_MASK;
53
{
47
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
48
if (old_spsel != new_spsel) {
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
49
tmp = env->v7m.other_sp;
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
50
env->v7m.other_sp = env->regs[13];
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
51
env->regs[13] = tmp;
58
+ # VSCCLRM (new in v8.1M) is similar:
52
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
53
- env->v7m.control = deposit32(env->v7m.control,
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
54
+ env->v7m.control[env->v7m.secure] = deposit32(old_control,
61
55
R_V7M_CONTROL_SPSEL_SHIFT,
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
56
R_V7M_CONTROL_SPSEL_LENGTH, new_spsel);
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
57
}
58
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
59
}
60
61
lr = 0xfffffff1;
62
- if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
63
+ if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK) {
64
lr |= 4;
65
}
66
if (!arm_v7m_is_handler_mode(env)) {
67
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
68
return xpsr_read(env) & mask;
69
break;
70
case 20: /* CONTROL */
71
- return env->v7m.control;
72
+ return env->v7m.control[env->v7m.secure];
73
}
74
75
if (el == 0) {
76
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
77
78
switch (reg) {
79
case 8: /* MSP */
80
- return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ?
81
+ return (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK) ?
82
env->v7m.other_sp : env->regs[13];
83
case 9: /* PSP */
84
- return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ?
85
+ return (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK) ?
86
env->regs[13] : env->v7m.other_sp;
87
case 16: /* PRIMASK */
88
return env->v7m.primask[env->v7m.secure];
89
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
90
}
91
break;
92
case 8: /* MSP */
93
- if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
94
+ if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK) {
95
env->v7m.other_sp = val;
96
} else {
97
env->regs[13] = val;
98
}
99
break;
100
case 9: /* PSP */
101
- if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
102
+ if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK) {
103
env->regs[13] = val;
104
} else {
105
env->v7m.other_sp = val;
106
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
107
if (!arm_v7m_is_handler_mode(env)) {
108
switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
109
}
110
- env->v7m.control &= ~R_V7M_CONTROL_NPRIV_MASK;
111
- env->v7m.control |= val & R_V7M_CONTROL_NPRIV_MASK;
112
+ env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
113
+ env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
114
break;
115
default:
116
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special"
117
diff --git a/target/arm/machine.c b/target/arm/machine.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/machine.c
120
+++ b/target/arm/machine.c
121
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
122
.fields = (VMStateField[]) {
123
VMSTATE_UINT32(env.v7m.vecbase, ARMCPU),
124
VMSTATE_UINT32(env.v7m.basepri[M_REG_NS], ARMCPU),
125
- VMSTATE_UINT32(env.v7m.control, ARMCPU),
126
+ VMSTATE_UINT32(env.v7m.control[M_REG_NS], ARMCPU),
127
VMSTATE_UINT32(env.v7m.ccr, ARMCPU),
128
VMSTATE_UINT32(env.v7m.cfsr, ARMCPU),
129
VMSTATE_UINT32(env.v7m.hfsr, ARMCPU),
130
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
131
VMSTATE_UINT32(env.v7m.basepri[M_REG_S], ARMCPU),
132
VMSTATE_UINT32(env.v7m.primask[M_REG_S], ARMCPU),
133
VMSTATE_UINT32(env.v7m.faultmask[M_REG_S], ARMCPU),
134
+ VMSTATE_UINT32(env.v7m.control[M_REG_S], ARMCPU),
135
VMSTATE_END_OF_LIST()
136
}
137
};
138
diff --git a/target/arm/translate.c b/target/arm/translate.c
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
139
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
140
--- a/target/arm/translate.c
66
--- a/target/arm/translate.c
141
+++ b/target/arm/translate.c
67
+++ b/target/arm/translate.c
142
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
143
if (xpsr & XPSR_EXCP) {
69
a64_translate_init();
144
mode = "handler";
70
}
145
} else {
71
146
- if (env->v7m.control & R_V7M_CONTROL_NPRIV_MASK) {
72
+/* Generate a label used for skipping this instruction */
147
+ if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) {
73
+static void arm_gen_condlabel(DisasContext *s)
148
mode = "unpriv-thread";
74
+{
149
} else {
75
+ if (!s->condjmp) {
150
mode = "priv-thread";
76
+ s->condlabel = gen_new_label();
77
+ s->condjmp = 1;
78
+ }
79
+}
80
+
81
/* Flags for the disas_set_da_iss info argument:
82
* lower bits hold the Rt register number, higher bits are flags.
83
*/
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
85
long off = neon_element_offset(reg, ele, memop);
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
}
97
98
-/* Generate a label used for skipping this instruction */
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
+{
120
+ int btmreg, topreg;
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
+}
201
+
202
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
203
{
204
/*
151
--
205
--
152
2.7.4
206
2.20.1
153
207
154
208
diff view generated by jsdifflib
1
As the first step in implementing ARM v8M's security extension:
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
2
* add a new feature bit ARM_FEATURE_M_SECURITY
2
the general-purpose registers and APSR. Implement this.
3
* add the CPU state field that indicates whether the CPU is
3
4
currently in the secure state
4
The encoding is a subset of the LDMIA T2 encoding, using what would
5
* add a migration subsection for this new state
5
be Rn=0b1111 (which UNDEFs for LDMIA).
6
(we will add the Secure copies of banked register state
7
to this subsection in later patches)
8
* add a #define for the one new-in-v8M exception type
9
* make the CPU debug log print S/NS status
10
6
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 1503414539-28762-4-git-send-email-peter.maydell@linaro.org
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
14
---
10
---
15
target/arm/cpu.h | 3 +++
11
target/arm/t32.decode | 6 +++++-
16
target/arm/cpu.c | 4 ++++
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
17
target/arm/machine.c | 20 ++++++++++++++++++++
13
2 files changed, 43 insertions(+), 1 deletion(-)
18
target/arm/translate.c | 8 +++++++-
19
4 files changed, 34 insertions(+), 1 deletion(-)
20
14
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
17
--- a/target/arm/t32.decode
24
+++ b/target/arm/cpu.h
18
+++ b/target/arm/t32.decode
25
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
26
#define ARMV7M_EXCP_MEM 4
20
27
#define ARMV7M_EXCP_BUS 5
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
28
#define ARMV7M_EXCP_USAGE 6
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
29
+#define ARMV7M_EXCP_SECURE 7
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
30
#define ARMV7M_EXCP_SVC 11
31
#define ARMV7M_EXCP_DEBUG 12
32
#define ARMV7M_EXCP_PENDSV 14
33
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
34
int exception;
35
uint32_t primask;
36
uint32_t faultmask;
37
+ uint32_t secure; /* Is CPU in Secure state? (not guest visible) */
38
} v7m;
39
40
/* Information associated with an exception about to be taken:
41
@@ -XXX,XX +XXX,XX @@ enum arm_features {
42
ARM_FEATURE_THUMB_DSP, /* DSP insns supported in the Thumb encodings */
43
ARM_FEATURE_PMU, /* has PMU support */
44
ARM_FEATURE_VBAR, /* has cp15 VBAR */
45
+ ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
46
};
47
48
static inline int arm_feature(CPUARMState *env, int feature)
49
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/cpu.c
52
+++ b/target/arm/cpu.c
53
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
54
uint32_t initial_pc; /* Loaded from 0x4 */
55
uint8_t *rom;
56
57
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
58
+ env->v7m.secure = true;
59
+ }
60
+
61
/* The reset value of this bit is IMPDEF, but ARM recommends
62
* that it resets to 1, so QEMU always does that rather than making
63
* it dependent on CPU model.
64
diff --git a/target/arm/machine.c b/target/arm/machine.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/machine.c
67
+++ b/target/arm/machine.c
68
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmsav8 = {
69
}
70
};
71
72
+static bool m_security_needed(void *opaque)
73
+{
24
+{
74
+ ARMCPU *cpu = opaque;
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
75
+ CPUARMState *env = &cpu->env;
26
+ CLRM 1110 1000 1001 1111 list:16
76
+
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
77
+ return arm_feature(env, ARM_FEATURE_M_SECURITY);
78
+}
28
+}
79
+
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
80
+static const VMStateDescription vmstate_m_security = {
30
81
+ .name = "cpu/m-security",
31
&rfe !extern rn w pu
82
+ .version_id = 1,
83
+ .minimum_version_id = 1,
84
+ .needed = m_security_needed,
85
+ .fields = (VMStateField[]) {
86
+ VMSTATE_UINT32(env.v7m.secure, ARMCPU),
87
+ VMSTATE_END_OF_LIST()
88
+ }
89
+};
90
+
91
static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
92
VMStateField *field)
93
{
94
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_arm_cpu = {
95
&vmstate_pmsav7_rnr,
96
&vmstate_pmsav7,
97
&vmstate_pmsav8,
98
+ &vmstate_m_security,
99
NULL
100
}
101
};
102
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
103
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/translate.c
34
--- a/target/arm/translate.c
105
+++ b/target/arm/translate.c
35
+++ b/target/arm/translate.c
106
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
107
if (arm_feature(env, ARM_FEATURE_M)) {
37
return do_ldm(s, a, 1);
108
uint32_t xpsr = xpsr_read(env);
38
}
109
const char *mode;
39
110
+ const char *ns_status = "";
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
41
+{
42
+ int i;
43
+ TCGv_i32 zero;
111
+
44
+
112
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
113
+ ns_status = env->v7m.secure ? "S " : "NS ";
46
+ return false;
47
+ }
48
+
49
+ if (extract32(a->list, 13, 1)) {
50
+ return false;
51
+ }
52
+
53
+ if (!a->list) {
54
+ /* UNPREDICTABLE; we choose to UNDEF */
55
+ return false;
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);
114
+ }
63
+ }
115
64
+ }
116
if (xpsr & XPSR_EXCP) {
65
+ if (extract32(a->list, 15, 1)) {
117
mode = "handler";
66
+ /*
118
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
67
+ * Clear APSR (by calling the MSR helper with the same argument
119
}
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
120
}
69
+ */
121
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
122
- cpu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s\n",
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
123
+ cpu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n",
72
+ tcg_temp_free_i32(maskreg);
124
xpsr,
73
+ }
125
xpsr & XPSR_N ? 'N' : '-',
74
+ tcg_temp_free_i32(zero);
126
xpsr & XPSR_Z ? 'Z' : '-',
75
+ return true;
127
xpsr & XPSR_C ? 'C' : '-',
76
+}
128
xpsr & XPSR_V ? 'V' : '-',
77
+
129
xpsr & XPSR_T ? 'T' : 'A',
78
/*
130
+ ns_status,
79
* Branch, branch with link
131
mode);
80
*/
132
} else {
133
uint32_t psr = cpsr_read(env);
134
--
81
--
135
2.7.4
82
2.20.1
136
83
137
84
diff view generated by jsdifflib
1
Make the MMFAR register banked if v8M security extensions are
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
2
enabled.
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.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 1503414539-28762-18-git-send-email-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-7-peter.maydell@linaro.org
7
---
9
---
8
target/arm/cpu.h | 2 +-
10
target/arm/translate-vfp.c.inc | 5 ++++-
9
hw/intc/armv7m_nvic.c | 4 ++--
11
1 file changed, 4 insertions(+), 1 deletion(-)
10
target/arm/helper.c | 4 ++--
11
target/arm/machine.c | 3 ++-
12
4 files changed, 7 insertions(+), 6 deletions(-)
13
12
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
15
--- a/target/arm/translate-vfp.c.inc
17
+++ b/target/arm/cpu.h
16
+++ b/target/arm/translate-vfp.c.inc
18
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
19
uint32_t cfsr; /* Configurable Fault Status */
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
20
uint32_t hfsr; /* HardFault Status */
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
21
uint32_t dfsr; /* Debug Fault Status Register */
20
*/
22
- uint32_t mmfar; /* MemManage Fault Address */
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
23
+ uint32_t mmfar[2]; /* MemManage Fault Address */
22
+ if (a->reg != ARM_VFP_FPSCR) {
24
uint32_t bfar; /* BusFault Address */
23
+ return false;
25
unsigned mpu_ctrl[2]; /* MPU_CTRL */
24
+ }
26
int exception;
25
+ if (a->rt == 15 && !a->l) {
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
26
return false;
28
index XXXXXXX..XXXXXXX 100644
27
}
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
case 0xd30: /* Debug Fault Status. */
33
return cpu->env.v7m.dfsr;
34
case 0xd34: /* MMFAR MemManage Fault Address */
35
- return cpu->env.v7m.mmfar;
36
+ return cpu->env.v7m.mmfar[attrs.secure];
37
case 0xd38: /* Bus Fault Address. */
38
return cpu->env.v7m.bfar;
39
case 0xd3c: /* Aux Fault Status. */
40
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
41
cpu->env.v7m.dfsr &= ~value; /* W1C */
42
break;
43
case 0xd34: /* Mem Manage Address. */
44
- cpu->env.v7m.mmfar = value;
45
+ cpu->env.v7m.mmfar[attrs.secure] = value;
46
return;
47
case 0xd38: /* Bus Fault Address. */
48
cpu->env.v7m.bfar = value;
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/helper.c
52
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
54
case EXCP_DATA_ABORT:
55
env->v7m.cfsr |=
56
(R_V7M_CFSR_DACCVIOL_MASK | R_V7M_CFSR_MMARVALID_MASK);
57
- env->v7m.mmfar = env->exception.vaddress;
58
+ env->v7m.mmfar[env->v7m.secure] = env->exception.vaddress;
59
qemu_log_mask(CPU_LOG_INT,
60
"...with CFSR.DACCVIOL and MMFAR 0x%x\n",
61
- env->v7m.mmfar);
62
+ env->v7m.mmfar[env->v7m.secure]);
63
break;
64
}
65
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
66
diff --git a/target/arm/machine.c b/target/arm/machine.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/machine.c
69
+++ b/target/arm/machine.c
70
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
71
VMSTATE_UINT32(env.v7m.cfsr, ARMCPU),
72
VMSTATE_UINT32(env.v7m.hfsr, ARMCPU),
73
VMSTATE_UINT32(env.v7m.dfsr, ARMCPU),
74
- VMSTATE_UINT32(env.v7m.mmfar, ARMCPU),
75
+ VMSTATE_UINT32(env.v7m.mmfar[M_REG_NS], ARMCPU),
76
VMSTATE_UINT32(env.v7m.bfar, ARMCPU),
77
VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_NS], ARMCPU),
78
VMSTATE_INT32(env.v7m.exception, ARMCPU),
79
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
80
VMSTATE_VALIDATE("secure MPU_RNR is valid", s_rnr_vmstate_validate),
81
VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_S], ARMCPU),
82
VMSTATE_UINT32(env.v7m.ccr[M_REG_S], ARMCPU),
83
+ VMSTATE_UINT32(env.v7m.mmfar[M_REG_S], ARMCPU),
84
VMSTATE_END_OF_LIST()
85
}
28
}
86
};
87
--
29
--
88
2.7.4
30
2.20.1
89
31
90
32
diff view generated by jsdifflib
1
Make the MPU_CTRL register banked if v8M security extensions are
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
2
enabled.
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
6
* there are several new FP system registers; some have side effects
7
on read, and one (FPCXT_NS) needs to avoid the usual
8
vfp_access_check() and the "only if FPU implemented" check
9
10
* all sysregs are now accessible both by VMRS/VMSR (which
11
reads/writes a general purpose register) and also by VLDR/VSTR
12
(which reads/writes them directly to memory)
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.
3
21
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 1503414539-28762-16-git-send-email-peter.maydell@linaro.org
24
Message-id: 20201119215617.29887-8-peter.maydell@linaro.org
7
---
25
---
8
target/arm/cpu.h | 2 +-
26
target/arm/cpu.h | 3 +
9
hw/intc/armv7m_nvic.c | 9 +++++----
27
target/arm/translate-vfp.c.inc | 182 ++++++++++++++++++++++++++++++---
10
target/arm/helper.c | 5 +++--
28
2 files changed, 171 insertions(+), 14 deletions(-)
11
target/arm/machine.c | 3 ++-
12
4 files changed, 11 insertions(+), 8 deletions(-)
13
29
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
32
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
33
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
19
uint32_t dfsr; /* Debug Fault Status Register */
35
#define ARM_VFP_FPINST 9
20
uint32_t mmfar; /* MemManage Fault Address */
36
#define ARM_VFP_FPINST2 10
21
uint32_t bfar; /* BusFault Address */
37
22
- unsigned mpu_ctrl; /* MPU_CTRL */
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
23
+ unsigned mpu_ctrl[2]; /* MPU_CTRL */
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
24
int exception;
40
+
25
uint32_t primask[2];
41
/* iwMMXt coprocessor control registers. */
26
uint32_t faultmask[2];
42
#define ARM_IWMMXT_wCID 0
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
43
#define ARM_IWMMXT_wCon 1
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
28
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
46
--- a/target/arm/translate-vfp.c.inc
30
+++ b/hw/intc/armv7m_nvic.c
47
+++ b/target/arm/translate-vfp.c.inc
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
32
return cpu->pmsav7_dregion << 8;
49
return true;
33
break;
50
}
34
case 0xd94: /* MPU_CTRL */
51
35
- return cpu->env.v7m.mpu_ctrl;
52
+/*
36
+ return cpu->env.v7m.mpu_ctrl[attrs.secure];
53
+ * M-profile provides two different sets of instructions that can
37
case 0xd98: /* MPU_RNR */
54
+ * access floating point system registers: VMSR/VMRS (which move
38
return cpu->env.pmsav7.rnr[attrs.secure];
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
39
case 0xd9c: /* MPU_RBAR */
56
+ * move directly to/from memory). In some cases there are also side
40
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
57
+ * effects which must happen after any write to memory (which could
41
qemu_log_mask(LOG_GUEST_ERROR, "MPU_CTRL: HFNMIENA and !ENABLE is "
58
+ * cause an exception). So we implement the common logic for the
42
"UNPREDICTABLE\n");
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
43
}
60
+ * which take pointers to callback functions which will perform the
44
- cpu->env.v7m.mpu_ctrl = value & (R_V7M_MPU_CTRL_ENABLE_MASK |
61
+ * actual "read/write general purpose register" and "read/write
45
- R_V7M_MPU_CTRL_HFNMIENA_MASK |
62
+ * memory" operations.
46
- R_V7M_MPU_CTRL_PRIVDEFENA_MASK);
63
+ */
47
+ cpu->env.v7m.mpu_ctrl[attrs.secure]
64
+
48
+ = value & (R_V7M_MPU_CTRL_ENABLE_MASK |
65
+/*
49
+ R_V7M_MPU_CTRL_HFNMIENA_MASK |
66
+ * Emit code to store the sysreg to its final destination; frees the
50
+ R_V7M_MPU_CTRL_PRIVDEFENA_MASK);
67
+ * TCG temp 'value' it is passed.
51
tlb_flush(CPU(cpu));
68
+ */
52
break;
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
53
case 0xd98: /* MPU_RNR */
70
+/*
54
diff --git a/target/arm/helper.c b/target/arm/helper.c
71
+ * Emit code to load the value to be copied to the sysreg; returns
55
index XXXXXXX..XXXXXXX 100644
72
+ * a new TCG temporary
56
--- a/target/arm/helper.c
73
+ */
57
+++ b/target/arm/helper.c
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
58
@@ -XXX,XX +XXX,XX @@ static inline bool regime_translation_disabled(CPUARMState *env,
75
+
59
ARMMMUIdx mmu_idx)
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
+{
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
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
+}
103
+
104
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
105
+
106
+ fp_sysreg_loadfn *loadfn,
107
+ void *opaque)
108
+{
109
+ /* Do a write to an M-profile floating point system register */
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
+}
133
+
134
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
135
+ fp_sysreg_storefn *storefn,
136
+ void *opaque)
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)
60
{
217
{
61
if (arm_feature(env, ARM_FEATURE_M)) {
218
TCGv_i32 tmp;
62
- switch (env->v7m.mpu_ctrl &
219
bool ignore_vfp_enabled = false;
63
+ switch (env->v7m.mpu_ctrl[regime_is_secure(env, mmu_idx)] &
220
64
(R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
65
case R_V7M_MPU_CTRL_ENABLE_MASK:
222
- return false;
66
/* Enabled, but not for HardFault and NMI */
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
67
@@ -XXX,XX +XXX,XX @@ static bool pmsav7_use_background_region(ARMCPU *cpu,
224
+ return gen_M_VMSR_VMRS(s, a);
68
}
225
}
69
226
70
if (arm_feature(env, ARM_FEATURE_M)) {
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
71
- return env->v7m.mpu_ctrl & R_V7M_MPU_CTRL_PRIVDEFENA_MASK;
228
- /*
72
+ return env->v7m.mpu_ctrl[regime_is_secure(env, mmu_idx)]
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
73
+ & R_V7M_MPU_CTRL_PRIVDEFENA_MASK;
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
74
} else {
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
75
return regime_sctlr(env, mmu_idx) & SCTLR_BR;
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;
76
}
241
}
77
diff --git a/target/arm/machine.c b/target/arm/machine.c
242
78
index XXXXXXX..XXXXXXX 100644
243
switch (a->reg) {
79
--- a/target/arm/machine.c
80
+++ b/target/arm/machine.c
81
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
82
VMSTATE_UINT32(env.v7m.dfsr, ARMCPU),
83
VMSTATE_UINT32(env.v7m.mmfar, ARMCPU),
84
VMSTATE_UINT32(env.v7m.bfar, ARMCPU),
85
- VMSTATE_UINT32(env.v7m.mpu_ctrl, ARMCPU),
86
+ VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_NS], ARMCPU),
87
VMSTATE_INT32(env.v7m.exception, ARMCPU),
88
VMSTATE_END_OF_LIST()
89
},
90
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
91
0, vmstate_info_uint32, uint32_t),
92
VMSTATE_UINT32(env.pmsav7.rnr[M_REG_S], ARMCPU),
93
VMSTATE_VALIDATE("secure MPU_RNR is valid", s_rnr_vmstate_validate),
94
+ VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_S], ARMCPU),
95
VMSTATE_END_OF_LIST()
96
}
97
};
98
--
244
--
99
2.7.4
245
2.20.1
100
246
101
247
diff view generated by jsdifflib
1
Move the regime_is_secure() utility function to internals.h;
1
The constant-expander functions like negate, plus_2, etc, are
2
we are going to want to call it from translate.c.
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.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 1503414539-28762-20-git-send-email-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-9-peter.maydell@linaro.org
7
---
8
---
8
target/arm/internals.h | 26 ++++++++++++++++++++++++++
9
target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
9
target/arm/helper.c | 26 --------------------------
10
1 file changed, 25 insertions(+), 21 deletions(-)
10
2 files changed, 26 insertions(+), 26 deletions(-)
11
11
12
diff --git a/target/arm/internals.h b/target/arm/internals.h
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/internals.h
14
--- a/target/arm/translate.c
15
+++ b/target/arm/internals.h
15
+++ b/target/arm/translate.c
16
@@ -XXX,XX +XXX,XX @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
17
}
17
}
18
}
18
}
19
19
20
+/* Return true if this address translation regime is secure */
20
+/*
21
+static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
21
+ * Constant expanders for the decoders.
22
+ */
23
+
24
+static int negate(DisasContext *s, int x)
22
+{
25
+{
23
+ switch (mmu_idx) {
26
+ return -x;
24
+ case ARMMMUIdx_S12NSE0:
25
+ case ARMMMUIdx_S12NSE1:
26
+ case ARMMMUIdx_S1NSE0:
27
+ case ARMMMUIdx_S1NSE1:
28
+ case ARMMMUIdx_S1E2:
29
+ case ARMMMUIdx_S2NS:
30
+ case ARMMMUIdx_MPriv:
31
+ case ARMMMUIdx_MNegPri:
32
+ case ARMMMUIdx_MUser:
33
+ return false;
34
+ case ARMMMUIdx_S1E3:
35
+ case ARMMMUIdx_S1SE0:
36
+ case ARMMMUIdx_S1SE1:
37
+ case ARMMMUIdx_MSPriv:
38
+ case ARMMMUIdx_MSNegPri:
39
+ case ARMMMUIdx_MSUser:
40
+ return true;
41
+ default:
42
+ g_assert_not_reached();
43
+ }
44
+}
27
+}
45
+
28
+
46
#endif
29
+static int plus_2(DisasContext *s, int x)
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
+{
48
index XXXXXXX..XXXXXXX 100644
31
+ return x + 2;
49
--- a/target/arm/helper.c
32
+}
50
+++ b/target/arm/helper.c
33
+
51
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
34
+static int times_2(DisasContext *s, int x)
52
}
35
+{
53
}
36
+ return x * 2;
54
37
+}
55
-/* Return true if this address translation regime is secure */
38
+
56
-static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
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)
57
-{
56
-{
58
- switch (mmu_idx) {
57
- return -x;
59
- case ARMMMUIdx_S12NSE0:
60
- case ARMMMUIdx_S12NSE1:
61
- case ARMMMUIdx_S1NSE0:
62
- case ARMMMUIdx_S1NSE1:
63
- case ARMMMUIdx_S1E2:
64
- case ARMMMUIdx_S2NS:
65
- case ARMMMUIdx_MPriv:
66
- case ARMMMUIdx_MNegPri:
67
- case ARMMMUIdx_MUser:
68
- return false;
69
- case ARMMMUIdx_S1E3:
70
- case ARMMMUIdx_S1SE0:
71
- case ARMMMUIdx_S1SE1:
72
- case ARMMMUIdx_MSPriv:
73
- case ARMMMUIdx_MSNegPri:
74
- case ARMMMUIdx_MSUser:
75
- return true;
76
- default:
77
- g_assert_not_reached();
78
- }
79
-}
58
-}
80
-
59
-
81
/* Return the SCTLR value which controls this address translation regime */
60
-static int plus_2(DisasContext *s, int x)
82
static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
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)
83
{
77
{
84
--
78
--
85
2.7.4
79
2.20.1
86
80
87
81
diff view generated by jsdifflib
1
Implement the BXNS v8M instruction, which is like BX but will do a
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
2
jump-and-switch-to-NonSecure if the branch target address has bit 0
2
read or write FP system registers to memory.
3
clear.
4
5
This is the first piece of code which implements "switch to the
6
other security state", so the commit also includes the code to
7
switch the stack pointers around, which is the only complicated
8
part of switching security state.
9
10
BLXNS is more complicated than just "BXNS but set the link register",
11
so we leave it for a separate commit.
12
3
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 1503414539-28762-21-git-send-email-peter.maydell@linaro.org
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
16
---
7
---
17
target/arm/cpu.h | 13 +++++++++
8
target/arm/vfp.decode | 14 ++++++
18
target/arm/helper.h | 2 ++
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
19
target/arm/translate.h | 1 +
10
2 files changed, 105 insertions(+)
20
target/arm/helper.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++
21
target/arm/machine.c | 2 ++
22
target/arm/translate.c | 42 ++++++++++++++++++++++++++-
23
6 files changed, 138 insertions(+), 1 deletion(-)
24
11
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
26
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/cpu.h
14
--- a/target/arm/vfp.decode
28
+++ b/target/arm/cpu.h
15
+++ b/target/arm/vfp.decode
29
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
30
} cp15;
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
31
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
32
struct {
19
33
+ /* M profile has up to 4 stack pointers:
20
+# M-profile VLDR/VSTR to sysreg
34
+ * a Main Stack Pointer and a Process Stack Pointer for each
21
+%vldr_sysreg 22:1 13:3
35
+ * of the Secure and Non-Secure states. (If the CPU doesn't support
22
+%imm7_0x4 0:7 !function=times_4
36
+ * the security extension then it has only two SPs.)
23
+
37
+ * In QEMU we always store the currently active SP in regs[13],
24
+&vldr_sysreg rn reg imm a w p
38
+ * and the non-active SP for the current security state in
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
39
+ * v7m.other_sp. The stack pointers for the inactive security state
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
40
+ * are stored in other_ss_msp and other_ss_psp.
27
+
41
+ * switch_v7m_security_state() is responsible for rearranging them
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
42
+ * when we change security state.
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
43
+ */
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
44
uint32_t other_sp;
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
45
+ uint32_t other_ss_msp;
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
46
+ uint32_t other_ss_psp;
33
+
47
uint32_t vecbase[2];
34
# We split the load/store multiple up into two patterns to avoid
48
uint32_t basepri[2];
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
49
uint32_t control[2];
36
# grouping:
50
diff --git a/target/arm/helper.h b/target/arm/helper.h
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
51
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/helper.h
39
--- a/target/arm/translate-vfp.c.inc
53
+++ b/target/arm/helper.h
40
+++ b/target/arm/translate-vfp.c.inc
54
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(cpsr_read, i32, env)
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
55
DEF_HELPER_3(v7m_msr, void, env, i32, i32)
42
return true;
56
DEF_HELPER_2(v7m_mrs, i32, env, i32)
43
}
57
44
58
+DEF_HELPER_2(v7m_bxns, void, env, i32)
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;
59
+
50
+
60
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
51
+ if (!a->a) {
61
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
52
+ offset = - offset;
62
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
63
diff --git a/target/arm/translate.h b/target/arm/translate.h
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate.h
66
+++ b/target/arm/translate.h
67
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
68
int vec_len;
69
int vec_stride;
70
bool v7m_handler_mode;
71
+ bool v8m_secure; /* true if v8M and we're in Secure mode */
72
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
73
* so that top level loop can generate correct syndrome information.
74
*/
75
diff --git a/target/arm/helper.c b/target/arm/helper.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/helper.c
78
+++ b/target/arm/helper.c
79
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
80
return 0;
81
}
82
83
+void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
84
+{
85
+ /* translate.c should never generate calls here in user-only mode */
86
+ g_assert_not_reached();
87
+}
88
+
89
void switch_mode(CPUARMState *env, int mode)
90
{
91
ARMCPU *cpu = arm_env_get_cpu(env);
92
@@ -XXX,XX +XXX,XX @@ static uint32_t v7m_pop(CPUARMState *env)
93
return val;
94
}
95
96
+/* Return true if we're using the process stack pointer (not the MSP) */
97
+static bool v7m_using_psp(CPUARMState *env)
98
+{
99
+ /* Handler mode always uses the main stack; for thread mode
100
+ * the CONTROL.SPSEL bit determines the answer.
101
+ * Note that in v7M it is not possible to be in Handler mode with
102
+ * CONTROL.SPSEL non-zero, but in v8M it is, so we must check both.
103
+ */
104
+ return !arm_v7m_is_handler_mode(env) &&
105
+ env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
106
+}
107
+
108
/* Switch to V7M main or process stack pointer. */
109
static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
110
{
111
@@ -XXX,XX +XXX,XX @@ static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
112
}
113
}
114
115
+/* Switch M profile security state between NS and S */
116
+static void switch_v7m_security_state(CPUARMState *env, bool new_secstate)
117
+{
118
+ uint32_t new_ss_msp, new_ss_psp;
119
+
120
+ if (env->v7m.secure == new_secstate) {
121
+ return;
122
+ }
53
+ }
123
+
54
+
124
+ /* All the banked state is accessed by looking at env->v7m.secure
55
+ addr = load_reg(s, a->rn);
125
+ * except for the stack pointer; rearrange the SP appropriately.
56
+ if (a->p) {
126
+ */
57
+ tcg_gen_addi_i32(addr, addr, offset);
127
+ new_ss_msp = env->v7m.other_ss_msp;
128
+ new_ss_psp = env->v7m.other_ss_psp;
129
+
130
+ if (v7m_using_psp(env)) {
131
+ env->v7m.other_ss_psp = env->regs[13];
132
+ env->v7m.other_ss_msp = env->v7m.other_sp;
133
+ } else {
134
+ env->v7m.other_ss_msp = env->regs[13];
135
+ env->v7m.other_ss_psp = env->v7m.other_sp;
136
+ }
58
+ }
137
+
59
+
138
+ env->v7m.secure = new_secstate;
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
62
+ }
139
+
63
+
140
+ if (v7m_using_psp(env)) {
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
141
+ env->regs[13] = new_ss_psp;
65
+ MO_UL | MO_ALIGN | s->be_data);
142
+ env->v7m.other_sp = new_ss_msp;
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);
143
+ } else {
74
+ } else {
144
+ env->regs[13] = new_ss_msp;
75
+ tcg_temp_free_i32(addr);
145
+ env->v7m.other_sp = new_ss_psp;
146
+ }
76
+ }
147
+}
77
+}
148
+
78
+
149
+void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
150
+{
80
+{
151
+ /* Handle v7M BXNS:
81
+ arg_vldr_sysreg *a = opaque;
152
+ * - if the return value is a magic value, do exception return (like BX)
82
+ uint32_t offset = a->imm;
153
+ * - otherwise bit 0 of the return value is the target security state
83
+ TCGv_i32 addr;
154
+ */
84
+ TCGv_i32 value = tcg_temp_new_i32();
155
+ if (dest >= 0xff000000) {
85
+
156
+ /* This is an exception return magic value; put it where
86
+ if (!a->a) {
157
+ * do_v7m_exception_exit() expects and raise EXCEPTION_EXIT.
87
+ offset = - offset;
158
+ * Note that if we ever add gen_ss_advance() singlestep support to
159
+ * M profile this should count as an "instruction execution complete"
160
+ * event (compare gen_bx_excret_final_code()).
161
+ */
162
+ env->regs[15] = dest & ~1;
163
+ env->thumb = dest & 1;
164
+ HELPER(exception_internal)(env, EXCP_EXCEPTION_EXIT);
165
+ /* notreached */
166
+ }
88
+ }
167
+
89
+
168
+ /* translate.c should have made BXNS UNDEF unless we're secure */
90
+ addr = load_reg(s, a->rn);
169
+ assert(env->v7m.secure);
91
+ if (a->p) {
92
+ tcg_gen_addi_i32(addr, addr, offset);
93
+ }
170
+
94
+
171
+ switch_v7m_security_state(env, dest & 1);
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
172
+ env->thumb = 1;
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
173
+ env->regs[15] = dest & ~1;
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;
174
+}
112
+}
175
+
113
+
176
static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
177
{
178
CPUState *cs = CPU(cpu);
179
diff --git a/target/arm/machine.c b/target/arm/machine.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/target/arm/machine.c
182
+++ b/target/arm/machine.c
183
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
184
.needed = m_security_needed,
185
.fields = (VMStateField[]) {
186
VMSTATE_UINT32(env.v7m.secure, ARMCPU),
187
+ VMSTATE_UINT32(env.v7m.other_ss_msp, ARMCPU),
188
+ VMSTATE_UINT32(env.v7m.other_ss_psp, ARMCPU),
189
VMSTATE_UINT32(env.v7m.basepri[M_REG_S], ARMCPU),
190
VMSTATE_UINT32(env.v7m.primask[M_REG_S], ARMCPU),
191
VMSTATE_UINT32(env.v7m.faultmask[M_REG_S], ARMCPU),
192
diff --git a/target/arm/translate.c b/target/arm/translate.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/target/arm/translate.c
195
+++ b/target/arm/translate.c
196
@@ -XXX,XX +XXX,XX @@ static inline void gen_bx_excret_final_code(DisasContext *s)
197
gen_exception_internal(EXCP_EXCEPTION_EXIT);
198
}
199
200
+static inline void gen_bxns(DisasContext *s, int rm)
201
+{
115
+{
202
+ TCGv_i32 var = load_reg(s, rm);
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
203
+
117
+ return false;
204
+ /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
118
+ }
205
+ * we need to sync state before calling it, but:
119
+ if (a->rn == 15) {
206
+ * - we don't need to do gen_set_pc_im() because the bxns helper will
120
+ return false;
207
+ * always set the PC itself
121
+ }
208
+ * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
209
+ * unless it's outside an IT block or the last insn in an IT block,
210
+ * so we know that condexec == 0 (already set at the top of the TB)
211
+ * is correct in the non-UNPREDICTABLE cases, and we can choose
212
+ * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
213
+ */
214
+ gen_helper_v7m_bxns(cpu_env, var);
215
+ tcg_temp_free_i32(var);
216
+ s->is_jmp = DISAS_EXIT;
217
+}
123
+}
218
+
124
+
219
/* Variant of store_reg which uses branch&exchange logic when storing
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
220
to r15 in ARM architecture v7 and above. The source must be a temporary
126
+{
221
and will be marked as dead. */
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
222
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
128
+ return false;
223
*/
129
+ }
224
bool link = insn & (1 << 7);
130
+ if (a->rn == 15) {
225
131
+ return false;
226
- if (insn & 7) {
132
+ }
227
+ if (insn & 3) {
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
228
goto undef;
134
+}
229
}
135
+
230
if (link) {
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
231
ARCH(5);
137
{
232
}
138
TCGv_i32 tmp;
233
+ if ((insn & 4)) {
234
+ /* BXNS/BLXNS: only exists for v8M with the
235
+ * security extensions, and always UNDEF if NonSecure.
236
+ * We don't implement these in the user-only mode
237
+ * either (in theory you can use them from Secure User
238
+ * mode but they are too tied in to system emulation.)
239
+ */
240
+ if (!s->v8m_secure || IS_USER_ONLY) {
241
+ goto undef;
242
+ }
243
+ if (link) {
244
+ /* BLXNS: not yet implemented */
245
+ goto undef;
246
+ } else {
247
+ gen_bxns(s, rm);
248
+ }
249
+ break;
250
+ }
251
+ /* BLX/BX */
252
tmp = load_reg(s, rm);
253
if (link) {
254
val = (uint32_t)s->pc | 1;
255
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
256
dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
257
dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
258
dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(tb->flags);
259
+ dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
260
+ regime_is_secure(env, dc->mmu_idx);
261
dc->cp_regs = cpu->cp_regs;
262
dc->features = env->features;
263
264
--
139
--
265
2.7.4
140
2.20.1
266
141
267
142
diff view generated by jsdifflib
1
Make the PRIMASK register banked if v8M security extensions are enabled.
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.)
2
6
3
Note that we do not yet implement the functionality of the new
7
Implement the register. Since we don't yet implement MVE, we handle
4
AIRCR.PRIS bit (which allows the effect of the NS copy of PRIMASK to
8
the QC bit as RES0, with todo comments for where we will need to add
5
be restricted).
9
support later.
6
10
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1503414539-28762-8-git-send-email-peter.maydell@linaro.org
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
10
---
14
---
11
target/arm/cpu.h | 2 +-
15
target/arm/cpu.h | 13 +++++++++++++
12
hw/intc/armv7m_nvic.c | 2 +-
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
13
target/arm/helper.c | 4 ++--
17
2 files changed, 40 insertions(+)
14
target/arm/machine.c | 9 +++++++--
15
4 files changed, 11 insertions(+), 6 deletions(-)
16
18
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
21
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
22
uint32_t bfar; /* BusFault Address */
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
23
unsigned mpu_ctrl; /* MPU_CTRL */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
24
int exception;
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
25
- uint32_t primask;
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
26
+ uint32_t primask[2];
28
+#define FPCR_C (1 << 29) /* FP carry flag */
27
uint32_t faultmask;
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
28
uint32_t secure; /* Is CPU in Secure state? (not guest visible) */
30
+#define FPCR_N (1 << 31) /* FP negative flag */
29
} v7m;
31
+
30
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
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
31
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/intc/armv7m_nvic.c
52
--- a/target/arm/translate-vfp.c.inc
33
+++ b/hw/intc/armv7m_nvic.c
53
+++ b/target/arm/translate-vfp.c.inc
34
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
35
55
case ARM_VFP_FPSCR:
36
if (env->v7m.faultmask) {
56
case QEMU_VFP_FPSCR_NZCV:
37
running = -1;
38
- } else if (env->v7m.primask) {
39
+ } else if (env->v7m.primask[env->v7m.secure]) {
40
running = 0;
41
} else if (env->v7m.basepri[env->v7m.secure] > 0) {
42
running = env->v7m.basepri[env->v7m.secure] & nvic_gprio_mask(s);
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 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
48
return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ?
49
env->regs[13] : env->v7m.other_sp;
50
case 16: /* PRIMASK */
51
- return env->v7m.primask;
52
+ return env->v7m.primask[env->v7m.secure];
53
case 17: /* BASEPRI */
54
case 18: /* BASEPRI_MAX */
55
return env->v7m.basepri[env->v7m.secure];
56
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
57
}
58
break;
57
break;
59
case 16: /* PRIMASK */
58
+ case ARM_VFP_FPSCR_NZCVQC:
60
- env->v7m.primask = val & 1;
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
61
+ env->v7m.primask[env->v7m.secure] = val & 1;
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);
62
break;
69
break;
63
case 17: /* BASEPRI */
70
+ case ARM_VFP_FPSCR_NZCVQC:
64
env->v7m.basepri[env->v7m.secure] = val & 0xff;
71
+ {
65
diff --git a/target/arm/machine.c b/target/arm/machine.c
72
+ TCGv_i32 fpscr;
66
index XXXXXXX..XXXXXXX 100644
73
+ tmp = loadfn(s, opaque);
67
--- a/target/arm/machine.c
74
+ /*
68
+++ b/target/arm/machine.c
75
+ * TODO: when we implement MVE, write the QC bit.
69
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_faultmask_primask = {
76
+ * For non-MVE, QC is RES0.
70
.minimum_version_id = 1,
77
+ */
71
.fields = (VMStateField[]) {
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
72
VMSTATE_UINT32(env.v7m.faultmask, ARMCPU),
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
73
- VMSTATE_UINT32(env.v7m.primask, ARMCPU),
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
74
+ VMSTATE_UINT32(env.v7m.primask[M_REG_NS], ARMCPU),
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
75
VMSTATE_END_OF_LIST()
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();
76
}
88
}
77
};
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
78
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
79
.fields = (VMStateField[]) {
91
storefn(s, opaque, tmp);
80
VMSTATE_UINT32(env.v7m.secure, ARMCPU),
92
break;
81
VMSTATE_UINT32(env.v7m.basepri[M_REG_S], ARMCPU),
93
+ case ARM_VFP_FPSCR_NZCVQC:
82
+ VMSTATE_UINT32(env.v7m.primask[M_REG_S], ARMCPU),
94
+ /*
83
VMSTATE_END_OF_LIST()
95
+ * TODO: MVE has a QC bit, which we probably won't store
84
}
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
85
};
97
+ * we can just fall through to the FPSCR_NZCV case.
86
@@ -XXX,XX +XXX,XX @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
98
+ */
87
* differences are that the T bit is not in the same place, the
99
case QEMU_VFP_FPSCR_NZCV:
88
* primask/faultmask info may be in the CPSR I and F bits, and
100
/*
89
* we do not want the mode bits.
101
* Read just NZCV; this is a special case to avoid the
90
+ * We know that this cleanup happened before v8M, so there
91
+ * is no complication with banked primask/faultmask.
92
*/
93
uint32_t newval = val;
94
95
+ assert(!arm_feature(env, ARM_FEATURE_M_SECURITY));
96
+
97
newval &= (CPSR_NZCV | CPSR_Q | CPSR_IT | CPSR_GE);
98
if (val & CPSR_T) {
99
newval |= XPSR_T;
100
@@ -XXX,XX +XXX,XX @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
101
env->v7m.faultmask = 1;
102
}
103
if (val & CPSR_I) {
104
- env->v7m.primask = 1;
105
+ env->v7m.primask[M_REG_NS] = 1;
106
}
107
val = newval;
108
}
109
--
102
--
110
2.7.4
103
2.20.1
111
104
112
105
diff view generated by jsdifflib
1
Make the VTOR register banked if v8M security extensions are enabled.
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.
2
5
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 1503414539-28762-12-git-send-email-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-12-peter.maydell@linaro.org
6
---
9
---
7
target/arm/cpu.h | 2 +-
10
target/arm/translate-vfp.c.inc | 4 ++--
8
hw/intc/armv7m_nvic.c | 13 +++++++------
11
1 file changed, 2 insertions(+), 2 deletions(-)
9
target/arm/helper.c | 2 +-
10
target/arm/machine.c | 3 ++-
11
4 files changed, 11 insertions(+), 9 deletions(-)
12
12
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/cpu.h
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
18
18
* helper call for the "VMRS to CPSR.NZCV" insn.
19
struct {
19
*/
20
uint32_t other_sp;
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
21
- uint32_t vecbase;
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
22
+ uint32_t vecbase[2];
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
uint32_t basepri[2];
23
storefn(s, opaque, tmp);
24
uint32_t control[2];
25
uint32_t ccr; /* Configuration and Control */
26
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/intc/armv7m_nvic.c
29
+++ b/hw/intc/armv7m_nvic.c
30
@@ -XXX,XX +XXX,XX @@ static void set_irq_level(void *opaque, int n, int level)
31
}
32
}
33
34
-static uint32_t nvic_readl(NVICState *s, uint32_t offset)
35
+static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
36
{
37
ARMCPU *cpu = s->cpu;
38
uint32_t val;
39
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
40
/* ISRPREEMPT not implemented */
41
return val;
42
case 0xd08: /* Vector Table Offset. */
43
- return cpu->env.v7m.vecbase;
44
+ return cpu->env.v7m.vecbase[attrs.secure];
45
case 0xd0c: /* Application Interrupt/Reset Control. */
46
return 0xfa050000 | (s->prigroup << 8);
47
case 0xd10: /* System Control. */
48
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
49
}
50
}
51
52
-static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
53
+static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
54
+ MemTxAttrs attrs)
55
{
56
ARMCPU *cpu = s->cpu;
57
58
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
59
}
60
break;
61
case 0xd08: /* Vector Table Offset. */
62
- cpu->env.v7m.vecbase = value & 0xffffff80;
63
+ cpu->env.v7m.vecbase[attrs.secure] = value & 0xffffff80;
64
break;
65
case 0xd0c: /* Application Interrupt/Reset Control. */
66
if ((value >> 16) == 0x05fa) {
67
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
68
break;
24
break;
69
default:
25
default:
70
if (size == 4) {
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
71
- val = nvic_readl(s, offset);
27
case ARM_VFP_FPSCR:
72
+ val = nvic_readl(s, offset, attrs);
28
if (a->rt == 15) {
73
} else {
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
74
qemu_log_mask(LOG_GUEST_ERROR,
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
75
"NVIC: Bad read of size %d at offset 0x%x\n",
31
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
76
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
32
} else {
77
return MEMTX_OK;
33
tmp = tcg_temp_new_i32();
78
}
34
gen_helper_vfp_get_fpscr(tmp, cpu_env);
79
if (size == 4) {
80
- nvic_writel(s, offset, value);
81
+ nvic_writel(s, offset, value, attrs);
82
return MEMTX_OK;
83
}
84
qemu_log_mask(LOG_GUEST_ERROR,
85
diff --git a/target/arm/helper.c b/target/arm/helper.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/helper.c
88
+++ b/target/arm/helper.c
89
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
90
CPUState *cs = CPU(cpu);
91
CPUARMState *env = &cpu->env;
92
MemTxResult result;
93
- hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
94
+ hwaddr vec = env->v7m.vecbase[env->v7m.secure] + env->v7m.exception * 4;
95
uint32_t addr;
96
97
addr = address_space_ldl(cs->as, vec,
98
diff --git a/target/arm/machine.c b/target/arm/machine.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/target/arm/machine.c
101
+++ b/target/arm/machine.c
102
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
103
.minimum_version_id = 4,
104
.needed = m_needed,
105
.fields = (VMStateField[]) {
106
- VMSTATE_UINT32(env.v7m.vecbase, ARMCPU),
107
+ VMSTATE_UINT32(env.v7m.vecbase[M_REG_NS], ARMCPU),
108
VMSTATE_UINT32(env.v7m.basepri[M_REG_NS], ARMCPU),
109
VMSTATE_UINT32(env.v7m.control[M_REG_NS], ARMCPU),
110
VMSTATE_UINT32(env.v7m.ccr, ARMCPU),
111
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
112
VMSTATE_UINT32(env.v7m.primask[M_REG_S], ARMCPU),
113
VMSTATE_UINT32(env.v7m.faultmask[M_REG_S], ARMCPU),
114
VMSTATE_UINT32(env.v7m.control[M_REG_S], ARMCPU),
115
+ VMSTATE_UINT32(env.v7m.vecbase[M_REG_S], ARMCPU),
116
VMSTATE_END_OF_LIST()
117
}
118
};
119
--
35
--
120
2.7.4
36
2.20.1
121
37
122
38
diff view generated by jsdifflib
1
Implement the new do_transaction_failed hook for ARM, which should
1
Factor out the code which handles M-profile lazy FP state preservation
2
cause the CPU to take a prefetch abort or data abort.
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.
3
7
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 1504626814-23124-4-git-send-email-peter.maydell@linaro.org
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
8
---
12
---
9
target/arm/internals.h | 10 ++++++++++
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
10
target/arm/cpu.c | 1 +
14
1 file changed, 27 insertions(+), 18 deletions(-)
11
target/arm/op_helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
12
3 files changed, 54 insertions(+)
13
15
14
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/internals.h
18
--- a/target/arm/translate-vfp.c.inc
17
+++ b/target/arm/internals.h
19
+++ b/target/arm/translate-vfp.c.inc
18
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
19
MMUAccessType access_type,
21
return offs;
20
int mmu_idx, uintptr_t retaddr);
22
}
21
23
22
+/* arm_cpu_do_transaction_failed: handle a memory system error response
24
+/*
23
+ * (eg "no device/memory present at address") by raising an external abort
25
+ * Generate code for M-profile lazy FP state preservation if needed;
24
+ * exception
26
+ * this corresponds to the pseudocode PreserveFPState() function.
25
+ */
27
+ */
26
+void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
28
+static void gen_preserve_fp_state(DisasContext *s)
27
+ vaddr addr, unsigned size,
28
+ MMUAccessType access_type,
29
+ int mmu_idx, MemTxAttrs attrs,
30
+ MemTxResult response, uintptr_t retaddr);
31
+
32
/* Call the EL change hook if one has been registered */
33
static inline void arm_call_el_change_hook(ARMCPU *cpu)
34
{
35
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.c
38
+++ b/target/arm/cpu.c
39
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
40
#else
41
cc->do_interrupt = arm_cpu_do_interrupt;
42
cc->do_unaligned_access = arm_cpu_do_unaligned_access;
43
+ cc->do_transaction_failed = arm_cpu_do_transaction_failed;
44
cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
45
cc->asidx_from_attrs = arm_asidx_from_attrs;
46
cc->vmsd = &vmstate_arm_cpu;
47
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/op_helper.c
50
+++ b/target/arm/op_helper.c
51
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
52
deliver_fault(cpu, vaddr, access_type, fsr, fsc, &fi);
53
}
54
55
+/* arm_cpu_do_transaction_failed: handle a memory system error response
56
+ * (eg "no device/memory present at address") by raising an external abort
57
+ * exception
58
+ */
59
+void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
60
+ vaddr addr, unsigned size,
61
+ MMUAccessType access_type,
62
+ int mmu_idx, MemTxAttrs attrs,
63
+ MemTxResult response, uintptr_t retaddr)
64
+{
29
+{
65
+ ARMCPU *cpu = ARM_CPU(cs);
30
+ if (s->v7m_lspact) {
66
+ CPUARMState *env = &cpu->env;
31
+ /*
67
+ uint32_t fsr, fsc;
32
+ * Lazy state saving affects external memory and also the NVIC,
68
+ ARMMMUFaultInfo fi = {};
33
+ * so we must mark it as an IO operation for icount (and cause
69
+ ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
34
+ * this to be the last insn in the TB).
70
+
35
+ */
71
+ if (retaddr) {
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
72
+ /* now we have a real cpu fault */
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
73
+ cpu_restore_state(cs, retaddr);
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;
74
+ }
47
+ }
75
+
76
+ /* The EA bit in syndromes and fault status registers is an
77
+ * IMPDEF classification of external aborts. ARM implementations
78
+ * usually use this to indicate AXI bus Decode error (0) or
79
+ * Slave error (1); in QEMU we follow that.
80
+ */
81
+ fi.ea = (response != MEMTX_DECODE_ERROR);
82
+
83
+ /* The fault status register format depends on whether we're using
84
+ * the LPAE long descriptor format, or the short descriptor format.
85
+ */
86
+ if (arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
87
+ /* long descriptor form, STATUS 0b010000: synchronous ext abort */
88
+ fsr = (fi.ea << 12) | (1 << 9) | 0x10;
89
+ } else {
90
+ /* short descriptor form, FSR 0b01000 : synchronous ext abort */
91
+ fsr = (fi.ea << 12) | 0x8;
92
+ }
93
+ fsc = 0x10;
94
+
95
+ deliver_fault(cpu, addr, access_type, fsr, fsc, &fi);
96
+}
48
+}
97
+
49
+
98
#endif /* !defined(CONFIG_USER_ONLY) */
50
/*
99
51
* Check that VFP access is enabled. If it is, do the necessary
100
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
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) {
101
--
79
--
102
2.7.4
80
2.20.1
103
81
104
82
diff view generated by jsdifflib
1
Now that MPU lookups can return different results for v8M
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
2
when the CPU is in secure vs non-secure state, we need to
2
This is for saving and restoring the secure floating point context,
3
have separate MMU indexes; add the secure counterparts
3
and it reads and writes bits [27:0] from the FPSCR and the
4
to the existing three M profile MMU indexes.
4
CONTROL.SFPA bit in bit [31].
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 1503414539-28762-6-git-send-email-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
9
---
9
---
10
target/arm/cpu.h | 19 +++++++++++++++++--
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
11
target/arm/helper.c | 9 ++++++++-
11
1 file changed, 58 insertions(+)
12
2 files changed, 25 insertions(+), 3 deletions(-)
13
12
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
15
--- a/target/arm/translate-vfp.c.inc
17
+++ b/target/arm/cpu.h
16
+++ b/target/arm/translate-vfp.c.inc
18
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
19
* Execution priority negative (this is like privileged, but the
18
return false;
20
* MPU HFNMIENA bit means that it may have different access permission
19
}
21
* check results to normal privileged code, so can't share a TLB).
20
break;
22
+ * If the CPU supports the v8M Security Extension then there are also:
21
+ case ARM_VFP_FPCXT_S:
23
+ * Secure User
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
24
+ * Secure Privileged
23
+ return false;
25
+ * Secure, execution priority negative
24
+ }
26
*
25
+ if (!s->v8m_secure) {
27
* The ARMMMUIdx and the mmu index value used by the core QEMU TLB code
26
+ return false;
28
* are not quite the same -- different CPU types (most notably M profile
27
+ }
29
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
28
+ break;
30
ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M,
29
default:
31
ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M,
30
return FPSysRegCheckFailed;
32
ARMMMUIdx_MNegPri = 2 | ARM_MMU_IDX_M,
31
}
33
+ ARMMMUIdx_MSUser = 3 | ARM_MMU_IDX_M,
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
34
+ ARMMMUIdx_MSPriv = 4 | ARM_MMU_IDX_M,
33
tcg_temp_free_i32(tmp);
35
+ ARMMMUIdx_MSNegPri = 5 | ARM_MMU_IDX_M,
34
break;
36
/* Indexes below here don't have TLBs and are used only for AT system
35
}
37
* instructions or for the first stage of an S12 page table walk.
36
+ case ARM_VFP_FPCXT_S:
38
*/
37
+ {
39
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
38
+ TCGv_i32 sfpa, control, fpscr;
40
ARMMMUIdxBit_MUser = 1 << 0,
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
41
ARMMMUIdxBit_MPriv = 1 << 1,
40
+ tmp = loadfn(s, opaque);
42
ARMMMUIdxBit_MNegPri = 1 << 2,
41
+ sfpa = tcg_temp_new_i32();
43
+ ARMMMUIdxBit_MSUser = 1 << 3,
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
44
+ ARMMMUIdxBit_MSPriv = 1 << 4,
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
45
+ ARMMMUIdxBit_MSNegPri = 1 << 5,
44
+ tcg_gen_deposit_i32(control, control, sfpa,
46
} ARMMMUIdxBit;
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
47
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
48
#define MMU_USER_IDX 0
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
49
@@ -XXX,XX +XXX,XX @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
50
case ARM_MMU_IDX_A:
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
51
return mmu_idx & 3;
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
52
case ARM_MMU_IDX_M:
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
53
- return mmu_idx == ARMMMUIdx_MUser ? 0 : 1;
52
+ tcg_temp_free_i32(tmp);
54
+ return (mmu_idx == ARMMMUIdx_MUser || mmu_idx == ARMMMUIdx_MSUser)
53
+ tcg_temp_free_i32(sfpa);
55
+ ? 0 : 1;
54
+ break;
55
+ }
56
default:
56
default:
57
g_assert_not_reached();
57
g_assert_not_reached();
58
}
58
}
59
@@ -XXX,XX +XXX,XX @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
60
*/
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
61
if ((env->v7m.exception > 0 && env->v7m.exception <= 3)
61
storefn(s, opaque, tmp);
62
|| env->v7m.faultmask) {
62
break;
63
- return arm_to_core_mmu_idx(ARMMMUIdx_MNegPri);
63
+ case ARM_VFP_FPCXT_S:
64
+ mmu_idx = ARMMMUIdx_MNegPri;
64
+ {
65
+ }
65
+ TCGv_i32 control, sfpa, fpscr;
66
+
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
67
+ if (env->v7m.secure) {
67
+ tmp = tcg_temp_new_i32();
68
+ mmu_idx += ARMMMUIdx_MSUser;
68
+ sfpa = tcg_temp_new_i32();
69
}
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
70
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
71
return arm_to_core_mmu_idx(mmu_idx);
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
72
diff --git a/target/arm/helper.c b/target/arm/helper.c
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
73
index XXXXXXX..XXXXXXX 100644
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
74
--- a/target/arm/helper.c
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
75
+++ b/target/arm/helper.c
75
+ tcg_temp_free_i32(sfpa);
76
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
76
+ /*
77
case ARMMMUIdx_MPriv:
77
+ * Store result before updating FPSCR etc, in case
78
case ARMMMUIdx_MNegPri:
78
+ * it is a memory write which causes an exception.
79
case ARMMMUIdx_MUser:
79
+ */
80
+ case ARMMMUIdx_MSPriv:
80
+ storefn(s, opaque, tmp);
81
+ case ARMMMUIdx_MSNegPri:
81
+ /*
82
+ case ARMMMUIdx_MSUser:
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
83
return 1;
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;
92
+ }
84
default:
93
default:
85
g_assert_not_reached();
94
g_assert_not_reached();
86
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
95
}
87
case ARMMMUIdx_S1E3:
88
case ARMMMUIdx_S1SE0:
89
case ARMMMUIdx_S1SE1:
90
+ case ARMMMUIdx_MSPriv:
91
+ case ARMMMUIdx_MSNegPri:
92
+ case ARMMMUIdx_MSUser:
93
return true;
94
default:
95
g_assert_not_reached();
96
@@ -XXX,XX +XXX,XX @@ static inline bool regime_translation_disabled(CPUARMState *env,
97
(R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {
98
case R_V7M_MPU_CTRL_ENABLE_MASK:
99
/* Enabled, but not for HardFault and NMI */
100
- return mmu_idx == ARMMMUIdx_MNegPri;
101
+ return mmu_idx == ARMMMUIdx_MNegPri ||
102
+ mmu_idx == ARMMMUIdx_MSNegPri;
103
case R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK:
104
/* Enabled for all cases */
105
return false;
106
--
96
--
107
2.7.4
97
2.20.1
108
98
109
99
diff view generated by jsdifflib
1
Make the CCR register banked if v8M security extensions are enabled.
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
2
2
gains new fields FZ16 (if half-precision floating point is supported)
3
This is slightly more complicated than the other "add banking"
3
and LTPSIZE (always reads as 4). Update the reset value and the code
4
patches because there is one bit in the register which is not
4
that handles writes to this register accordingly.
5
banked. We keep the live data in the NS copy of the register,
6
and adjust it on register reads and writes. (Since we don't
7
currently implement the behaviour that the bit controls, there
8
is nowhere else that needs to care.)
9
10
This patch includes the enforcement of the bits which are newly
11
RES1 in ARMv8M.
12
5
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 1503414539-28762-17-git-send-email-peter.maydell@linaro.org
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
15
---
9
---
16
target/arm/cpu.h | 2 +-
10
target/arm/cpu.h | 5 +++++
17
hw/intc/armv7m_nvic.c | 33 +++++++++++++++++++++++++++------
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
18
target/arm/cpu.c | 12 +++++++++---
12
target/arm/cpu.c | 3 +++
19
target/arm/helper.c | 5 +++--
13
3 files changed, 16 insertions(+), 1 deletion(-)
20
target/arm/machine.c | 3 ++-
21
5 files changed, 42 insertions(+), 13 deletions(-)
22
14
23
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
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
26
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
28
uint32_t vecbase[2];
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
29
uint32_t basepri[2];
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
30
uint32_t control[2];
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
31
- uint32_t ccr; /* Configuration and Control */
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
32
+ uint32_t ccr[2]; /* Configuration and Control */
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
33
uint32_t cfsr; /* Configurable Fault Status */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
34
uint32_t hfsr; /* HardFault Status */
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
35
uint32_t dfsr; /* Debug Fault Status Register */
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
36
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
37
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/intc/armv7m_nvic.c
41
--- a/hw/intc/armv7m_nvic.c
39
+++ b/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
40
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
41
/* TODO: Implement SLEEPONEXIT. */
42
return 0;
43
case 0xd14: /* Configuration Control. */
44
- return cpu->env.v7m.ccr;
45
+ /* The BFHFNMIGN bit is the only non-banked bit; we
46
+ * keep it in the non-secure copy of the register.
47
+ */
48
+ val = cpu->env.v7m.ccr[attrs.secure];
49
+ val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
50
+ return val;
51
case 0xd24: /* System Handler Status. */
52
val = 0;
53
if (s->vectors[ARMV7M_EXCP_MEM].active) {
54
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
55
R_V7M_CCR_USERSETMPEND_MASK |
56
R_V7M_CCR_NONBASETHRDENA_MASK);
57
58
- cpu->env.v7m.ccr = value;
59
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
60
+ /* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
61
+ value |= R_V7M_CCR_NONBASETHRDENA_MASK
62
+ | R_V7M_CCR_STKALIGN_MASK;
63
+ }
64
+ if (attrs.secure) {
65
+ /* the BFHFNMIGN bit is not banked; keep that in the NS copy */
66
+ cpu->env.v7m.ccr[M_REG_NS] =
67
+ (cpu->env.v7m.ccr[M_REG_NS] & ~R_V7M_CCR_BFHFNMIGN_MASK)
68
+ | (value & R_V7M_CCR_BFHFNMIGN_MASK);
69
+ value &= ~R_V7M_CCR_BFHFNMIGN_MASK;
70
+ }
71
+
72
+ cpu->env.v7m.ccr[attrs.secure] = value;
73
break;
44
break;
74
case 0xd24: /* System Handler Control. */
45
case 0xf3c: /* FPDSCR */
75
s->vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
76
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
47
- value &= 0x07c00000;
77
}
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
78
}
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
79
50
+ mask |= FPCR_FZ16;
80
-static bool nvic_user_access_ok(NVICState *s, hwaddr offset)
51
+ }
81
+static bool nvic_user_access_ok(NVICState *s, hwaddr offset, MemTxAttrs attrs)
52
+ value &= mask;
82
{
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
83
/* Return true if unprivileged access to this register is permitted. */
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
84
switch (offset) {
55
+ }
85
case 0xf00: /* STIR: accessible only if CCR.USERSETMPEND permits */
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
86
- return s->cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK;
57
}
87
+ /* For access via STIR_NS it is the NS CCR.USERSETMPEND that
58
break;
88
+ * controls access even though the CPU is in Secure state (I_QDKX).
89
+ */
90
+ return s->cpu->env.v7m.ccr[attrs.secure] & R_V7M_CCR_USERSETMPEND_MASK;
91
default:
92
/* All other user accesses cause a BusFault unconditionally */
93
return false;
94
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
95
unsigned i, startvec, end;
96
uint32_t val;
97
98
- if (attrs.user && !nvic_user_access_ok(s, addr)) {
99
+ if (attrs.user && !nvic_user_access_ok(s, addr, attrs)) {
100
/* Generate BusFault for unprivileged accesses */
101
return MEMTX_ERROR;
102
}
103
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
104
105
trace_nvic_sysreg_write(addr, value, size);
106
107
- if (attrs.user && !nvic_user_access_ok(s, addr)) {
108
+ if (attrs.user && !nvic_user_access_ok(s, addr, attrs)) {
109
/* Generate BusFault for unprivileged accesses */
110
return MEMTX_ERROR;
111
}
112
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
113
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/cpu.c
61
--- a/target/arm/cpu.c
115
+++ b/target/arm/cpu.c
62
+++ b/target/arm/cpu.c
116
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
117
env->v7m.secure = true;
64
* always reset to 4.
65
*/
66
env->v7m.ltpsize = 4;
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
118
}
70
}
119
71
120
- /* The reset value of this bit is IMPDEF, but ARM recommends
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
121
+ /* In v7M the reset value of this bit is IMPDEF, but ARM recommends
122
* that it resets to 1, so QEMU always does that rather than making
123
- * it dependent on CPU model.
124
+ * it dependent on CPU model. In v8M it is RES1.
125
*/
126
- env->v7m.ccr = R_V7M_CCR_STKALIGN_MASK;
127
+ env->v7m.ccr[M_REG_NS] = R_V7M_CCR_STKALIGN_MASK;
128
+ env->v7m.ccr[M_REG_S] = R_V7M_CCR_STKALIGN_MASK;
129
+ if (arm_feature(env, ARM_FEATURE_V8)) {
130
+ /* in v8M the NONBASETHRDENA bit [0] is RES1 */
131
+ env->v7m.ccr[M_REG_NS] |= R_V7M_CCR_NONBASETHRDENA_MASK;
132
+ env->v7m.ccr[M_REG_S] |= R_V7M_CCR_NONBASETHRDENA_MASK;
133
+ }
134
135
/* Unlike A/R profile, M profile defines the reset LR value */
136
env->regs[14] = 0xffffffff;
137
diff --git a/target/arm/helper.c b/target/arm/helper.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/target/arm/helper.c
140
+++ b/target/arm/helper.c
141
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
142
uint32_t xpsr = xpsr_read(env);
143
144
/* Align stack pointer if the guest wants that */
145
- if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
146
+ if ((env->regs[13] & 4) &&
147
+ (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKALIGN_MASK)) {
148
env->regs[13] -= 4;
149
xpsr |= XPSR_SPREALIGN;
150
}
151
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
152
/* fall through */
153
case 9: /* Return to Thread using Main stack */
154
if (!rettobase &&
155
- !(env->v7m.ccr & R_V7M_CCR_NONBASETHRDENA_MASK)) {
156
+ !(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_NONBASETHRDENA_MASK)) {
157
ufault = true;
158
}
159
break;
160
diff --git a/target/arm/machine.c b/target/arm/machine.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/target/arm/machine.c
163
+++ b/target/arm/machine.c
164
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
165
VMSTATE_UINT32(env.v7m.vecbase[M_REG_NS], ARMCPU),
166
VMSTATE_UINT32(env.v7m.basepri[M_REG_NS], ARMCPU),
167
VMSTATE_UINT32(env.v7m.control[M_REG_NS], ARMCPU),
168
- VMSTATE_UINT32(env.v7m.ccr, ARMCPU),
169
+ VMSTATE_UINT32(env.v7m.ccr[M_REG_NS], ARMCPU),
170
VMSTATE_UINT32(env.v7m.cfsr, ARMCPU),
171
VMSTATE_UINT32(env.v7m.hfsr, ARMCPU),
172
VMSTATE_UINT32(env.v7m.dfsr, ARMCPU),
173
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
174
VMSTATE_UINT32(env.pmsav7.rnr[M_REG_S], ARMCPU),
175
VMSTATE_VALIDATE("secure MPU_RNR is valid", s_rnr_vmstate_validate),
176
VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_S], ARMCPU),
177
+ VMSTATE_UINT32(env.v7m.ccr[M_REG_S], ARMCPU),
178
VMSTATE_END_OF_LIST()
179
}
180
};
181
--
73
--
182
2.7.4
74
2.20.1
183
75
184
76
diff view generated by jsdifflib
New 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.
1
5
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
New 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.)
1
4
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
1
Make the CFSR register banked if v8M security extensions are enabled.
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
2
2
and is a read-only IMPDEF register providing implementation specific
3
Not all the bits in this register are banked: the BFSR
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
4
bits [15:8] are shared between S and NS, and we store them
5
in the NS copy of the register.
6
4
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1503414539-28762-19-git-send-email-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-19-peter.maydell@linaro.org
10
---
8
---
11
target/arm/cpu.h | 7 ++++++-
9
hw/intc/armv7m_nvic.c | 5 +++++
12
hw/intc/armv7m_nvic.c | 15 +++++++++++++--
10
1 file changed, 5 insertions(+)
13
target/arm/helper.c | 18 +++++++++---------
14
target/arm/machine.c | 3 ++-
15
4 files changed, 30 insertions(+), 13 deletions(-)
16
11
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
22
uint32_t basepri[2];
23
uint32_t control[2];
24
uint32_t ccr[2]; /* Configuration and Control */
25
- uint32_t cfsr; /* Configurable Fault Status */
26
+ uint32_t cfsr[2]; /* Configurable Fault Status */
27
uint32_t hfsr; /* HardFault Status */
28
uint32_t dfsr; /* Debug Fault Status Register */
29
uint32_t mmfar[2]; /* MemManage Fault Address */
30
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CFSR, NOCP, 16 + 3, 1)
31
FIELD(V7M_CFSR, UNALIGNED, 16 + 8, 1)
32
FIELD(V7M_CFSR, DIVBYZERO, 16 + 9, 1)
33
34
+/* V7M CFSR bit masks covering all of the subregister bits */
35
+FIELD(V7M_CFSR, MMFSR, 0, 8)
36
+FIELD(V7M_CFSR, BFSR, 8, 8)
37
+FIELD(V7M_CFSR, UFSR, 16, 16)
38
+
39
/* V7M HFSR bits */
40
FIELD(V7M_HFSR, VECTTBL, 1, 1)
41
FIELD(V7M_HFSR, FORCED, 30, 1)
42
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
43
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/intc/armv7m_nvic.c
14
--- a/hw/intc/armv7m_nvic.c
45
+++ b/hw/intc/armv7m_nvic.c
15
+++ b/hw/intc/armv7m_nvic.c
46
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
47
}
17
}
48
return val;
18
return val;
49
case 0xd28: /* Configurable Fault Status. */
19
}
50
- return cpu->env.v7m.cfsr;
20
+ case 0xcfc:
51
+ /* The BFSR bits [15:8] are shared between security states
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
52
+ * and we store them in the NS copy
22
+ goto bad_offset;
53
+ */
54
+ val = cpu->env.v7m.cfsr[attrs.secure];
55
+ val |= cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
56
+ return val;
57
case 0xd2c: /* Hard Fault Status. */
58
return cpu->env.v7m.hfsr;
59
case 0xd30: /* Debug Fault Status. */
60
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
61
nvic_irq_update(s);
62
break;
63
case 0xd28: /* Configurable Fault Status. */
64
- cpu->env.v7m.cfsr &= ~value; /* W1C */
65
+ cpu->env.v7m.cfsr[attrs.secure] &= ~value; /* W1C */
66
+ if (attrs.secure) {
67
+ /* The BFSR bits [15:8] are shared between security states
68
+ * and we store them in the NS copy.
69
+ */
70
+ cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK);
71
+ }
23
+ }
72
break;
24
+ return cpu->revidr;
73
case 0xd2c: /* Hard Fault Status. */
25
case 0xd00: /* CPUID Base. */
74
cpu->env.v7m.hfsr &= ~value; /* W1C */
26
return cpu->midr;
75
diff --git a/target/arm/helper.c b/target/arm/helper.c
27
case 0xd04: /* Interrupt Control State (ICSR) */
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/helper.c
78
+++ b/target/arm/helper.c
79
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
80
/* Bad exception return: instead of popping the exception
81
* stack, directly take a usage fault on the current stack.
82
*/
83
- env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
84
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
85
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
86
v7m_exception_taken(cpu, type | 0xf0000000);
87
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
88
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
89
if (return_to_handler != arm_v7m_is_handler_mode(env)) {
90
/* Take an INVPC UsageFault by pushing the stack again. */
91
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
92
- env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
93
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
94
v7m_push_stack(cpu);
95
v7m_exception_taken(cpu, type | 0xf0000000);
96
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
97
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
98
switch (cs->exception_index) {
99
case EXCP_UDEF:
100
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
101
- env->v7m.cfsr |= R_V7M_CFSR_UNDEFINSTR_MASK;
102
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNDEFINSTR_MASK;
103
break;
104
case EXCP_NOCP:
105
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
106
- env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
107
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_NOCP_MASK;
108
break;
109
case EXCP_INVSTATE:
110
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
111
- env->v7m.cfsr |= R_V7M_CFSR_INVSTATE_MASK;
112
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVSTATE_MASK;
113
break;
114
case EXCP_SWI:
115
/* The PC already points to the next instruction. */
116
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
117
case 0x8: /* External Abort */
118
switch (cs->exception_index) {
119
case EXCP_PREFETCH_ABORT:
120
- env->v7m.cfsr |= R_V7M_CFSR_PRECISERR_MASK;
121
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_PRECISERR_MASK;
122
qemu_log_mask(CPU_LOG_INT, "...with CFSR.PRECISERR\n");
123
break;
124
case EXCP_DATA_ABORT:
125
- env->v7m.cfsr |=
126
+ env->v7m.cfsr[M_REG_NS] |=
127
(R_V7M_CFSR_IBUSERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
128
env->v7m.bfar = env->exception.vaddress;
129
qemu_log_mask(CPU_LOG_INT,
130
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
131
*/
132
switch (cs->exception_index) {
133
case EXCP_PREFETCH_ABORT:
134
- env->v7m.cfsr |= R_V7M_CFSR_IACCVIOL_MASK;
135
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_IACCVIOL_MASK;
136
qemu_log_mask(CPU_LOG_INT, "...with CFSR.IACCVIOL\n");
137
break;
138
case EXCP_DATA_ABORT:
139
- env->v7m.cfsr |=
140
+ env->v7m.cfsr[env->v7m.secure] |=
141
(R_V7M_CFSR_DACCVIOL_MASK | R_V7M_CFSR_MMARVALID_MASK);
142
env->v7m.mmfar[env->v7m.secure] = env->exception.vaddress;
143
qemu_log_mask(CPU_LOG_INT,
144
diff --git a/target/arm/machine.c b/target/arm/machine.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/target/arm/machine.c
147
+++ b/target/arm/machine.c
148
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
149
VMSTATE_UINT32(env.v7m.basepri[M_REG_NS], ARMCPU),
150
VMSTATE_UINT32(env.v7m.control[M_REG_NS], ARMCPU),
151
VMSTATE_UINT32(env.v7m.ccr[M_REG_NS], ARMCPU),
152
- VMSTATE_UINT32(env.v7m.cfsr, ARMCPU),
153
+ VMSTATE_UINT32(env.v7m.cfsr[M_REG_NS], ARMCPU),
154
VMSTATE_UINT32(env.v7m.hfsr, ARMCPU),
155
VMSTATE_UINT32(env.v7m.dfsr, ARMCPU),
156
VMSTATE_UINT32(env.v7m.mmfar[M_REG_NS], ARMCPU),
157
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
158
VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_S], ARMCPU),
159
VMSTATE_UINT32(env.v7m.ccr[M_REG_S], ARMCPU),
160
VMSTATE_UINT32(env.v7m.mmfar[M_REG_S], ARMCPU),
161
+ VMSTATE_UINT32(env.v7m.cfsr[M_REG_S], ARMCPU),
162
VMSTATE_END_OF_LIST()
163
}
164
};
165
--
28
--
166
2.7.4
29
2.20.1
167
30
168
31
diff view generated by jsdifflib
1
Make the BASEPRI register banked if v8M security extensions are enabled.
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.
2
5
3
Note that we do not yet implement the functionality of the new
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
4
AIRCR.PRIS bit (which allows the effect of the NS copy of BASEPRI to
7
never cause CP10 accesses to fail.)
5
be restricted).
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.
6
12
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>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1503414539-28762-7-git-send-email-peter.maydell@linaro.org
15
Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
10
---
16
---
11
target/arm/cpu.h | 14 +++++++++++++-
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
12
hw/intc/armv7m_nvic.c | 4 ++--
18
1 file changed, 21 insertions(+), 1 deletion(-)
13
target/arm/helper.c | 10 ++++++----
14
target/arm/machine.c | 3 ++-
15
4 files changed, 23 insertions(+), 8 deletions(-)
16
19
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
22
--- a/target/arm/m_helper.c
20
+++ b/target/arm/cpu.h
23
+++ b/target/arm/m_helper.c
21
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
22
#define ARMV7M_EXCP_PENDSV 14
25
v7m_exception_taken(cpu, excret, true, false);
23
#define ARMV7M_EXCP_SYSTICK 15
26
return;
24
27
} else {
25
+/* For M profile, some registers are banked secure vs non-secure;
28
- /* Clear s0..s15 and FPSCR */
26
+ * these are represented as a 2-element array where the first element
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
27
+ * is the non-secure copy and the second is the secure copy.
30
+ /* v8.1M adds this NOCP check */
28
+ * When the CPU does not have implement the security extension then
31
+ bool nsacr_pass = exc_secure ||
29
+ * only the first element is used.
32
+ extract32(env->v7m.nsacr, 10, 1);
30
+ * This means that the copy for the current security state can be
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
31
+ * accessed via env->registerfield[env->v7m.secure] (whether the security
34
+ if (!nsacr_pass) {
32
+ * extension is implemented or not).
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
33
+ */
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
34
+#define M_REG_NS 0
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
35
+#define M_REG_S 1
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
36
+
39
+ v7m_exception_taken(cpu, excret, true, false);
37
/* ARM-specific interrupt pending bits. */
40
+ } else if (!cpacr_pass) {
38
#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
39
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_EXT_2
42
+ exc_secure);
40
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
41
struct {
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
42
uint32_t other_sp;
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
43
uint32_t vecbase;
46
+ v7m_exception_taken(cpu, excret, true, false);
44
- uint32_t basepri;
47
+ }
45
+ uint32_t basepri[2];
48
+ }
46
uint32_t control;
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
47
uint32_t ccr; /* Configuration and Control */
50
int i;
48
uint32_t cfsr; /* Configurable Fault Status */
51
49
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
52
for (i = 0; i < 16; i += 2) {
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/intc/armv7m_nvic.c
52
+++ b/hw/intc/armv7m_nvic.c
53
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
54
running = -1;
55
} else if (env->v7m.primask) {
56
running = 0;
57
- } else if (env->v7m.basepri > 0) {
58
- running = env->v7m.basepri & nvic_gprio_mask(s);
59
+ } else if (env->v7m.basepri[env->v7m.secure] > 0) {
60
+ running = env->v7m.basepri[env->v7m.secure] & nvic_gprio_mask(s);
61
} else {
62
running = NVIC_NOEXC_PRIO; /* lower than any possible priority */
63
}
64
diff --git a/target/arm/helper.c b/target/arm/helper.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/helper.c
67
+++ b/target/arm/helper.c
68
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
69
return env->v7m.primask;
70
case 17: /* BASEPRI */
71
case 18: /* BASEPRI_MAX */
72
- return env->v7m.basepri;
73
+ return env->v7m.basepri[env->v7m.secure];
74
case 19: /* FAULTMASK */
75
return env->v7m.faultmask;
76
default:
77
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
78
env->v7m.primask = val & 1;
79
break;
80
case 17: /* BASEPRI */
81
- env->v7m.basepri = val & 0xff;
82
+ env->v7m.basepri[env->v7m.secure] = val & 0xff;
83
break;
84
case 18: /* BASEPRI_MAX */
85
val &= 0xff;
86
- if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
87
- env->v7m.basepri = val;
88
+ if (val != 0 && (val < env->v7m.basepri[env->v7m.secure]
89
+ || env->v7m.basepri[env->v7m.secure] == 0)) {
90
+ env->v7m.basepri[env->v7m.secure] = val;
91
+ }
92
break;
93
case 19: /* FAULTMASK */
94
env->v7m.faultmask = val & 1;
95
diff --git a/target/arm/machine.c b/target/arm/machine.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/target/arm/machine.c
98
+++ b/target/arm/machine.c
99
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
100
.needed = m_needed,
101
.fields = (VMStateField[]) {
102
VMSTATE_UINT32(env.v7m.vecbase, ARMCPU),
103
- VMSTATE_UINT32(env.v7m.basepri, ARMCPU),
104
+ VMSTATE_UINT32(env.v7m.basepri[M_REG_NS], ARMCPU),
105
VMSTATE_UINT32(env.v7m.control, ARMCPU),
106
VMSTATE_UINT32(env.v7m.ccr, ARMCPU),
107
VMSTATE_UINT32(env.v7m.cfsr, ARMCPU),
108
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
109
.needed = m_security_needed,
110
.fields = (VMStateField[]) {
111
VMSTATE_UINT32(env.v7m.secure, ARMCPU),
112
+ VMSTATE_UINT32(env.v7m.basepri[M_REG_S], ARMCPU),
113
VMSTATE_END_OF_LIST()
114
}
115
};
116
--
53
--
117
2.7.4
54
2.20.1
118
55
119
56
diff view generated by jsdifflib
1
Define a new MachineClass field ignore_memory_transaction_failures.
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
2
If this is flag is true then the CPU will ignore memory transaction
2
The only difference is that:
3
failures which should cause the CPU to take an exception due to an
3
* the old T1 encodings UNDEF if the implementation implements 32
4
access to an unassigned physical address; the transaction will
4
Dregs (this is currently architecturally impossible for M-profile)
5
instead return zero (for a read) or be ignored (for a write). This
5
* the new T2 encodings have the implementation-defined option to
6
should be set only by legacy board models which rely on the old
6
read from memory (discarding the data) or write UNKNOWN values to
7
RAZ/WI behaviour for handling devices that QEMU does not yet model.
7
memory for the stack slots that would be D16-D31
8
New board models should instead use "unimplemented-device" for all
9
memory ranges where the guest will attempt to probe for a device that
10
QEMU doesn't implement and a stub device is required.
11
8
12
We need this for ARM boards, where we're about to implement support for
9
We choose not to make those accesses, so for us the two
13
generating external aborts on memory transaction failures. Too many
10
instructions behave identically assuming they don't UNDEF.
14
of our legacy board models rely on the RAZ/WI behaviour and we
15
would break currently working guests when their "probe for device"
16
code provoked an external abort rather than a RAZ.
17
11
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
14
Message-id: 20201119215617.29887-21-peter.maydell@linaro.org
21
Message-id: 1504626814-23124-2-git-send-email-peter.maydell@linaro.org
22
---
15
---
23
include/hw/boards.h | 11 +++++++++++
16
target/arm/m-nocp.decode | 2 +-
24
include/qom/cpu.h | 7 ++++++-
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
25
qom/cpu.c | 16 ++++++++++++++++
18
2 files changed, 26 insertions(+), 1 deletion(-)
26
3 files changed, 33 insertions(+), 1 deletion(-)
27
19
28
diff --git a/include/hw/boards.h b/include/hw/boards.h
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
29
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/boards.h
22
--- a/target/arm/m-nocp.decode
31
+++ b/include/hw/boards.h
23
+++ b/target/arm/m-nocp.decode
32
@@ -XXX,XX +XXX,XX @@ typedef struct {
24
@@ -XXX,XX +XXX,XX @@
33
* size than the target architecture's minimum. (Attempting to create
25
34
* such a CPU will fail.) Note that changing this is a migration
26
{
35
* compatibility break for the machine.
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
36
+ * @ignore_memory_transaction_failures:
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
37
+ * If this is flag is true then the CPU will ignore memory transaction
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
38
+ * failures which should cause the CPU to take an exception due to an
30
# VSCCLRM (new in v8.1M) is similar:
39
+ * access to an unassigned physical address; the transaction will instead
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
40
+ * return zero (for a read) or be ignored (for a write). This should be
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
41
+ * set only by legacy board models which rely on the old RAZ/WI behaviour
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
42
+ * for handling devices that QEMU does not yet model. New board models
43
+ * should instead use "unimplemented-device" for all memory ranges where
44
+ * the guest will attempt to probe for a device that QEMU doesn't
45
+ * implement and a stub device is required.
46
*/
47
struct MachineClass {
48
/*< private >*/
49
@@ -XXX,XX +XXX,XX @@ struct MachineClass {
50
bool rom_file_has_mr;
51
int minimum_page_bits;
52
bool has_hotpluggable_cpus;
53
+ bool ignore_memory_transaction_failures;
54
int numa_mem_align_shift;
55
void (*numa_auto_assign_ram)(MachineClass *mc, NodeInfo *nodes,
56
int nb_nodes, ram_addr_t size);
57
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
58
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
59
--- a/include/qom/cpu.h
35
--- a/target/arm/translate-vfp.c.inc
60
+++ b/include/qom/cpu.h
36
+++ b/target/arm/translate-vfp.c.inc
61
@@ -XXX,XX +XXX,XX @@ struct qemu_work_item;
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
62
* @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
63
* to @trace_dstate).
39
return false;
64
* @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
40
}
65
+ * @ignore_memory_transaction_failures: Cached copy of the MachineState
66
+ * flag of the same name: allows the board to suppress calling of the
67
+ * CPU do_transaction_failed hook function.
68
*
69
* State of one CPU core or thread.
70
*/
71
@@ -XXX,XX +XXX,XX @@ struct CPUState {
72
*/
73
bool throttle_thread_scheduled;
74
75
+ bool ignore_memory_transaction_failures;
76
+
41
+
77
/* Note that this is accessed at the start of every TB via a negative
42
+ if (a->op) {
78
offset from AREG0. Leave this field at the end so as to make the
43
+ /*
79
(absolute value) offset as small as possible. This reduces code
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
80
@@ -XXX,XX +XXX,XX @@ static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
45
+ * to take the IMPDEF option to make memory accesses to the stack
81
{
46
+ * slots that correspond to the D16-D31 registers (discarding
82
CPUClass *cc = CPU_GET_CLASS(cpu);
47
+ * read data and writing UNKNOWN values), so for us the T2
83
48
+ * encoding behaves identically to the T1 encoding.
84
- if (cc->do_transaction_failed) {
49
+ */
85
+ if (!cpu->ignore_memory_transaction_failures && cc->do_transaction_failed) {
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
86
cc->do_transaction_failed(cpu, physaddr, addr, size, access_type,
51
+ return false;
87
mmu_idx, attrs, response, retaddr);
52
+ }
88
}
53
+ } else {
89
diff --git a/qom/cpu.c b/qom/cpu.c
54
+ /*
90
index XXXXXXX..XXXXXXX 100644
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
91
--- a/qom/cpu.c
56
+ * This is currently architecturally impossible, but we add the
92
+++ b/qom/cpu.c
57
+ * check to stay in line with the pseudocode. Note that we must
93
@@ -XXX,XX +XXX,XX @@
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
94
#include "exec/cpu-common.h"
59
+ */
95
#include "qemu/error-report.h"
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
96
#include "sysemu/sysemu.h"
61
+ unallocated_encoding(s);
97
+#include "hw/boards.h"
62
+ return true;
98
#include "hw/qdev-properties.h"
99
#include "trace-root.h"
100
101
@@ -XXX,XX +XXX,XX @@ static void cpu_common_parse_features(const char *typename, char *features,
102
static void cpu_common_realizefn(DeviceState *dev, Error **errp)
103
{
104
CPUState *cpu = CPU(dev);
105
+ Object *machine = qdev_get_machine();
106
+
107
+ /* qdev_get_machine() can return something that's not TYPE_MACHINE
108
+ * if this is one of the user-only emulators; in that case there's
109
+ * no need to check the ignore_memory_transaction_failures board flag.
110
+ */
111
+ if (object_dynamic_cast(machine, TYPE_MACHINE)) {
112
+ ObjectClass *oc = object_get_class(machine);
113
+ MachineClass *mc = MACHINE_CLASS(oc);
114
+
115
+ if (mc) {
116
+ cpu->ignore_memory_transaction_failures =
117
+ mc->ignore_memory_transaction_failures;
118
+ }
63
+ }
119
+ }
64
+ }
120
65
+
121
if (dev->hotplugged) {
66
/*
122
cpu_synchronize_post_init(cpu);
67
* If not secure, UNDEF. We must emit code for this
68
* rather than returning false so that this takes
123
--
69
--
124
2.7.4
70
2.20.1
125
71
126
72
diff view generated by jsdifflib
1
Make the MPU registers MPU_MAIR0 and MPU_MAIR1 banked if v8M security
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
extensions are enabled.
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.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 1503414539-28762-13-git-send-email-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-23-peter.maydell@linaro.org
7
---
9
---
8
target/arm/cpu.h | 4 ++--
10
target/arm/cpu.h | 2 ++
9
hw/intc/armv7m_nvic.c | 8 ++++----
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
10
target/arm/cpu.c | 6 ++++--
12
2 files changed, 20 insertions(+), 8 deletions(-)
11
target/arm/machine.c | 6 ++++--
12
4 files changed, 14 insertions(+), 10 deletions(-)
13
13
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
18
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
19
*/
19
FIELD(V7M_CCR, DC, 16, 1)
20
uint32_t *rbar;
20
FIELD(V7M_CCR, IC, 17, 1)
21
uint32_t *rlar;
21
FIELD(V7M_CCR, BP, 18, 1)
22
- uint32_t mair0;
22
+FIELD(V7M_CCR, LOB, 19, 1)
23
- uint32_t mair1;
23
+FIELD(V7M_CCR, TRD, 20, 1)
24
+ uint32_t mair0[2];
24
25
+ uint32_t mair1[2];
25
/* V7M SCR bits */
26
} pmsav8;
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
27
28
void *nvic;
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
30
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/armv7m_nvic.c
29
--- a/hw/intc/armv7m_nvic.c
32
+++ b/hw/intc/armv7m_nvic.c
30
+++ b/hw/intc/armv7m_nvic.c
33
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
34
if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
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)) {
35
goto bad_offset;
51
goto bad_offset;
36
}
52
}
37
- return cpu->env.pmsav8.mair0;
53
38
+ return cpu->env.pmsav8.mair0[attrs.secure];
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
39
case 0xdc4: /* MPU_MAIR1 */
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
40
if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
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)) {
41
goto bad_offset;
82
goto bad_offset;
42
}
43
- return cpu->env.pmsav8.mair1;
44
+ return cpu->env.pmsav8.mair1[attrs.secure];
45
default:
46
bad_offset:
47
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
48
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
49
}
50
if (cpu->pmsav7_dregion) {
51
/* Register is RES0 if no MPU regions are implemented */
52
- cpu->env.pmsav8.mair0 = value;
53
+ cpu->env.pmsav8.mair0[attrs.secure] = value;
54
}
55
/* We don't need to do anything else because memory attributes
56
* only affect cacheability, and we don't implement caching.
57
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
58
}
59
if (cpu->pmsav7_dregion) {
60
/* Register is RES0 if no MPU regions are implemented */
61
- cpu->env.pmsav8.mair1 = value;
62
+ cpu->env.pmsav8.mair1[attrs.secure] = value;
63
}
64
/* We don't need to do anything else because memory attributes
65
* only affect cacheability, and we don't implement caching.
66
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/cpu.c
69
+++ b/target/arm/cpu.c
70
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
71
}
72
}
73
env->pmsav7.rnr = 0;
74
- env->pmsav8.mair0 = 0;
75
- env->pmsav8.mair1 = 0;
76
+ env->pmsav8.mair0[M_REG_NS] = 0;
77
+ env->pmsav8.mair0[M_REG_S] = 0;
78
+ env->pmsav8.mair1[M_REG_NS] = 0;
79
+ env->pmsav8.mair1[M_REG_S] = 0;
80
}
81
82
set_flush_to_zero(1, &env->vfp.standard_fp_status);
83
diff --git a/target/arm/machine.c b/target/arm/machine.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/machine.c
86
+++ b/target/arm/machine.c
87
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmsav8 = {
88
vmstate_info_uint32, uint32_t),
89
VMSTATE_VARRAY_UINT32(env.pmsav8.rlar, ARMCPU, pmsav7_dregion, 0,
90
vmstate_info_uint32, uint32_t),
91
- VMSTATE_UINT32(env.pmsav8.mair0, ARMCPU),
92
- VMSTATE_UINT32(env.pmsav8.mair1, ARMCPU),
93
+ VMSTATE_UINT32(env.pmsav8.mair0[M_REG_NS], ARMCPU),
94
+ VMSTATE_UINT32(env.pmsav8.mair1[M_REG_NS], ARMCPU),
95
VMSTATE_END_OF_LIST()
96
}
97
};
98
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
99
VMSTATE_UINT32(env.v7m.faultmask[M_REG_S], ARMCPU),
100
VMSTATE_UINT32(env.v7m.control[M_REG_S], ARMCPU),
101
VMSTATE_UINT32(env.v7m.vecbase[M_REG_S], ARMCPU),
102
+ VMSTATE_UINT32(env.pmsav8.mair0[M_REG_S], ARMCPU),
103
+ VMSTATE_UINT32(env.pmsav8.mair1[M_REG_S], ARMCPU),
104
VMSTATE_END_OF_LIST()
105
}
106
};
107
--
83
--
108
2.7.4
84
2.20.1
109
85
110
86
diff view generated by jsdifflib
1
Implement the behavioural side of the new PMSAv8 specification.
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.
2
4
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 1503414539-28762-3-git-send-email-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
6
---
8
---
7
target/arm/helper.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++-
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
8
1 file changed, 110 insertions(+), 1 deletion(-)
10
1 file changed, 86 insertions(+)
9
11
10
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
11
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/helper.c
14
--- a/target/arm/m_helper.c
13
+++ b/target/arm/helper.c
15
+++ b/target/arm/m_helper.c
14
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
15
return !(*prot & (1 << access_type));
17
return true;
16
}
18
}
17
19
18
+static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
19
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
21
+ uint32_t addr, uint32_t *spdata)
20
+ hwaddr *phys_ptr, int *prot, uint32_t *fsr)
21
+{
22
+{
22
+ ARMCPU *cpu = arm_env_get_cpu(env);
23
+ /*
23
+ bool is_user = regime_is_user(env, mmu_idx);
24
+ * Read a word of data from the stack for the SG instruction,
24
+ int n;
25
+ * writing the value into *spdata. If the load succeeds, return
25
+ int matchregion = -1;
26
+ * true; otherwise pend an appropriate exception and return false.
26
+ bool hit = 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;
27
+
41
+
28
+ *phys_ptr = address;
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
29
+ *prot = 0;
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
+ }
30
+
73
+
31
+ /* Unlike the ARM ARM pseudocode, we don't need to check whether this
74
+ *spdata = value;
32
+ * was an exception vector read from the vector table (which is always
75
+ return true;
33
+ * done using the default system address map), because those accesses
76
+}
34
+ * are done in arm_v7m_load_vector(), which always does a direct
35
+ * read using address_space_ldl(), rather than going via this function.
36
+ */
37
+ if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */
38
+ hit = true;
39
+ } else if (m_is_ppb_region(env, address)) {
40
+ hit = true;
41
+ } else if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
42
+ hit = true;
43
+ } else {
44
+ for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
45
+ /* region search */
46
+ /* Note that the base address is bits [31:5] from the register
47
+ * with bits [4:0] all zeroes, but the limit address is bits
48
+ * [31:5] from the register with bits [4:0] all ones.
49
+ */
50
+ uint32_t base = env->pmsav8.rbar[n] & ~0x1f;
51
+ uint32_t limit = env->pmsav8.rlar[n] | 0x1f;
52
+
77
+
53
+ if (!(env->pmsav8.rlar[n] & 0x1)) {
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
54
+ /* Region disabled */
79
{
55
+ continue;
80
/*
56
+ }
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]);
57
+
85
+
58
+ if (address < base || address > limit) {
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
59
+ continue;
87
+ !arm_v7m_is_handler_mode(env)) {
60
+ }
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;
61
+
94
+
62
+ if (hit) {
95
+ /*
63
+ /* Multiple regions match -- always a failure (unlike
96
+ * We know we are currently NS, so the S stack pointers must be
64
+ * PMSAv7 where highest-numbered-region wins)
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
65
+ */
98
+ */
66
+ *fsr = 0x00d; /* permission fault */
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
67
+ return true;
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
68
+ }
101
+ /* Stack access failed and an exception has been pended */
102
+ return false;
103
+ }
69
+
104
+
70
+ matchregion = n;
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
71
+ hit = true;
106
+ if (((spdata & ~1) == 0xfefa125a) ||
72
+
107
+ !(env->v7m.control[M_REG_S] & 1)) {
73
+ if (base & ~TARGET_PAGE_MASK) {
108
+ goto gen_invep;
74
+ qemu_log_mask(LOG_UNIMP,
75
+ "MPU_RBAR[%d]: No support for MPU region base"
76
+ "address of 0x%" PRIx32 ". Minimum alignment is "
77
+ "%d\n",
78
+ n, base, TARGET_PAGE_BITS);
79
+ continue;
80
+ }
81
+ if ((limit + 1) & ~TARGET_PAGE_MASK) {
82
+ qemu_log_mask(LOG_UNIMP,
83
+ "MPU_RBAR[%d]: No support for MPU region limit"
84
+ "address of 0x%" PRIx32 ". Minimum alignment is "
85
+ "%d\n",
86
+ n, limit, TARGET_PAGE_BITS);
87
+ continue;
88
+ }
109
+ }
89
+ }
110
+ }
90
+ }
111
+ }
91
+
112
+
92
+ if (!hit) {
113
env->regs[14] &= ~1;
93
+ /* background fault */
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
94
+ *fsr = 0;
115
switch_v7m_security_state(env, true);
95
+ return true;
96
+ }
97
+
98
+ if (matchregion == -1) {
99
+ /* hit using the background region */
100
+ get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
101
+ } else {
102
+ uint32_t ap = extract32(env->pmsav8.rbar[matchregion], 1, 2);
103
+ uint32_t xn = extract32(env->pmsav8.rbar[matchregion], 0, 1);
104
+
105
+ if (m_is_system_region(env, address)) {
106
+ /* System space is always execute never */
107
+ xn = 1;
108
+ }
109
+
110
+ *prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
111
+ if (*prot && !xn) {
112
+ *prot |= PAGE_EXEC;
113
+ }
114
+ /* We don't need to look the attribute up in the MAIR0/MAIR1
115
+ * registers because that only tells us about cacheability.
116
+ */
117
+ }
118
+
119
+ *fsr = 0x00d; /* Permission fault */
120
+ return !(*prot & (1 << access_type));
121
+}
122
+
123
static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
124
MMUAccessType access_type, ARMMMUIdx mmu_idx,
125
hwaddr *phys_ptr, int *prot, uint32_t *fsr)
126
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
127
bool ret;
128
*page_size = TARGET_PAGE_SIZE;
129
130
- if (arm_feature(env, ARM_FEATURE_V7)) {
131
+ if (arm_feature(env, ARM_FEATURE_V8)) {
132
+ /* PMSAv8 */
133
+ ret = get_phys_addr_pmsav8(env, address, access_type, mmu_idx,
134
+ phys_ptr, prot, fsr);
135
+ } else if (arm_feature(env, ARM_FEATURE_V7)) {
136
/* PMSAv7 */
137
ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
138
phys_ptr, prot, fsr);
139
--
116
--
140
2.7.4
117
2.20.1
141
118
142
119
diff view generated by jsdifflib
1
Make the MPU_RNR register banked if v8M security extensions are
1
In commit 077d7449100d824a4 we added code to handle the v8M
2
enabled.
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
13
In the case for "configurable exception targeting the opposite
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
18
Rearrange the code so that we first identify the illegal return
19
cases, then see if we really need to deactivate NMI or HardFault
20
instead, and finally do the deactivation.
3
21
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 1503414539-28762-15-git-send-email-peter.maydell@linaro.org
24
Message-id: 20201119215617.29887-25-peter.maydell@linaro.org
7
---
25
---
8
target/arm/cpu.h | 2 +-
26
hw/intc/armv7m_nvic.c | 59 +++++++++++++++++++++++--------------------
9
hw/intc/armv7m_nvic.c | 18 +++++++++---------
27
1 file changed, 32 insertions(+), 27 deletions(-)
10
target/arm/cpu.c | 3 ++-
11
target/arm/helper.c | 6 +++---
12
target/arm/machine.c | 13 +++++++++++--
13
5 files changed, 26 insertions(+), 16 deletions(-)
14
28
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 @@ typedef struct CPUARMState {
20
uint32_t *drbar;
21
uint32_t *drsr;
22
uint32_t *dracr;
23
- uint32_t rnr;
24
+ uint32_t rnr[2];
25
} pmsav7;
26
27
/* PMSAv8 MPU */
28
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
29
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/intc/armv7m_nvic.c
31
--- a/hw/intc/armv7m_nvic.c
31
+++ b/hw/intc/armv7m_nvic.c
32
+++ b/hw/intc/armv7m_nvic.c
32
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
33
case 0xd94: /* MPU_CTRL */
34
{
34
return cpu->env.v7m.mpu_ctrl;
35
NVICState *s = (NVICState *)opaque;
35
case 0xd98: /* MPU_RNR */
36
VecInfo *vec = NULL;
36
- return cpu->env.pmsav7.rnr;
37
- int ret;
37
+ return cpu->env.pmsav7.rnr[attrs.secure];
38
+ int ret = 0;
38
case 0xd9c: /* MPU_RBAR */
39
39
case 0xda4: /* MPU_RBAR_A1 */
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
40
case 0xdac: /* MPU_RBAR_A2 */
41
41
case 0xdb4: /* MPU_RBAR_A3 */
42
+ trace_nvic_complete_irq(irq, secure);
42
{
43
+
43
- int region = cpu->env.pmsav7.rnr;
44
+ if (secure && exc_is_banked(irq)) {
44
+ int region = cpu->env.pmsav7.rnr[attrs.secure];
45
+ vec = &s->sec_vectors[irq];
45
46
+ } else {
46
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
47
+ vec = &s->vectors[irq];
47
/* PMSAv8M handling of the aliases is different from v7M:
48
+ }
48
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
49
+
49
case 0xdb0: /* MPU_RASR_A2 (v7M), MPU_RLAR_A2 (v8M) */
50
+ /*
50
case 0xdb8: /* MPU_RASR_A3 (v7M), MPU_RLAR_A3 (v8M) */
51
+ * Identify illegal exception return cases. We can't immediately
51
{
52
+ * return at this point because we still need to deactivate
52
- int region = cpu->env.pmsav7.rnr;
53
+ * (either this exception or NMI/HardFault) first.
53
+ int region = cpu->env.pmsav7.rnr[attrs.secure];
54
+ */
54
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
55
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
56
+ /*
56
/* PMSAv8M handling of the aliases is different from v7M:
57
+ * Return from a configurable exception targeting the opposite
57
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
58
+ * security state from the one we're trying to complete it for.
58
PRIu32 "/%" PRIu32 "\n",
59
+ * Clear vec because it's not really the VecInfo for this
59
value, cpu->pmsav7_dregion);
60
+ * (irq, secstate) so we mustn't deactivate it.
60
} else {
61
+ */
61
- cpu->env.pmsav7.rnr = value;
62
+ ret = -1;
62
+ cpu->env.pmsav7.rnr[attrs.secure] = value;
63
+ vec = NULL;
63
}
64
+ } else if (!vec->active) {
64
break;
65
+ /* Return from an inactive interrupt */
65
case 0xd9c: /* MPU_RBAR */
66
+ ret = -1;
66
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
67
+ } else {
67
*/
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
68
int aliasno = (offset - 0xd9c) / 8; /* 0..3 */
69
+ ret = nvic_rettobase(s);
69
70
+ }
70
- region = cpu->env.pmsav7.rnr;
71
+
71
+ region = cpu->env.pmsav7.rnr[attrs.secure];
72
/*
72
if (aliasno) {
73
* For negative priorities, v8M will forcibly deactivate the appropriate
73
region = deposit32(region, 0, 2, aliasno);
74
* NMI or HardFault regardless of what interrupt we're being asked to
74
}
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
76
region, cpu->pmsav7_dregion);
77
return;
78
}
79
- cpu->env.pmsav7.rnr = region;
80
+ cpu->env.pmsav7.rnr[attrs.secure] = region;
81
} else {
82
- region = cpu->env.pmsav7.rnr;
83
+ region = cpu->env.pmsav7.rnr[attrs.secure];
84
}
85
86
if (region >= cpu->pmsav7_dregion) {
87
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
88
case 0xdb0: /* MPU_RASR_A2 (v7M), MPU_RLAR_A2 (v8M) */
89
case 0xdb8: /* MPU_RASR_A3 (v7M), MPU_RLAR_A3 (v8M) */
90
{
91
- int region = cpu->env.pmsav7.rnr;
92
+ int region = cpu->env.pmsav7.rnr[attrs.secure];
93
94
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
95
/* PMSAv8M handling of the aliases is different from v7M:
96
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
97
*/
98
int aliasno = (offset - 0xd9c) / 8; /* 0..3 */
99
100
- region = cpu->env.pmsav7.rnr;
101
+ region = cpu->env.pmsav7.rnr[attrs.secure];
102
if (aliasno) {
103
region = deposit32(region, 0, 2, aliasno);
104
}
105
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/cpu.c
108
+++ b/target/arm/cpu.c
109
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
110
sizeof(*env->pmsav7.dracr) * cpu->pmsav7_dregion);
111
}
112
}
113
- env->pmsav7.rnr = 0;
114
+ env->pmsav7.rnr[M_REG_NS] = 0;
115
+ env->pmsav7.rnr[M_REG_S] = 0;
116
env->pmsav8.mair0[M_REG_NS] = 0;
117
env->pmsav8.mair0[M_REG_S] = 0;
118
env->pmsav8.mair1[M_REG_NS] = 0;
119
diff --git a/target/arm/helper.c b/target/arm/helper.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/target/arm/helper.c
122
+++ b/target/arm/helper.c
123
@@ -XXX,XX +XXX,XX @@ static uint64_t pmsav7_read(CPUARMState *env, const ARMCPRegInfo *ri)
124
return 0;
125
}
76
}
126
77
127
- u32p += env->pmsav7.rnr;
78
if (!vec) {
128
+ u32p += env->pmsav7.rnr[M_REG_NS];
79
- if (secure && exc_is_banked(irq)) {
129
return *u32p;
80
- vec = &s->sec_vectors[irq];
130
}
81
- } else {
131
82
- vec = &s->vectors[irq];
132
@@ -XXX,XX +XXX,XX @@ static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri,
83
- }
133
return;
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;
134
}
106
}
135
107
136
- u32p += env->pmsav7.rnr;
108
vec->active = 0;
137
+ u32p += env->pmsav7.rnr[M_REG_NS];
138
tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
139
*u32p = value;
140
}
141
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
142
.resetfn = arm_cp_reset_ignore },
143
{ .name = "RGNR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 2, .opc2 = 0,
144
.access = PL1_RW,
145
- .fieldoffset = offsetof(CPUARMState, pmsav7.rnr),
146
+ .fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]),
147
.writefn = pmsav7_rgnr_write,
148
.resetfn = arm_cp_reset_ignore },
149
REGINFO_SENTINEL
150
diff --git a/target/arm/machine.c b/target/arm/machine.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/target/arm/machine.c
153
+++ b/target/arm/machine.c
154
@@ -XXX,XX +XXX,XX @@ static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id)
155
{
156
ARMCPU *cpu = opaque;
157
158
- return cpu->env.pmsav7.rnr < cpu->pmsav7_dregion;
159
+ return cpu->env.pmsav7.rnr[M_REG_NS] < cpu->pmsav7_dregion;
160
}
161
162
static const VMStateDescription vmstate_pmsav7 = {
163
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmsav7_rnr = {
164
.minimum_version_id = 1,
165
.needed = pmsav7_rnr_needed,
166
.fields = (VMStateField[]) {
167
- VMSTATE_UINT32(env.pmsav7.rnr, ARMCPU),
168
+ VMSTATE_UINT32(env.pmsav7.rnr[M_REG_NS], ARMCPU),
169
VMSTATE_END_OF_LIST()
170
}
171
};
172
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmsav8 = {
173
}
174
};
175
176
+static bool s_rnr_vmstate_validate(void *opaque, int version_id)
177
+{
178
+ ARMCPU *cpu = opaque;
179
+
180
+ return cpu->env.pmsav7.rnr[M_REG_S] < cpu->pmsav7_dregion;
181
+}
182
+
183
static bool m_security_needed(void *opaque)
184
{
185
ARMCPU *cpu = opaque;
186
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
187
0, vmstate_info_uint32, uint32_t),
188
VMSTATE_VARRAY_UINT32(env.pmsav8.rlar[M_REG_S], ARMCPU, pmsav7_dregion,
189
0, vmstate_info_uint32, uint32_t),
190
+ VMSTATE_UINT32(env.pmsav7.rnr[M_REG_S], ARMCPU),
191
+ VMSTATE_VALIDATE("secure MPU_RNR is valid", s_rnr_vmstate_validate),
192
VMSTATE_END_OF_LIST()
193
}
194
};
195
--
109
--
196
2.7.4
110
2.20.1
197
111
198
112
diff view generated by jsdifflib
1
As part of ARMv8M, we need to add support for the PMSAv8 MPU
1
For v8.1M the architecture mandates that CPUs must provide at
2
architecture.
2
least the "minimal RAS implementation" from the Reliability,
3
3
Availability and Serviceability extension. This consists of:
4
PMSAv8 differs from PMSAv7 both in register/data layout (for instance
4
* an ESB instruction which is a NOP
5
using base and limit registers rather than base and size) and also in
5
-- since it is in the HINT space we need only add a comment
6
behaviour (for example it does not have subregions); rather than
6
* an RFSR register which will RAZ/WI
7
trying to wedge it into the existing PMSAv7 code and data structures,
7
* a RAZ/WI AIRCR.IESB bit
8
we define separate ones.
8
-- the code which handles writes to AIRCR does not allow setting
9
9
of RES0 bits, so we already treat this as RAZ/WI; add a comment
10
This commit adds the data structures which hold the state for a
10
noting that this is deliberate
11
PMSAv8 MPU and the register interface to it. The implementation of
11
* minimal implementation of the RAS register block at 0xe0005000
12
the MPU behaviour will be added in a subsequent commit.
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
13
15
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>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 1503414539-28762-2-git-send-email-peter.maydell@linaro.org
18
Message-id: 20201119215617.29887-26-peter.maydell@linaro.org
17
---
19
---
18
target/arm/cpu.h | 13 ++++++
20
target/arm/cpu.h | 14 ++++++++++++++
19
hw/intc/armv7m_nvic.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++----
21
target/arm/t32.decode | 4 ++++
20
target/arm/cpu.c | 36 ++++++++++-----
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
21
target/arm/machine.c | 29 +++++++++++-
23
3 files changed, 31 insertions(+)
22
4 files changed, 180 insertions(+), 20 deletions(-)
23
24
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
27
--- a/target/arm/cpu.h
27
+++ b/target/arm/cpu.h
28
+++ b/target/arm/cpu.h
28
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
29
uint32_t rnr;
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
30
} pmsav7;
31
FIELD(ID_MMFR4, EVT, 28, 4)
31
32
32
+ /* PMSAv8 MPU */
33
+FIELD(ID_PFR0, STATE0, 0, 4)
33
+ struct {
34
+FIELD(ID_PFR0, STATE1, 4, 4)
34
+ /* The PMSAv8 implementation also shares some PMSAv7 config
35
+FIELD(ID_PFR0, STATE2, 8, 4)
35
+ * and state:
36
+FIELD(ID_PFR0, STATE3, 12, 4)
36
+ * pmsav7.rnr (region number register)
37
+FIELD(ID_PFR0, CSV2, 16, 4)
37
+ * pmsav7_dregion (number of configured regions)
38
+FIELD(ID_PFR0, AMU, 20, 4)
38
+ */
39
+FIELD(ID_PFR0, DIT, 24, 4)
39
+ uint32_t *rbar;
40
+FIELD(ID_PFR0, RAS, 28, 4)
40
+ uint32_t *rlar;
41
+ uint32_t mair0;
42
+ uint32_t mair1;
43
+ } pmsav8;
44
+
41
+
45
void *nvic;
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
46
const struct arm_boot_info *boot_info;
43
FIELD(ID_PFR1, SECURITY, 4, 4)
47
/* Store GICv3CPUState to access from this struct */
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
47
}
48
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
50
+{
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
52
+}
53
+
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
55
{
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/t32.decode
60
+++ b/target/arm/t32.decode
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
64
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
66
+ # default behaviour since it is in the hint space.
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
68
+
69
# The canonical nop ends in 0000 0000, but the whole rest
70
# of the space is "reserved hint, behaves as nop".
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
48
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
49
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/intc/armv7m_nvic.c
74
--- a/hw/intc/armv7m_nvic.c
51
+++ b/hw/intc/armv7m_nvic.c
75
+++ b/hw/intc/armv7m_nvic.c
52
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
53
{
54
int region = cpu->env.pmsav7.rnr;
55
56
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
57
+ /* PMSAv8M handling of the aliases is different from v7M:
58
+ * aliases A1, A2, A3 override the low two bits of the region
59
+ * number in MPU_RNR, and there is no 'region' field in the
60
+ * RBAR register.
61
+ */
62
+ int aliasno = (offset - 0xd9c) / 8; /* 0..3 */
63
+ if (aliasno) {
64
+ region = deposit32(region, 0, 2, aliasno);
65
+ }
66
+ if (region >= cpu->pmsav7_dregion) {
67
+ return 0;
68
+ }
69
+ return cpu->env.pmsav8.rbar[region];
70
+ }
71
+
72
if (region >= cpu->pmsav7_dregion) {
73
return 0;
77
return 0;
74
}
78
}
75
return (cpu->env.pmsav7.drbar[region] & 0x1f) | (region & 0xf);
79
return cpu->env.v7m.sfar;
76
}
80
+ case 0xf04: /* RFSR */
77
- case 0xda0: /* MPU_RASR */
81
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
78
- case 0xda8: /* MPU_RASR_A1 */
79
- case 0xdb0: /* MPU_RASR_A2 */
80
- case 0xdb8: /* MPU_RASR_A3 */
81
+ case 0xda0: /* MPU_RASR (v7M), MPU_RLAR (v8M) */
82
+ case 0xda8: /* MPU_RASR_A1 (v7M), MPU_RLAR_A1 (v8M) */
83
+ case 0xdb0: /* MPU_RASR_A2 (v7M), MPU_RLAR_A2 (v8M) */
84
+ case 0xdb8: /* MPU_RASR_A3 (v7M), MPU_RLAR_A3 (v8M) */
85
{
86
int region = cpu->env.pmsav7.rnr;
87
88
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
89
+ /* PMSAv8M handling of the aliases is different from v7M:
90
+ * aliases A1, A2, A3 override the low two bits of the region
91
+ * number in MPU_RNR.
92
+ */
93
+ int aliasno = (offset - 0xda0) / 8; /* 0..3 */
94
+ if (aliasno) {
95
+ region = deposit32(region, 0, 2, aliasno);
96
+ }
97
+ if (region >= cpu->pmsav7_dregion) {
98
+ return 0;
99
+ }
100
+ return cpu->env.pmsav8.rlar[region];
101
+ }
102
+
103
if (region >= cpu->pmsav7_dregion) {
104
return 0;
105
}
106
return ((cpu->env.pmsav7.dracr[region] & 0xffff) << 16) |
107
(cpu->env.pmsav7.drsr[region] & 0xffff);
108
}
109
+ case 0xdc0: /* MPU_MAIR0 */
110
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
111
+ goto bad_offset;
82
+ goto bad_offset;
112
+ }
83
+ }
113
+ return cpu->env.pmsav8.mair0;
84
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
114
+ case 0xdc4: /* MPU_MAIR1 */
85
+ return 0;
115
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
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)) {
116
+ goto bad_offset;
103
+ goto bad_offset;
117
+ }
104
+ }
118
+ return cpu->env.pmsav8.mair1;
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
119
default:
120
+ bad_offset:
121
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
122
return 0;
123
}
124
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
125
{
126
int region;
127
128
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
129
+ /* PMSAv8M handling of the aliases is different from v7M:
130
+ * aliases A1, A2, A3 override the low two bits of the region
131
+ * number in MPU_RNR, and there is no 'region' field in the
132
+ * RBAR register.
133
+ */
134
+ int aliasno = (offset - 0xd9c) / 8; /* 0..3 */
135
+
136
+ region = cpu->env.pmsav7.rnr;
137
+ if (aliasno) {
138
+ region = deposit32(region, 0, 2, aliasno);
139
+ }
140
+ if (region >= cpu->pmsav7_dregion) {
141
+ return;
142
+ }
143
+ cpu->env.pmsav8.rbar[region] = value;
144
+ tlb_flush(CPU(cpu));
145
+ return;
146
+ }
147
+
148
if (value & (1 << 4)) {
149
/* VALID bit means use the region number specified in this
150
* value and also update MPU_RNR.REGION with that value.
151
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
152
tlb_flush(CPU(cpu));
153
break;
154
}
155
- case 0xda0: /* MPU_RASR */
156
- case 0xda8: /* MPU_RASR_A1 */
157
- case 0xdb0: /* MPU_RASR_A2 */
158
- case 0xdb8: /* MPU_RASR_A3 */
159
+ case 0xda0: /* MPU_RASR (v7M), MPU_RLAR (v8M) */
160
+ case 0xda8: /* MPU_RASR_A1 (v7M), MPU_RLAR_A1 (v8M) */
161
+ case 0xdb0: /* MPU_RASR_A2 (v7M), MPU_RLAR_A2 (v8M) */
162
+ case 0xdb8: /* MPU_RASR_A3 (v7M), MPU_RLAR_A3 (v8M) */
163
{
164
int region = cpu->env.pmsav7.rnr;
165
166
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
167
+ /* PMSAv8M handling of the aliases is different from v7M:
168
+ * aliases A1, A2, A3 override the low two bits of the region
169
+ * number in MPU_RNR.
170
+ */
171
+ int aliasno = (offset - 0xd9c) / 8; /* 0..3 */
172
+
173
+ region = cpu->env.pmsav7.rnr;
174
+ if (aliasno) {
175
+ region = deposit32(region, 0, 2, aliasno);
176
+ }
177
+ if (region >= cpu->pmsav7_dregion) {
178
+ return;
179
+ }
180
+ cpu->env.pmsav8.rlar[region] = value;
181
+ tlb_flush(CPU(cpu));
182
+ return;
183
+ }
184
+
185
if (region >= cpu->pmsav7_dregion) {
186
return;
187
}
188
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
189
tlb_flush(CPU(cpu));
190
break;
191
}
192
+ case 0xdc0: /* MPU_MAIR0 */
193
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
194
+ goto bad_offset;
195
+ }
196
+ if (cpu->pmsav7_dregion) {
197
+ /* Register is RES0 if no MPU regions are implemented */
198
+ cpu->env.pmsav8.mair0 = value;
199
+ }
200
+ /* We don't need to do anything else because memory attributes
201
+ * only affect cacheability, and we don't implement caching.
202
+ */
203
+ break;
106
+ break;
204
+ case 0xdc4: /* MPU_MAIR1 */
107
case 0xf34: /* FPCCR */
205
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
206
+ goto bad_offset;
109
/* Not all bits here are banked. */
207
+ }
208
+ if (cpu->pmsav7_dregion) {
209
+ /* Register is RES0 if no MPU regions are implemented */
210
+ cpu->env.pmsav8.mair1 = value;
211
+ }
212
+ /* We don't need to do anything else because memory attributes
213
+ * only affect cacheability, and we don't implement caching.
214
+ */
215
+ break;
216
case 0xf00: /* Software Triggered Interrupt Register */
217
{
218
int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
219
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
220
break;
221
}
222
default:
223
+ bad_offset:
224
qemu_log_mask(LOG_GUEST_ERROR,
225
"NVIC: Bad write offset 0x%x\n", offset);
226
}
227
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
228
index XXXXXXX..XXXXXXX 100644
229
--- a/target/arm/cpu.c
230
+++ b/target/arm/cpu.c
231
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
232
env->vfp.xregs[ARM_VFP_FPEXC] = 0;
233
#endif
234
235
- if (arm_feature(env, ARM_FEATURE_PMSA) &&
236
- arm_feature(env, ARM_FEATURE_V7)) {
237
+ if (arm_feature(env, ARM_FEATURE_PMSA)) {
238
if (cpu->pmsav7_dregion > 0) {
239
- memset(env->pmsav7.drbar, 0,
240
- sizeof(*env->pmsav7.drbar) * cpu->pmsav7_dregion);
241
- memset(env->pmsav7.drsr, 0,
242
- sizeof(*env->pmsav7.drsr) * cpu->pmsav7_dregion);
243
- memset(env->pmsav7.dracr, 0,
244
- sizeof(*env->pmsav7.dracr) * cpu->pmsav7_dregion);
245
+ if (arm_feature(env, ARM_FEATURE_V8)) {
246
+ memset(env->pmsav8.rbar, 0,
247
+ sizeof(*env->pmsav8.rbar) * cpu->pmsav7_dregion);
248
+ memset(env->pmsav8.rlar, 0,
249
+ sizeof(*env->pmsav8.rlar) * cpu->pmsav7_dregion);
250
+ } else if (arm_feature(env, ARM_FEATURE_V7)) {
251
+ memset(env->pmsav7.drbar, 0,
252
+ sizeof(*env->pmsav7.drbar) * cpu->pmsav7_dregion);
253
+ memset(env->pmsav7.drsr, 0,
254
+ sizeof(*env->pmsav7.drsr) * cpu->pmsav7_dregion);
255
+ memset(env->pmsav7.dracr, 0,
256
+ sizeof(*env->pmsav7.dracr) * cpu->pmsav7_dregion);
257
+ }
258
}
259
env->pmsav7.rnr = 0;
260
+ env->pmsav8.mair0 = 0;
261
+ env->pmsav8.mair1 = 0;
262
}
263
264
set_flush_to_zero(1, &env->vfp.standard_fp_status);
265
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
266
}
267
268
if (nr) {
269
- env->pmsav7.drbar = g_new0(uint32_t, nr);
270
- env->pmsav7.drsr = g_new0(uint32_t, nr);
271
- env->pmsav7.dracr = g_new0(uint32_t, nr);
272
+ if (arm_feature(env, ARM_FEATURE_V8)) {
273
+ /* PMSAv8 */
274
+ env->pmsav8.rbar = g_new0(uint32_t, nr);
275
+ env->pmsav8.rlar = g_new0(uint32_t, nr);
276
+ } else {
277
+ env->pmsav7.drbar = g_new0(uint32_t, nr);
278
+ env->pmsav7.drsr = g_new0(uint32_t, nr);
279
+ env->pmsav7.dracr = g_new0(uint32_t, nr);
280
+ }
281
}
282
}
283
284
diff --git a/target/arm/machine.c b/target/arm/machine.c
285
index XXXXXXX..XXXXXXX 100644
286
--- a/target/arm/machine.c
287
+++ b/target/arm/machine.c
288
@@ -XXX,XX +XXX,XX @@ static bool pmsav7_needed(void *opaque)
289
CPUARMState *env = &cpu->env;
290
291
return arm_feature(env, ARM_FEATURE_PMSA) &&
292
- arm_feature(env, ARM_FEATURE_V7);
293
+ arm_feature(env, ARM_FEATURE_V7) &&
294
+ !arm_feature(env, ARM_FEATURE_V8);
295
}
296
297
static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id)
298
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmsav7_rnr = {
299
}
300
};
301
302
+static bool pmsav8_needed(void *opaque)
303
+{
304
+ ARMCPU *cpu = opaque;
305
+ CPUARMState *env = &cpu->env;
306
+
307
+ return arm_feature(env, ARM_FEATURE_PMSA) &&
308
+ arm_feature(env, ARM_FEATURE_V8);
309
+}
310
+
311
+static const VMStateDescription vmstate_pmsav8 = {
312
+ .name = "cpu/pmsav8",
313
+ .version_id = 1,
314
+ .minimum_version_id = 1,
315
+ .needed = pmsav8_needed,
316
+ .fields = (VMStateField[]) {
317
+ VMSTATE_VARRAY_UINT32(env.pmsav8.rbar, ARMCPU, pmsav7_dregion, 0,
318
+ vmstate_info_uint32, uint32_t),
319
+ VMSTATE_VARRAY_UINT32(env.pmsav8.rlar, ARMCPU, pmsav7_dregion, 0,
320
+ vmstate_info_uint32, uint32_t),
321
+ VMSTATE_UINT32(env.pmsav8.mair0, ARMCPU),
322
+ VMSTATE_UINT32(env.pmsav8.mair1, ARMCPU),
323
+ VMSTATE_END_OF_LIST()
324
+ }
325
+};
326
+
327
static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
328
VMStateField *field)
329
{
330
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_arm_cpu = {
331
*/
332
&vmstate_pmsav7_rnr,
333
&vmstate_pmsav7,
334
+ &vmstate_pmsav8,
335
NULL
336
}
337
};
338
--
110
--
339
2.7.4
111
2.20.1
340
112
341
113
diff view generated by jsdifflib
1
For v8M the range 0xe002e000..0xe002efff is an alias region which
1
The RAS feature has a block of memory-mapped registers at offset
2
for secure accesses behaves like a NonSecure access to the main
2
0x5000 within the PPB. For a "minimal RAS" implementation we provide
3
SCS region. (For nonsecure accesses including when the security
3
no error records and so the only registers that exist in the block
4
extension is not implemented, it is RAZ/WI.)
4
are ERRIIDR and ERRDEVID.
5
6
The "RAZ/WI for privileged, BusFault for nonprivileged" behaviour
7
of the "nvic-default" region is actually valid for minimal-RAS,
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.
5
12
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 1503414539-28762-11-git-send-email-peter.maydell@linaro.org
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-27-peter.maydell@linaro.org
8
---
16
---
9
include/hw/intc/armv7m_nvic.h | 1 +
17
include/hw/intc/armv7m_nvic.h | 1 +
10
hw/intc/armv7m_nvic.c | 66 ++++++++++++++++++++++++++++++++++++++++++-
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
11
2 files changed, 66 insertions(+), 1 deletion(-)
19
2 files changed, 57 insertions(+)
12
20
13
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/intc/armv7m_nvic.h
23
--- a/include/hw/intc/armv7m_nvic.h
16
+++ b/include/hw/intc/armv7m_nvic.h
24
+++ b/include/hw/intc/armv7m_nvic.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct NVICState {
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
18
int exception_prio; /* group prio of the highest prio active exception */
26
MemoryRegion sysreg_ns_mem;
19
27
MemoryRegion systickmem;
20
MemoryRegion sysregmem;
28
MemoryRegion systick_ns_mem;
21
+ MemoryRegion sysreg_ns_mem;
29
+ MemoryRegion ras_mem;
22
MemoryRegion container;
30
MemoryRegion container;
23
31
MemoryRegion defaultmem;
24
uint32_t num_irq;
32
25
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
26
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/intc/armv7m_nvic.c
35
--- a/hw/intc/armv7m_nvic.c
28
+++ b/hw/intc/armv7m_nvic.c
36
+++ b/hw/intc/armv7m_nvic.c
29
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
30
.endianness = DEVICE_NATIVE_ENDIAN,
38
.endianness = DEVICE_NATIVE_ENDIAN,
31
};
39
};
32
40
33
+static MemTxResult nvic_sysreg_ns_write(void *opaque, hwaddr addr,
41
+
34
+ uint64_t value, unsigned size,
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
35
+ MemTxAttrs attrs)
43
+ uint64_t *data, unsigned size,
44
+ MemTxAttrs attrs)
36
+{
45
+{
37
+ if (attrs.secure) {
46
+ if (attrs.user) {
38
+ /* S accesses to the alias act like NS accesses to the real region */
47
+ return MEMTX_ERROR;
39
+ attrs.secure = 0;
40
+ return nvic_sysreg_write(opaque, addr, value, size, attrs);
41
+ } else {
42
+ /* NS attrs are RAZ/WI for privileged, and BusFault for user */
43
+ if (attrs.user) {
44
+ return MEMTX_ERROR;
45
+ }
46
+ return MEMTX_OK;
47
+ }
48
+ }
49
+
50
+ switch (addr) {
51
+ case 0xe10: /* ERRIIDR */
52
+ /* architect field = Arm; product/variant/revision 0 */
53
+ *data = 0x43b;
54
+ break;
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;
48
+}
66
+}
49
+
67
+
50
+static MemTxResult nvic_sysreg_ns_read(void *opaque, hwaddr addr,
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
51
+ uint64_t *data, unsigned size,
69
+ uint64_t value, unsigned size,
52
+ MemTxAttrs attrs)
70
+ MemTxAttrs attrs)
53
+{
71
+{
54
+ if (attrs.secure) {
72
+ if (attrs.user) {
55
+ /* S accesses to the alias act like NS accesses to the real region */
73
+ return MEMTX_ERROR;
56
+ attrs.secure = 0;
57
+ return nvic_sysreg_read(opaque, addr, data, size, attrs);
58
+ } else {
59
+ /* NS attrs are RAZ/WI for privileged, and BusFault for user */
60
+ if (attrs.user) {
61
+ return MEMTX_ERROR;
62
+ }
63
+ *data = 0;
64
+ return MEMTX_OK;
65
+ }
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;
66
+}
83
+}
67
+
84
+
68
+static const MemoryRegionOps nvic_sysreg_ns_ops = {
85
+static const MemoryRegionOps ras_ops = {
69
+ .read_with_attrs = nvic_sysreg_ns_read,
86
+ .read_with_attrs = ras_read,
70
+ .write_with_attrs = nvic_sysreg_ns_write,
87
+ .write_with_attrs = ras_write,
71
+ .endianness = DEVICE_NATIVE_ENDIAN,
88
+ .endianness = DEVICE_NATIVE_ENDIAN,
72
+};
89
+};
73
+
90
+
74
static int nvic_post_load(void *opaque, int version_id)
91
/*
75
{
92
* Unassigned portions of the PPB space are RAZ/WI for privileged
76
NVICState *s = opaque;
93
* accesses, and fault for non-privileged accesses.
77
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
94
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
78
NVICState *s = NVIC(dev);
95
&s->systick_ns_mem, 1);
79
SysBusDevice *systick_sbd;
96
}
80
Error *err = NULL;
97
81
+ int regionlen;
98
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
82
99
+ memory_region_init_io(&s->ras_mem, OBJECT(s),
83
s->cpu = ARM_CPU(qemu_get_cpu(0));
100
+ &ras_ops, s, "nvic_ras", 0x1000);
84
assert(s->cpu);
101
+ memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
85
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
86
* 0xd00..0xd3c - SCS registers
87
* 0xd40..0xeff - Reserved or Not implemented
88
* 0xf00 - STIR
89
+ *
90
+ * Some registers within this space are banked between security states.
91
+ * In v8M there is a second range 0xe002e000..0xe002efff which is the
92
+ * NonSecure alias SCS; secure accesses to this behave like NS accesses
93
+ * to the main SCS range, and non-secure accesses (including when
94
+ * the security extension is not implemented) are RAZ/WI.
95
+ * Note that both the main SCS range and the alias range are defined
96
+ * to be exempt from memory attribution (R_BLJT) and so the memory
97
+ * transaction attribute always matches the current CPU security
98
+ * state (attrs.secure == env->v7m.secure). In the nvic_sysreg_ns_ops
99
+ * wrappers we change attrs.secure to indicate the NS access; so
100
+ * generally code determining which banked register to use should
101
+ * use attrs.secure; code determining actual behaviour of the system
102
+ * should use env->v7m.secure.
103
*/
104
- memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
105
+ regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
106
+ memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
107
/* The system register region goes at the bottom of the priority
108
* stack as it covers the whole page.
109
*/
110
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
111
sysbus_mmio_get_region(systick_sbd, 0),
112
1);
113
114
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
115
+ memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
116
+ &nvic_sysreg_ns_ops, s,
117
+ "nvic_sysregs_ns", 0x1000);
118
+ memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
119
+ }
102
+ }
120
+
103
+
121
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
104
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
122
}
105
}
123
106
124
--
107
--
125
2.7.4
108
2.20.1
126
109
127
110
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
Correct a typo in the name we give the NVIC object.
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20170905131149.10669-3-famz@redhat.com
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
7
---
9
hw/arm/armv7m.c | 8 ++------
8
hw/arm/armv7m.c | 2 +-
10
1 file changed, 2 insertions(+), 6 deletions(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
11
10
12
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/armv7m.c
13
--- a/hw/arm/armv7m.c
15
+++ b/hw/arm/armv7m.c
14
+++ b/hw/arm/armv7m.c
16
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
17
16
18
/* Can't init the cpu here, we don't yet know which model to use */
19
20
- object_property_add_link(obj, "memory",
21
- TYPE_MEMORY_REGION,
22
- (Object **)&s->board_memory,
23
- qdev_prop_allow_set_link_before_realize,
24
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
25
- &error_abort);
26
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
27
18
28
object_initialize(&s->nvic, sizeof(s->nvic), TYPE_NVIC);
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
29
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
30
21
object_property_add_alias(obj, "num-irq",
31
static Property armv7m_properties[] = {
22
OBJECT(&s->nvic), "num-irq");
32
DEFINE_PROP_STRING("cpu-model", ARMv7MState, cpu_model),
33
+ DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
34
+ MemoryRegion *),
35
DEFINE_PROP_END_OF_LIST(),
36
};
37
23
38
--
24
--
39
2.7.4
25
2.20.1
40
26
41
27
diff view generated by jsdifflib