1
Mostly my stuff with a few easy patches from others. I know I have
1
Last handful of arm patches before softfreeze...
2
a few big series in my to-review queue, but I've been too jetlagged
3
to try to tackle those :-(
4
2
5
thanks
3
The following changes since commit a98135f727595382e200d04c2996e868b7925a01:
6
-- PMM
7
4
8
The following changes since commit a26a98dfb9d448d7234d931ae3720feddf6f0651:
5
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20200316-pull-request' into staging (2020-03-16 14:55:59 +0000)
9
6
10
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20171006' into staging (2017-10-06 13:19:03 +0100)
7
are available in the Git repository at:
11
8
12
are available in the git repository at:
9
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200317
13
10
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20171006
11
for you to fetch changes up to e88d3671e3bbd59d385838a4101ea19cdcf47309:
15
12
16
for you to fetch changes up to 04829ce334bece78d4fa1d0fdbc8bc27dae9b242:
13
hw/arm/pxa2xx: Do not wire up OHCI for PXA255 (2020-03-17 11:36:48 +0000)
17
18
nvic: Add missing code for writing SHCSR.HARDFAULTPENDED bit (2017-10-06 16:46:49 +0100)
19
14
20
----------------------------------------------------------------
15
----------------------------------------------------------------
21
target-arm:
16
target-arm:
22
* v8M: more preparatory work
17
* hw/arm/pxa2xx: Do not wire up OHCI for PXA255
23
* nvic: reset properly rather than leaving the nvic in a weird state
18
* aspeed/smc: Fix number of dummy cycles for FAST_READ_4 command
24
* xlnx-zynqmp: Mark the "xlnx, zynqmp" device with user_creatable = false
19
* m25p80: Improve command handling for Jedec and unsupported commands
25
* sd: fix out-of-bounds check for multi block reads
20
* hw/net/imx_fec: write TGSR and TCSR3 in imx_enet_write()
26
* arm: Fix SMC reporting to EL2 when QEMU provides PSCI
21
* hw/arm/fsl-imx6, imx6ul: Wire up USB controllers
22
* hw/arm/fsl-imx6ul: Instantiate unimplemented pwm and can devices
27
23
28
----------------------------------------------------------------
24
----------------------------------------------------------------
29
Jan Kiszka (1):
25
Chen Qun (1):
30
arm: Fix SMC reporting to EL2 when QEMU provides PSCI
26
hw/net/imx_fec: write TGSR and TCSR3 in imx_enet_write()
31
27
32
Michael Olbrich (1):
28
Guenter Roeck (10):
33
hw/sd: fix out-of-bounds check for multi block reads
29
hw/usb: Add basic i.MX USB Phy support
30
hw/arm/fsl-imx6ul: Fix USB interrupt numbers
31
hw/arm/fsl-imx6ul: Instantiate unimplemented pwm and can devices
32
hw/arm/fsl-imx6ul: Wire up USB controllers
33
hw/arm/fsl-imx6: Wire up USB controllers
34
m25p80: Convert to support tracing
35
m25p80: Improve command handling for Jedec commands
36
m25p80: Improve command handling for unsupported commands
37
aspeed/smc: Fix number of dummy cycles for FAST_READ_4 command
38
hw/arm/pxa2xx: Do not wire up OHCI for PXA255
34
39
35
Peter Maydell (17):
40
hw/usb/Makefile.objs | 2 +
36
nvic: Clear the vector arrays and prigroup on reset
41
include/hw/arm/fsl-imx6.h | 6 ++
37
target/arm: Don't switch to target stack early in v7M exception return
42
include/hw/arm/fsl-imx6ul.h | 16 ++-
38
target/arm: Prepare for CONTROL.SPSEL being nonzero in Handler mode
43
include/hw/usb/imx-usb-phy.h | 53 ++++++++++
39
target/arm: Restore security state on exception return
44
hw/arm/fsl-imx6.c | 36 +++++++
40
target/arm: Restore SPSEL to correct CONTROL register on exception return
45
hw/arm/fsl-imx6ul.c | 49 ++++++++++
41
target/arm: Check for xPSR mismatch usage faults earlier for v8M
46
hw/arm/pxa2xx.c | 3 -
42
target/arm: Warn about restoring to unaligned stack
47
hw/block/m25p80.c | 58 +++++------
43
target/arm: Don't warn about exception return with PC low bit set for v8M
48
hw/net/imx_fec.c | 6 +-
44
target/arm: Add new-in-v8M SFSR and SFAR
49
hw/ssi/aspeed_smc.c | 2 +-
45
target/arm: Update excret sanity checks for v8M
50
hw/usb/imx-usb-phy.c | 225 +++++++++++++++++++++++++++++++++++++++++++
46
target/arm: Add support for restoring v8M additional state context
51
MAINTAINERS | 2 +
47
target/arm: Add v8M support to exception entry code
52
hw/arm/Kconfig | 1 +
48
nvic: Implement Security Attribution Unit registers
53
hw/block/trace-events | 16 +++
49
target/arm: Implement security attribute lookups for memory accesses
54
hw/usb/Kconfig | 5 +
50
target/arm: Fix calculation of secure mm_idx values
55
15 files changed, 444 insertions(+), 36 deletions(-)
51
target/arm: Factor out "get mmuidx for specified security state"
56
create mode 100644 include/hw/usb/imx-usb-phy.h
52
nvic: Add missing code for writing SHCSR.HARDFAULTPENDED bit
57
create mode 100644 hw/usb/imx-usb-phy.c
53
58
54
Thomas Huth (1):
55
hw/arm/xlnx-zynqmp: Mark the "xlnx, zynqmp" device with user_creatable = false
56
57
target/arm/cpu.h | 60 ++++-
58
target/arm/internals.h | 15 ++
59
hw/arm/xlnx-zynqmp.c | 2 +
60
hw/intc/armv7m_nvic.c | 158 ++++++++++-
61
hw/sd/sd.c | 12 +-
62
target/arm/cpu.c | 27 ++
63
target/arm/helper.c | 691 +++++++++++++++++++++++++++++++++++++++++++------
64
target/arm/machine.c | 16 ++
65
target/arm/op_helper.c | 27 +-
66
9 files changed, 898 insertions(+), 110 deletions(-)
67
diff view generated by jsdifflib
1
Currently our M profile exception return code switches to the
1
From: Guenter Roeck <linux@roeck-us.net>
2
target stack pointer relatively early in the process, before
2
3
it tries to pop the exception frame off the stack. This is
3
Add basic USB PHY support as implemented in i.MX23, i.MX28, i.MX6,
4
awkward for v8M for two reasons:
4
and i.MX7 SoCs.
5
* in v8M the process vs main stack pointer is not selected
5
6
purely by the value of CONTROL.SPSEL, so updating SPSEL
6
The only support really needed - at least to boot Linux - is support
7
and relying on that to switch to the right stack pointer
7
for soft reset, which needs to reset various registers to their initial
8
won't work
8
value. Otherwise, just record register values.
9
* the stack we should be reading the stack frame from and
9
10
the stack we will eventually switch to might not be the
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
same if the guest is doing strange things
11
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
12
12
Message-id: 20200313014551.12554-2-linux@roeck-us.net
13
Change our exception return code to use a 'frame pointer'
14
to read the exception frame rather than assuming that we
15
can switch the live stack pointer this early.
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 1506092407-26985-3-git-send-email-peter.maydell@linaro.org
21
---
14
---
22
target/arm/helper.c | 130 +++++++++++++++++++++++++++++++++++++++-------------
15
hw/usb/Makefile.objs | 2 +
23
1 file changed, 98 insertions(+), 32 deletions(-)
16
include/hw/usb/imx-usb-phy.h | 53 +++++++++
24
17
hw/usb/imx-usb-phy.c | 225 +++++++++++++++++++++++++++++++++++
25
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
MAINTAINERS | 2 +
19
hw/arm/Kconfig | 1 +
20
hw/usb/Kconfig | 5 +
21
6 files changed, 288 insertions(+)
22
create mode 100644 include/hw/usb/imx-usb-phy.h
23
create mode 100644 hw/usb/imx-usb-phy.c
24
25
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
26
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/helper.c
27
--- a/hw/usb/Makefile.objs
28
+++ b/target/arm/helper.c
28
+++ b/hw/usb/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ static void v7m_push(CPUARMState *env, uint32_t val)
29
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XEN) += xen-usb.o
30
stl_phys(cs->as, env->regs[13], val);
30
xen-usb.o-cflags := $(LIBUSB_CFLAGS)
31
}
31
xen-usb.o-libs := $(LIBUSB_LIBS)
32
32
endif
33
-static uint32_t v7m_pop(CPUARMState *env)
33
+
34
-{
34
+common-obj-$(CONFIG_IMX_USBPHY) += imx-usb-phy.o
35
- CPUState *cs = CPU(arm_env_get_cpu(env));
35
diff --git a/include/hw/usb/imx-usb-phy.h b/include/hw/usb/imx-usb-phy.h
36
- uint32_t val;
36
new file mode 100644
37
-
37
index XXXXXXX..XXXXXXX
38
- val = ldl_phys(cs->as, env->regs[13]);
38
--- /dev/null
39
- env->regs[13] += 4;
39
+++ b/include/hw/usb/imx-usb-phy.h
40
- return val;
40
@@ -XXX,XX +XXX,XX @@
41
-}
41
+#ifndef IMX_USB_PHY_H
42
-
42
+#define IMX_USB_PHY_H
43
/* Return true if we're using the process stack pointer (not the MSP) */
43
+
44
static bool v7m_using_psp(CPUARMState *env)
44
+#include "hw/sysbus.h"
45
{
45
+#include "qemu/bitops.h"
46
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
46
+
47
env->regs[15] = dest & ~1;
47
+enum IMXUsbPhyRegisters {
48
}
48
+ USBPHY_PWD,
49
49
+ USBPHY_PWD_SET,
50
+static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
50
+ USBPHY_PWD_CLR,
51
+ bool spsel)
51
+ USBPHY_PWD_TOG,
52
+{
52
+ USBPHY_TX,
53
+ /* Return a pointer to the location where we currently store the
53
+ USBPHY_TX_SET,
54
+ * stack pointer for the requested security state and thread mode.
54
+ USBPHY_TX_CLR,
55
+ * This pointer will become invalid if the CPU state is updated
55
+ USBPHY_TX_TOG,
56
+ * such that the stack pointers are switched around (eg changing
56
+ USBPHY_RX,
57
+ * the SPSEL control bit).
57
+ USBPHY_RX_SET,
58
+ * Compare the v8M ARM ARM pseudocode LookUpSP_with_security_mode().
58
+ USBPHY_RX_CLR,
59
+ * Unlike that pseudocode, we require the caller to pass us in the
59
+ USBPHY_RX_TOG,
60
+ * SPSEL control bit value; this is because we also use this
60
+ USBPHY_CTRL,
61
+ * function in handling of pushing of the callee-saves registers
61
+ USBPHY_CTRL_SET,
62
+ * part of the v8M stack frame (pseudocode PushCalleeStack()),
62
+ USBPHY_CTRL_CLR,
63
+ * and in the tailchain codepath the SPSEL bit comes from the exception
63
+ USBPHY_CTRL_TOG,
64
+ * return magic LR value from the previous exception. The pseudocode
64
+ USBPHY_STATUS,
65
+ * opencodes the stack-selection in PushCalleeStack(), but we prefer
65
+ USBPHY_DEBUG = 0x14,
66
+ * to make this utility function generic enough to do the job.
66
+ USBPHY_DEBUG_SET,
67
+ */
67
+ USBPHY_DEBUG_CLR,
68
+ bool want_psp = threadmode && spsel;
68
+ USBPHY_DEBUG_TOG,
69
+
69
+ USBPHY_DEBUG0_STATUS,
70
+ if (secure == env->v7m.secure) {
70
+ USBPHY_DEBUG1 = 0x1c,
71
+ /* Currently switch_v7m_sp switches SP as it updates SPSEL,
71
+ USBPHY_DEBUG1_SET,
72
+ * so the SP we want is always in regs[13].
72
+ USBPHY_DEBUG1_CLR,
73
+ * When we decouple SPSEL from the actually selected SP
73
+ USBPHY_DEBUG1_TOG,
74
+ * we need to check want_psp against v7m_using_psp()
74
+ USBPHY_VERSION,
75
+ * to see whether we need regs[13] or v7m.other_sp.
75
+ USBPHY_MAX
76
+ */
76
+};
77
+ return &env->regs[13];
77
+
78
+ } else {
78
+#define USBPHY_CTRL_SFTRST BIT(31)
79
+ if (want_psp) {
79
+
80
+ return &env->v7m.other_ss_psp;
80
+#define TYPE_IMX_USBPHY "imx.usbphy"
81
+ } else {
81
+#define IMX_USBPHY(obj) OBJECT_CHECK(IMXUSBPHYState, (obj), TYPE_IMX_USBPHY)
82
+ return &env->v7m.other_ss_msp;
82
+
83
+typedef struct IMXUSBPHYState {
84
+ /* <private> */
85
+ SysBusDevice parent_obj;
86
+
87
+ /* <public> */
88
+ MemoryRegion iomem;
89
+
90
+ uint32_t usbphy[USBPHY_MAX];
91
+} IMXUSBPHYState;
92
+
93
+#endif /* IMX_USB_PHY_H */
94
diff --git a/hw/usb/imx-usb-phy.c b/hw/usb/imx-usb-phy.c
95
new file mode 100644
96
index XXXXXXX..XXXXXXX
97
--- /dev/null
98
+++ b/hw/usb/imx-usb-phy.c
99
@@ -XXX,XX +XXX,XX @@
100
+/*
101
+ * i.MX USB PHY
102
+ *
103
+ * Copyright (c) 2020 Guenter Roeck <linux@roeck-us.net>
104
+ *
105
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
106
+ * See the COPYING file in the top-level directory.
107
+ *
108
+ * We need to implement basic reset control in the PHY control register.
109
+ * For everything else, it is sufficient to set whatever is written.
110
+ */
111
+
112
+#include "qemu/osdep.h"
113
+#include "hw/usb/imx-usb-phy.h"
114
+#include "migration/vmstate.h"
115
+#include "qemu/log.h"
116
+#include "qemu/module.h"
117
+
118
+static const VMStateDescription vmstate_imx_usbphy = {
119
+ .name = TYPE_IMX_USBPHY,
120
+ .version_id = 1,
121
+ .minimum_version_id = 1,
122
+ .fields = (VMStateField[]) {
123
+ VMSTATE_UINT32_ARRAY(usbphy, IMXUSBPHYState, USBPHY_MAX),
124
+ VMSTATE_END_OF_LIST()
125
+ },
126
+};
127
+
128
+static void imx_usbphy_softreset(IMXUSBPHYState *s)
129
+{
130
+ s->usbphy[USBPHY_PWD] = 0x001e1c00;
131
+ s->usbphy[USBPHY_TX] = 0x10060607;
132
+ s->usbphy[USBPHY_RX] = 0x00000000;
133
+ s->usbphy[USBPHY_CTRL] = 0xc0200000;
134
+}
135
+
136
+static void imx_usbphy_reset(DeviceState *dev)
137
+{
138
+ IMXUSBPHYState *s = IMX_USBPHY(dev);
139
+
140
+ s->usbphy[USBPHY_STATUS] = 0x00000000;
141
+ s->usbphy[USBPHY_DEBUG] = 0x7f180000;
142
+ s->usbphy[USBPHY_DEBUG0_STATUS] = 0x00000000;
143
+ s->usbphy[USBPHY_DEBUG1] = 0x00001000;
144
+ s->usbphy[USBPHY_VERSION] = 0x04020000;
145
+
146
+ imx_usbphy_softreset(s);
147
+}
148
+
149
+static uint64_t imx_usbphy_read(void *opaque, hwaddr offset, unsigned size)
150
+{
151
+ IMXUSBPHYState *s = (IMXUSBPHYState *)opaque;
152
+ uint32_t index = offset >> 2;
153
+ uint32_t value;
154
+
155
+ switch (index) {
156
+ case USBPHY_PWD_SET:
157
+ case USBPHY_TX_SET:
158
+ case USBPHY_RX_SET:
159
+ case USBPHY_CTRL_SET:
160
+ case USBPHY_DEBUG_SET:
161
+ case USBPHY_DEBUG1_SET:
162
+ /*
163
+ * All REG_NAME_SET register access are in fact targeting the
164
+ * REG_NAME register.
165
+ */
166
+ value = s->usbphy[index - 1];
167
+ break;
168
+ case USBPHY_PWD_CLR:
169
+ case USBPHY_TX_CLR:
170
+ case USBPHY_RX_CLR:
171
+ case USBPHY_CTRL_CLR:
172
+ case USBPHY_DEBUG_CLR:
173
+ case USBPHY_DEBUG1_CLR:
174
+ /*
175
+ * All REG_NAME_CLR register access are in fact targeting the
176
+ * REG_NAME register.
177
+ */
178
+ value = s->usbphy[index - 2];
179
+ break;
180
+ case USBPHY_PWD_TOG:
181
+ case USBPHY_TX_TOG:
182
+ case USBPHY_RX_TOG:
183
+ case USBPHY_CTRL_TOG:
184
+ case USBPHY_DEBUG_TOG:
185
+ case USBPHY_DEBUG1_TOG:
186
+ /*
187
+ * All REG_NAME_TOG register access are in fact targeting the
188
+ * REG_NAME register.
189
+ */
190
+ value = s->usbphy[index - 3];
191
+ break;
192
+ default:
193
+ value = s->usbphy[index];
194
+ break;
195
+ }
196
+ return (uint64_t)value;
197
+}
198
+
199
+static void imx_usbphy_write(void *opaque, hwaddr offset, uint64_t value,
200
+ unsigned size)
201
+{
202
+ IMXUSBPHYState *s = (IMXUSBPHYState *)opaque;
203
+ uint32_t index = offset >> 2;
204
+
205
+ switch (index) {
206
+ case USBPHY_CTRL:
207
+ s->usbphy[index] = value;
208
+ if (value & USBPHY_CTRL_SFTRST) {
209
+ imx_usbphy_softreset(s);
83
+ }
210
+ }
211
+ break;
212
+ case USBPHY_PWD:
213
+ case USBPHY_TX:
214
+ case USBPHY_RX:
215
+ case USBPHY_STATUS:
216
+ case USBPHY_DEBUG:
217
+ case USBPHY_DEBUG1:
218
+ s->usbphy[index] = value;
219
+ break;
220
+ case USBPHY_CTRL_SET:
221
+ s->usbphy[index - 1] |= value;
222
+ if (value & USBPHY_CTRL_SFTRST) {
223
+ imx_usbphy_softreset(s);
224
+ }
225
+ break;
226
+ case USBPHY_PWD_SET:
227
+ case USBPHY_TX_SET:
228
+ case USBPHY_RX_SET:
229
+ case USBPHY_DEBUG_SET:
230
+ case USBPHY_DEBUG1_SET:
231
+ /*
232
+ * All REG_NAME_SET register access are in fact targeting the
233
+ * REG_NAME register. So we change the value of the REG_NAME
234
+ * register, setting bits passed in the value.
235
+ */
236
+ s->usbphy[index - 1] |= value;
237
+ break;
238
+ case USBPHY_PWD_CLR:
239
+ case USBPHY_TX_CLR:
240
+ case USBPHY_RX_CLR:
241
+ case USBPHY_CTRL_CLR:
242
+ case USBPHY_DEBUG_CLR:
243
+ case USBPHY_DEBUG1_CLR:
244
+ /*
245
+ * All REG_NAME_CLR register access are in fact targeting the
246
+ * REG_NAME register. So we change the value of the REG_NAME
247
+ * register, unsetting bits passed in the value.
248
+ */
249
+ s->usbphy[index - 2] &= ~value;
250
+ break;
251
+ case USBPHY_CTRL_TOG:
252
+ s->usbphy[index - 3] ^= value;
253
+ if ((value & USBPHY_CTRL_SFTRST) &&
254
+ (s->usbphy[index - 3] & USBPHY_CTRL_SFTRST)) {
255
+ imx_usbphy_softreset(s);
256
+ }
257
+ break;
258
+ case USBPHY_PWD_TOG:
259
+ case USBPHY_TX_TOG:
260
+ case USBPHY_RX_TOG:
261
+ case USBPHY_DEBUG_TOG:
262
+ case USBPHY_DEBUG1_TOG:
263
+ /*
264
+ * All REG_NAME_TOG register access are in fact targeting the
265
+ * REG_NAME register. So we change the value of the REG_NAME
266
+ * register, toggling bits passed in the value.
267
+ */
268
+ s->usbphy[index - 3] ^= value;
269
+ break;
270
+ default:
271
+ /* Other registers are read-only */
272
+ break;
84
+ }
273
+ }
85
+}
274
+}
86
+
275
+
87
static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
276
+static const struct MemoryRegionOps imx_usbphy_ops = {
88
{
277
+ .read = imx_usbphy_read,
89
CPUState *cs = CPU(cpu);
278
+ .write = imx_usbphy_write,
90
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
279
+ .endianness = DEVICE_NATIVE_ENDIAN,
91
static void do_v7m_exception_exit(ARMCPU *cpu)
280
+ .valid = {
92
{
281
+ /*
93
CPUARMState *env = &cpu->env;
282
+ * Our device would not work correctly if the guest was doing
94
+ CPUState *cs = CPU(cpu);
283
+ * unaligned access. This might not be a limitation on the real
95
uint32_t excret;
284
+ * device but in practice there is no reason for a guest to access
96
uint32_t xpsr;
285
+ * this device unaligned.
97
bool ufault = false;
286
+ */
98
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
287
+ .min_access_size = 4,
99
bool return_to_handler = false;
288
+ .max_access_size = 4,
100
bool rettobase = false;
289
+ .unaligned = false,
101
bool exc_secure = false;
290
+ },
102
+ bool return_to_secure;
291
+};
103
292
+
104
/* We can only get here from an EXCP_EXCEPTION_EXIT, and
293
+static void imx_usbphy_realize(DeviceState *dev, Error **errp)
105
* gen_bx_excret() enforces the architectural rule
294
+{
106
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
295
+ IMXUSBPHYState *s = IMX_USBPHY(dev);
107
g_assert_not_reached();
296
+
108
}
297
+ memory_region_init_io(&s->iomem, OBJECT(s), &imx_usbphy_ops, s,
109
298
+ "imx-usbphy", 0x1000);
110
+ return_to_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
299
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
111
+ (excret & R_V7M_EXCRET_S_MASK);
300
+}
112
+
301
+
113
switch (excret & 0xf) {
302
+static void imx_usbphy_class_init(ObjectClass *klass, void *data)
114
case 1: /* Return to Handler */
303
+{
115
return_to_handler = true;
304
+ DeviceClass *dc = DEVICE_CLASS(klass);
116
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
305
+
117
return;
306
+ dc->reset = imx_usbphy_reset;
118
}
307
+ dc->vmsd = &vmstate_imx_usbphy;
119
308
+ dc->desc = "i.MX USB PHY Module";
120
- /* Switch to the target stack. */
309
+ dc->realize = imx_usbphy_realize;
121
+ /* Set CONTROL.SPSEL from excret.SPSEL. For QEMU this currently
310
+}
122
+ * causes us to switch the active SP, but we will change this
311
+
123
+ * later to not do that so we can support v8M.
312
+static const TypeInfo imx_usbphy_info = {
124
+ */
313
+ .name = TYPE_IMX_USBPHY,
125
switch_v7m_sp(env, return_to_sp_process);
314
+ .parent = TYPE_SYS_BUS_DEVICE,
126
- /* Pop registers. */
315
+ .instance_size = sizeof(IMXUSBPHYState),
127
- env->regs[0] = v7m_pop(env);
316
+ .class_init = imx_usbphy_class_init,
128
- env->regs[1] = v7m_pop(env);
317
+};
129
- env->regs[2] = v7m_pop(env);
318
+
130
- env->regs[3] = v7m_pop(env);
319
+static void imx_usbphy_register_types(void)
131
- env->regs[12] = v7m_pop(env);
320
+{
132
- env->regs[14] = v7m_pop(env);
321
+ type_register_static(&imx_usbphy_info);
133
- env->regs[15] = v7m_pop(env);
322
+}
134
- if (env->regs[15] & 1) {
323
+
135
- qemu_log_mask(LOG_GUEST_ERROR,
324
+type_init(imx_usbphy_register_types)
136
- "M profile return from interrupt with misaligned "
325
diff --git a/MAINTAINERS b/MAINTAINERS
137
- "PC is UNPREDICTABLE\n");
326
index XXXXXXX..XXXXXXX 100644
138
- /* Actual hardware seems to ignore the lsbit, and there are several
327
--- a/MAINTAINERS
139
- * RTOSes out there which incorrectly assume the r15 in the stack
328
+++ b/MAINTAINERS
140
- * frame should be a Thumb-style "lsbit indicates ARM/Thumb" value.
329
@@ -XXX,XX +XXX,XX @@ F: hw/arm/sabrelite.c
141
+
330
F: hw/arm/fsl-imx6.c
142
+ {
331
F: hw/misc/imx6_*.c
143
+ /* The stack pointer we should be reading the exception frame from
332
F: hw/ssi/imx_spi.c
144
+ * depends on bits in the magic exception return type value (and
333
+F: hw/usb/imx-usb-phy.c
145
+ * for v8M isn't necessarily the stack pointer we will eventually
334
+F: include/hw/usb/imx-usb-phy.h
146
+ * end up resuming execution with). Get a pointer to the location
335
F: include/hw/arm/fsl-imx6.h
147
+ * in the CPU state struct where the SP we need is currently being
336
F: include/hw/misc/imx6_*.h
148
+ * stored; we will use and modify it in place.
337
F: include/hw/ssi/imx_spi.h
149
+ * We use this limited C variable scope so we don't accidentally
338
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
150
+ * use 'frame_sp_p' after we do something that makes it invalid.
339
index XXXXXXX..XXXXXXX 100644
151
+ */
340
--- a/hw/arm/Kconfig
152
+ uint32_t *frame_sp_p = get_v7m_sp_ptr(env,
341
+++ b/hw/arm/Kconfig
153
+ return_to_secure,
342
@@ -XXX,XX +XXX,XX @@ config FSL_IMX6
154
+ !return_to_handler,
343
select IMX
155
+ return_to_sp_process);
344
select IMX_FEC
156
+ uint32_t frameptr = *frame_sp_p;
345
select IMX_I2C
157
+
346
+ select IMX_USBPHY
158
+ /* Pop registers. TODO: make these accesses use the correct
347
select SDHCI
159
+ * attributes and address space (S/NS, priv/unpriv) and handle
348
160
+ * memory transaction failures.
349
config ASPEED_SOC
161
*/
350
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
162
- env->regs[15] &= ~1U;
351
index XXXXXXX..XXXXXXX 100644
163
+ env->regs[0] = ldl_phys(cs->as, frameptr);
352
--- a/hw/usb/Kconfig
164
+ env->regs[1] = ldl_phys(cs->as, frameptr + 0x4);
353
+++ b/hw/usb/Kconfig
165
+ env->regs[2] = ldl_phys(cs->as, frameptr + 0x8);
354
@@ -XXX,XX +XXX,XX @@ config USB_STORAGE_MTP
166
+ env->regs[3] = ldl_phys(cs->as, frameptr + 0xc);
355
bool
167
+ env->regs[12] = ldl_phys(cs->as, frameptr + 0x10);
356
default y
168
+ env->regs[14] = ldl_phys(cs->as, frameptr + 0x14);
357
depends on USB
169
+ env->regs[15] = ldl_phys(cs->as, frameptr + 0x18);
358
+
170
+ if (env->regs[15] & 1) {
359
+config IMX_USBPHY
171
+ qemu_log_mask(LOG_GUEST_ERROR,
360
+ bool
172
+ "M profile return from interrupt with misaligned "
361
+ default y
173
+ "PC is UNPREDICTABLE\n");
362
+ depends on USB
174
+ /* Actual hardware seems to ignore the lsbit, and there are several
175
+ * RTOSes out there which incorrectly assume the r15 in the stack
176
+ * frame should be a Thumb-style "lsbit indicates ARM/Thumb" value.
177
+ */
178
+ env->regs[15] &= ~1U;
179
+ }
180
+ xpsr = ldl_phys(cs->as, frameptr + 0x1c);
181
+
182
+ /* Commit to consuming the stack frame */
183
+ frameptr += 0x20;
184
+ /* Undo stack alignment (the SPREALIGN bit indicates that the original
185
+ * pre-exception SP was not 8-aligned and we added a padding word to
186
+ * align it, so we undo this by ORing in the bit that increases it
187
+ * from the current 8-aligned value to the 8-unaligned value. (Adding 4
188
+ * would work too but a logical OR is how the pseudocode specifies it.)
189
+ */
190
+ if (xpsr & XPSR_SPREALIGN) {
191
+ frameptr |= 4;
192
+ }
193
+ *frame_sp_p = frameptr;
194
}
195
- xpsr = v7m_pop(env);
196
+ /* This xpsr_write() will invalidate frame_sp_p as it may switch stack */
197
xpsr_write(env, xpsr, ~XPSR_SPREALIGN);
198
- /* Undo stack alignment. */
199
- if (xpsr & XPSR_SPREALIGN) {
200
- env->regs[13] |= 4;
201
- }
202
203
/* The restored xPSR exception field will be zero if we're
204
* resuming in Thread mode. If that doesn't match what the
205
--
363
--
206
2.7.4
364
2.20.1
207
365
208
366
diff view generated by jsdifflib
1
When we added support for the new SHCSR bits in v8M in commit
1
From: Guenter Roeck <linux@roeck-us.net>
2
437d59c17e9 the code to support writing to the new HARDFAULTPENDED
3
bit was accidentally only added for non-secure writes; the
4
secure banked version of the bit should also be writable.
5
2
3
USB1 and USB2 interrupt numbers were swapped. USB_PHY2 interrupt number
4
is 45. That didn't really matter up to now since the interrupts were not
5
used, but it needs to be fixed to be able to wire up the USB controllers.
6
7
Fixes: 31cbf933f0e ("i.MX6UL: Add i.MX6UL SOC")
8
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
9
Message-id: 20200313014551.12554-3-linux@roeck-us.net
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1506092407-26985-21-git-send-email-peter.maydell@linaro.org
10
---
12
---
11
hw/intc/armv7m_nvic.c | 1 +
13
include/hw/arm/fsl-imx6ul.h | 6 +++---
12
1 file changed, 1 insertion(+)
14
1 file changed, 3 insertions(+), 3 deletions(-)
13
15
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
16
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/armv7m_nvic.c
18
--- a/include/hw/arm/fsl-imx6ul.h
17
+++ b/hw/intc/armv7m_nvic.c
19
+++ b/include/hw/arm/fsl-imx6ul.h
18
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
20
@@ -XXX,XX +XXX,XX @@ enum FslIMX6ULIRQs {
19
s->sec_vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
21
FSL_IMX6UL_UART7_IRQ = 39,
20
s->sec_vectors[ARMV7M_EXCP_USAGE].enabled =
22
FSL_IMX6UL_UART8_IRQ = 40,
21
(value & (1 << 18)) != 0;
23
22
+ s->sec_vectors[ARMV7M_EXCP_HARD].pending = (value & (1 << 21)) != 0;
24
- FSL_IMX6UL_USB1_IRQ = 42,
23
/* SecureFault not banked, but RAZ/WI to NS */
25
- FSL_IMX6UL_USB2_IRQ = 43,
24
s->vectors[ARMV7M_EXCP_SECURE].active = (value & (1 << 4)) != 0;
26
+ FSL_IMX6UL_USB1_IRQ = 43,
25
s->vectors[ARMV7M_EXCP_SECURE].enabled = (value & (1 << 19)) != 0;
27
+ FSL_IMX6UL_USB2_IRQ = 42,
28
FSL_IMX6UL_USB_PHY1_IRQ = 44,
29
- FSL_IMX6UL_USB_PHY2_IRQ = 44,
30
+ FSL_IMX6UL_USB_PHY2_IRQ = 45,
31
32
FSL_IMX6UL_CAAM_JQ2_IRQ = 46,
33
FSL_IMX6UL_CAAM_ERR_IRQ = 47,
26
--
34
--
27
2.7.4
35
2.20.1
28
36
29
37
diff view generated by jsdifflib
1
For the SG instruction and secure function return we are going
1
From: Guenter Roeck <linux@roeck-us.net>
2
to want to do memory accesses using the MMU index of the CPU
3
in secure state, even though the CPU is currently in non-secure
4
state. Write arm_v7m_mmu_idx_for_secstate() to do this job,
5
and use it in cpu_mmu_index().
6
2
3
Recent Linux kernels (post v4.20) crash due to accesses to flexcan
4
and pwm controllers. Instantiate as unimplemented devices to work
5
around the problem.
6
7
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20200313014551.12554-4-linux@roeck-us.net
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
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1506092407-26985-17-git-send-email-peter.maydell@linaro.org
11
---
11
---
12
target/arm/cpu.h | 32 +++++++++++++++++++++-----------
12
hw/arm/fsl-imx6ul.c | 14 ++++++++++++++
13
1 file changed, 21 insertions(+), 11 deletions(-)
13
1 file changed, 14 insertions(+)
14
14
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
17
--- a/hw/arm/fsl-imx6ul.c
18
+++ b/target/arm/cpu.h
18
+++ b/hw/arm/fsl-imx6ul.c
19
@@ -XXX,XX +XXX,XX @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
19
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
20
}
20
*/
21
}
21
create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR, 0x4000);
22
22
23
+/* Return the MMU index for a v7M CPU in the specified security state */
23
+ /*
24
+static inline ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env,
24
+ * PWM
25
+ bool secstate)
25
+ */
26
+{
26
+ create_unimplemented_device("pwm1", FSL_IMX6UL_PWM1_ADDR, 0x4000);
27
+ int el = arm_current_el(env);
27
+ create_unimplemented_device("pwm2", FSL_IMX6UL_PWM2_ADDR, 0x4000);
28
+ ARMMMUIdx mmu_idx;
28
+ create_unimplemented_device("pwm3", FSL_IMX6UL_PWM3_ADDR, 0x4000);
29
+ create_unimplemented_device("pwm4", FSL_IMX6UL_PWM4_ADDR, 0x4000);
29
+
30
+
30
+ if (el == 0) {
31
+ /*
31
+ mmu_idx = secstate ? ARMMMUIdx_MSUser : ARMMMUIdx_MUser;
32
+ * CAN
32
+ } else {
33
+ */
33
+ mmu_idx = secstate ? ARMMMUIdx_MSPriv : ARMMMUIdx_MPriv;
34
+ create_unimplemented_device("can1", FSL_IMX6UL_CAN1_ADDR, 0x4000);
34
+ }
35
+ create_unimplemented_device("can2", FSL_IMX6UL_CAN2_ADDR, 0x4000);
35
+
36
+
36
+ if (armv7m_nvic_neg_prio_requested(env->nvic, secstate)) {
37
/*
37
+ mmu_idx = secstate ? ARMMMUIdx_MSNegPri : ARMMMUIdx_MNegPri;
38
* APHB_DMA
38
+ }
39
*/
39
+
40
+ return mmu_idx;
41
+}
42
+
43
/* Determine the current mmu_idx to use for normal loads/stores */
44
static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
45
{
46
int el = arm_current_el(env);
47
48
if (arm_feature(env, ARM_FEATURE_M)) {
49
- ARMMMUIdx mmu_idx;
50
-
51
- if (el == 0) {
52
- mmu_idx = env->v7m.secure ? ARMMMUIdx_MSUser : ARMMMUIdx_MUser;
53
- } else {
54
- mmu_idx = env->v7m.secure ? ARMMMUIdx_MSPriv : ARMMMUIdx_MPriv;
55
- }
56
-
57
- if (armv7m_nvic_neg_prio_requested(env->nvic, env->v7m.secure)) {
58
- mmu_idx = env->v7m.secure ? ARMMMUIdx_MSNegPri : ARMMMUIdx_MNegPri;
59
- }
60
+ ARMMMUIdx mmu_idx = arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
61
62
return arm_to_core_mmu_idx(mmu_idx);
63
}
64
--
40
--
65
2.7.4
41
2.20.1
66
42
67
43
diff view generated by jsdifflib
1
Implement the security attribute lookups for memory accesses
1
From: Guenter Roeck <linux@roeck-us.net>
2
in the get_phys_addr() functions, causing these to generate
3
various kinds of SecureFault for bad accesses.
4
2
5
The major subtlety in this code relates to handling of the
3
IMX6UL USB controllers are quite similar to IMX7 USB controllers.
6
case when the security attributes the SAU assigns to the
4
Wire them up the same way.
7
address don't match the current security state of the CPU.
8
5
9
In the ARM ARM pseudocode for validating instruction
6
The only real difference is that wiring up phy devices is necessary
10
accesses, the security attributes of the address determine
7
to avoid phy reset timeouts in the Linux kernel.
11
whether the Secure or NonSecure MPU state is used. At face
12
value, handling this would require us to encode the relevant
13
bits of state into mmu_idx for both S and NS at once, which
14
would result in our needing 16 mmu indexes. Fortunately we
15
don't actually need to do this because a mismatch between
16
address attributes and CPU state means either:
17
* some kind of fault (usually a SecureFault, but in theory
18
perhaps a UserFault for unaligned access to Device memory)
19
* execution of the SG instruction in NS state from a
20
Secure & NonSecure code region
21
8
22
The purpose of SG is simply to flip the CPU into Secure
9
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
23
state, so we can handle it by emulating execution of that
10
Message-id: 20200313014551.12554-5-linux@roeck-us.net
24
instruction directly in arm_v7m_cpu_do_interrupt(), which
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
means we can treat all the mismatch cases as "throw an
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
exception" and we don't need to encode the state of the
13
---
27
other MPU bank into our mmu_idx values.
14
include/hw/arm/fsl-imx6ul.h | 10 ++++++++++
15
hw/arm/fsl-imx6ul.c | 35 +++++++++++++++++++++++++++++++++++
16
2 files changed, 45 insertions(+)
28
17
29
This commit doesn't include the actual emulation of SG;
18
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
30
it also doesn't include implementation of the IDAU, which
31
is a per-board way to specify hard-coded memory attributes
32
for addresses, which override the CPU-internal SAU if they
33
specify a more secure setting than the SAU is programmed to.
34
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
37
Message-id: 1506092407-26985-15-git-send-email-peter.maydell@linaro.org
38
---
39
target/arm/internals.h | 15 ++++
40
target/arm/helper.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++-
41
2 files changed, 195 insertions(+), 2 deletions(-)
42
43
diff --git a/target/arm/internals.h b/target/arm/internals.h
44
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/internals.h
20
--- a/include/hw/arm/fsl-imx6ul.h
46
+++ b/target/arm/internals.h
21
+++ b/include/hw/arm/fsl-imx6ul.h
47
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_EXCRET, DCRS, 5, 1)
22
@@ -XXX,XX +XXX,XX @@
48
FIELD(V7M_EXCRET, S, 6, 1)
23
#include "hw/sd/sdhci.h"
49
FIELD(V7M_EXCRET, RES1, 7, 25) /* including the must-be-1 prefix */
24
#include "hw/ssi/imx_spi.h"
50
25
#include "hw/net/imx_fec.h"
51
+/* We use a few fake FSR values for internal purposes in M profile.
26
+#include "hw/usb/chipidea.h"
52
+ * M profile cores don't have A/R format FSRs, but currently our
27
+#include "hw/usb/imx-usb-phy.h"
53
+ * get_phys_addr() code assumes A/R profile and reports failures via
28
#include "exec/memory.h"
54
+ * an A/R format FSR value. We then translate that into the proper
29
#include "cpu.h"
55
+ * M profile exception and FSR status bit in arm_v7m_cpu_do_interrupt().
30
56
+ * Mostly the FSR values we use for this are those defined for v7PMSA,
31
@@ -XXX,XX +XXX,XX @@ enum FslIMX6ULConfiguration {
57
+ * since we share some of that codepath. A few kinds of fault are
32
FSL_IMX6UL_NUM_I2CS = 4,
58
+ * only for M profile and have no A/R equivalent, though, so we have
33
FSL_IMX6UL_NUM_ECSPIS = 4,
59
+ * to pick a value from the reserved range (which we never otherwise
34
FSL_IMX6UL_NUM_ADCS = 2,
60
+ * generate) to use for these.
35
+ FSL_IMX6UL_NUM_USB_PHYS = 2,
61
+ * These values will never be visible to the guest.
36
+ FSL_IMX6UL_NUM_USBS = 2,
62
+ */
37
};
63
+#define M_FAKE_FSR_NSC_EXEC 0xf /* NS executing in S&NSC memory */
38
64
+#define M_FAKE_FSR_SFAULT 0xe /* SecureFault INVTRAN, INVEP or AUVIOL */
39
typedef struct FslIMX6ULState {
65
+
40
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX6ULState {
66
/*
41
IMXFECState eth[FSL_IMX6UL_NUM_ETHS];
67
* For AArch64, map a given EL to an index in the banked_spsr array.
42
SDHCIState usdhc[FSL_IMX6UL_NUM_USDHCS];
68
* Note that this mapping and the AArch32 mapping defined in bank_number()
43
IMX2WdtState wdt[FSL_IMX6UL_NUM_WDTS];
69
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
+ IMXUSBPHYState usbphy[FSL_IMX6UL_NUM_USB_PHYS];
45
+ ChipideaState usb[FSL_IMX6UL_NUM_USBS];
46
MemoryRegion rom;
47
MemoryRegion caam;
48
MemoryRegion ocram;
49
@@ -XXX,XX +XXX,XX @@ enum FslIMX6ULMemoryMap {
50
FSL_IMX6UL_EPIT2_ADDR = 0x020D4000,
51
FSL_IMX6UL_EPIT1_ADDR = 0x020D0000,
52
FSL_IMX6UL_SNVS_HP_ADDR = 0x020CC000,
53
+ FSL_IMX6UL_USBPHY2_ADDR = 0x020CA000,
54
+ FSL_IMX6UL_USBPHY2_SIZE = (4 * 1024),
55
+ FSL_IMX6UL_USBPHY1_ADDR = 0x020C9000,
56
+ FSL_IMX6UL_USBPHY1_SIZE = (4 * 1024),
57
FSL_IMX6UL_ANALOG_ADDR = 0x020C8000,
58
FSL_IMX6UL_CCM_ADDR = 0x020C4000,
59
FSL_IMX6UL_WDOG2_ADDR = 0x020C0000,
60
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
70
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/helper.c
62
--- a/hw/arm/fsl-imx6ul.c
72
+++ b/target/arm/helper.c
63
+++ b/hw/arm/fsl-imx6ul.c
73
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
64
@@ -XXX,XX +XXX,XX @@
74
target_ulong *page_size_ptr, uint32_t *fsr,
65
#include "qapi/error.h"
75
ARMMMUFaultInfo *fi);
66
#include "hw/arm/fsl-imx6ul.h"
76
67
#include "hw/misc/unimp.h"
77
+/* Security attributes for an address, as returned by v8m_security_lookup. */
68
+#include "hw/usb/imx-usb-phy.h"
78
+typedef struct V8M_SAttributes {
69
#include "hw/boards.h"
79
+ bool ns;
70
#include "sysemu/sysemu.h"
80
+ bool nsc;
71
#include "qemu/error-report.h"
81
+ uint8_t sregion;
72
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
82
+ bool srvalid;
73
TYPE_IMX_ENET);
83
+ uint8_t iregion;
74
}
84
+ bool irvalid;
75
85
+} V8M_SAttributes;
76
+ /* USB */
86
+
77
+ for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) {
87
/* Definitions for the PMCCNTR and PMCR registers */
78
+ snprintf(name, NAME_SIZE, "usbphy%d", i);
88
#define PMCRD 0x8
79
+ sysbus_init_child_obj(obj, name, &s->usbphy[i], sizeof(s->usbphy[i]),
89
#define PMCRC 0x4
80
+ TYPE_IMX_USBPHY);
90
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
81
+ }
91
* raises the fault, in the A profile short-descriptor format.
82
+ for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) {
92
*/
83
+ snprintf(name, NAME_SIZE, "usb%d", i);
93
switch (env->exception.fsr & 0xf) {
84
+ sysbus_init_child_obj(obj, name, &s->usb[i], sizeof(s->usb[i]),
94
+ case M_FAKE_FSR_NSC_EXEC:
85
+ TYPE_CHIPIDEA);
95
+ /* Exception generated when we try to execute code at an address
96
+ * which is marked as Secure & Non-Secure Callable and the CPU
97
+ * is in the Non-Secure state. The only instruction which can
98
+ * be executed like this is SG (and that only if both halves of
99
+ * the SG instruction have the same security attributes.)
100
+ * Everything else must generate an INVEP SecureFault, so we
101
+ * emulate the SG instruction here.
102
+ * TODO: actually emulate SG.
103
+ */
104
+ env->v7m.sfsr |= R_V7M_SFSR_INVEP_MASK;
105
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
106
+ qemu_log_mask(CPU_LOG_INT,
107
+ "...really SecureFault with SFSR.INVEP\n");
108
+ break;
109
+ case M_FAKE_FSR_SFAULT:
110
+ /* Various flavours of SecureFault for attempts to execute or
111
+ * access data in the wrong security state.
112
+ */
113
+ switch (cs->exception_index) {
114
+ case EXCP_PREFETCH_ABORT:
115
+ if (env->v7m.secure) {
116
+ env->v7m.sfsr |= R_V7M_SFSR_INVTRAN_MASK;
117
+ qemu_log_mask(CPU_LOG_INT,
118
+ "...really SecureFault with SFSR.INVTRAN\n");
119
+ } else {
120
+ env->v7m.sfsr |= R_V7M_SFSR_INVEP_MASK;
121
+ qemu_log_mask(CPU_LOG_INT,
122
+ "...really SecureFault with SFSR.INVEP\n");
123
+ }
124
+ break;
125
+ case EXCP_DATA_ABORT:
126
+ /* This must be an NS access to S memory */
127
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK;
128
+ qemu_log_mask(CPU_LOG_INT,
129
+ "...really SecureFault with SFSR.AUVIOL\n");
130
+ break;
131
+ }
132
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
133
+ break;
134
case 0x8: /* External Abort */
135
switch (cs->exception_index) {
136
case EXCP_PREFETCH_ABORT:
137
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
138
return !(*prot & (1 << access_type));
139
}
140
141
+static bool v8m_is_sau_exempt(CPUARMState *env,
142
+ uint32_t address, MMUAccessType access_type)
143
+{
144
+ /* The architecture specifies that certain address ranges are
145
+ * exempt from v8M SAU/IDAU checks.
146
+ */
147
+ return
148
+ (access_type == MMU_INST_FETCH && m_is_system_region(env, address)) ||
149
+ (address >= 0xe0000000 && address <= 0xe0002fff) ||
150
+ (address >= 0xe000e000 && address <= 0xe000efff) ||
151
+ (address >= 0xe002e000 && address <= 0xe002efff) ||
152
+ (address >= 0xe0040000 && address <= 0xe0041fff) ||
153
+ (address >= 0xe00ff000 && address <= 0xe00fffff);
154
+}
155
+
156
+static void v8m_security_lookup(CPUARMState *env, uint32_t address,
157
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
158
+ V8M_SAttributes *sattrs)
159
+{
160
+ /* Look up the security attributes for this address. Compare the
161
+ * pseudocode SecurityCheck() function.
162
+ * We assume the caller has zero-initialized *sattrs.
163
+ */
164
+ ARMCPU *cpu = arm_env_get_cpu(env);
165
+ int r;
166
+
167
+ /* TODO: implement IDAU */
168
+
169
+ if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
170
+ /* 0xf0000000..0xffffffff is always S for insn fetches */
171
+ return;
172
+ }
86
+ }
173
+
87
+
174
+ if (v8m_is_sau_exempt(env, address, access_type)) {
88
/*
175
+ sattrs->ns = !regime_is_secure(env, mmu_idx);
89
* SDHCI
176
+ return;
90
*/
91
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
92
FSL_IMX6UL_ENETn_TIMER_IRQ[i]));
93
}
94
95
+ /* USB */
96
+ for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) {
97
+ object_property_set_bool(OBJECT(&s->usbphy[i]), true, "realized",
98
+ &error_abort);
99
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usbphy[i]), 0,
100
+ FSL_IMX6UL_USBPHY1_ADDR + i * 0x1000);
177
+ }
101
+ }
178
+
102
+
179
+ switch (env->sau.ctrl & 3) {
103
+ for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) {
180
+ case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
104
+ static const int FSL_IMX6UL_USBn_IRQ[] = {
181
+ break;
105
+ FSL_IMX6UL_USB1_IRQ,
182
+ case 2: /* SAU.ENABLE == 0, SAU.ALLNS == 1 */
106
+ FSL_IMX6UL_USB2_IRQ,
183
+ sattrs->ns = true;
107
+ };
184
+ break;
108
+ object_property_set_bool(OBJECT(&s->usb[i]), true, "realized",
185
+ default: /* SAU.ENABLE == 1 */
109
+ &error_abort);
186
+ for (r = 0; r < cpu->sau_sregion; r++) {
110
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0,
187
+ if (env->sau.rlar[r] & 1) {
111
+ FSL_IMX6UL_USBO2_USB_ADDR + i * 0x200);
188
+ uint32_t base = env->sau.rbar[r] & ~0x1f;
112
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
189
+ uint32_t limit = env->sau.rlar[r] | 0x1f;
113
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
190
+
114
+ FSL_IMX6UL_USBn_IRQ[i]));
191
+ if (base <= address && limit >= address) {
192
+ if (sattrs->srvalid) {
193
+ /* If we hit in more than one region then we must report
194
+ * as Secure, not NS-Callable, with no valid region
195
+ * number info.
196
+ */
197
+ sattrs->ns = false;
198
+ sattrs->nsc = false;
199
+ sattrs->sregion = 0;
200
+ sattrs->srvalid = false;
201
+ break;
202
+ } else {
203
+ if (env->sau.rlar[r] & 2) {
204
+ sattrs->nsc = true;
205
+ } else {
206
+ sattrs->ns = true;
207
+ }
208
+ sattrs->srvalid = true;
209
+ sattrs->sregion = r;
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ /* TODO when we support the IDAU then it may override the result here */
216
+ break;
217
+ }
218
+}
219
+
220
static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
221
MMUAccessType access_type, ARMMMUIdx mmu_idx,
222
- hwaddr *phys_ptr, int *prot, uint32_t *fsr)
223
+ hwaddr *phys_ptr, MemTxAttrs *txattrs,
224
+ int *prot, uint32_t *fsr)
225
{
226
ARMCPU *cpu = arm_env_get_cpu(env);
227
bool is_user = regime_is_user(env, mmu_idx);
228
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
229
int n;
230
int matchregion = -1;
231
bool hit = false;
232
+ V8M_SAttributes sattrs = {};
233
234
*phys_ptr = address;
235
*prot = 0;
236
237
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
238
+ v8m_security_lookup(env, address, access_type, mmu_idx, &sattrs);
239
+ if (access_type == MMU_INST_FETCH) {
240
+ /* Instruction fetches always use the MMU bank and the
241
+ * transaction attribute determined by the fetch address,
242
+ * regardless of CPU state. This is painful for QEMU
243
+ * to handle, because it would mean we need to encode
244
+ * into the mmu_idx not just the (user, negpri) information
245
+ * for the current security state but also that for the
246
+ * other security state, which would balloon the number
247
+ * of mmu_idx values needed alarmingly.
248
+ * Fortunately we can avoid this because it's not actually
249
+ * possible to arbitrarily execute code from memory with
250
+ * the wrong security attribute: it will always generate
251
+ * an exception of some kind or another, apart from the
252
+ * special case of an NS CPU executing an SG instruction
253
+ * in S&NSC memory. So we always just fail the translation
254
+ * here and sort things out in the exception handler
255
+ * (including possibly emulating an SG instruction).
256
+ */
257
+ if (sattrs.ns != !secure) {
258
+ *fsr = sattrs.nsc ? M_FAKE_FSR_NSC_EXEC : M_FAKE_FSR_SFAULT;
259
+ return true;
260
+ }
261
+ } else {
262
+ /* For data accesses we always use the MMU bank indicated
263
+ * by the current CPU state, but the security attributes
264
+ * might downgrade a secure access to nonsecure.
265
+ */
266
+ if (sattrs.ns) {
267
+ txattrs->secure = false;
268
+ } else if (!secure) {
269
+ /* NS access to S memory must fault.
270
+ * Architecturally we should first check whether the
271
+ * MPU information for this address indicates that we
272
+ * are doing an unaligned access to Device memory, which
273
+ * should generate a UsageFault instead. QEMU does not
274
+ * currently check for that kind of unaligned access though.
275
+ * If we added it we would need to do so as a special case
276
+ * for M_FAKE_FSR_SFAULT in arm_v7m_cpu_do_interrupt().
277
+ */
278
+ *fsr = M_FAKE_FSR_SFAULT;
279
+ return true;
280
+ }
281
+ }
282
+ }
115
+ }
283
+
116
+
284
/* Unlike the ARM ARM pseudocode, we don't need to check whether this
117
/*
285
* was an exception vector read from the vector table (which is always
118
* USDHC
286
* done using the default system address map), because those accesses
119
*/
287
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
288
if (arm_feature(env, ARM_FEATURE_V8)) {
289
/* PMSAv8 */
290
ret = get_phys_addr_pmsav8(env, address, access_type, mmu_idx,
291
- phys_ptr, prot, fsr);
292
+ phys_ptr, attrs, prot, fsr);
293
} else if (arm_feature(env, ARM_FEATURE_V7)) {
294
/* PMSAv7 */
295
ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
296
--
120
--
297
2.7.4
121
2.20.1
298
122
299
123
diff view generated by jsdifflib
1
Implement the register interface for the SAU: SAU_CTRL,
1
From: Guenter Roeck <linux@roeck-us.net>
2
SAU_TYPE, SAU_RNR, SAU_RBAR and SAU_RLAR. None of the
3
actual behaviour is implemented here; registers just
4
read back as written.
5
2
6
When the CPU definition for Cortex-M33 is eventually
3
With this patch, the USB controllers on 'sabrelite' are detected
7
added, its initfn will set cpu->sau_sregion, in the same
4
and can be used to boot the system.
8
way that we currently set cpu->pmsav7_dregion for the
9
M3 and M4.
10
5
11
Number of SAU regions is typically a configurable
6
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
12
CPU parameter, but this patch doesn't provide a
7
Message-id: 20200313014551.12554-6-linux@roeck-us.net
13
QEMU CPU property for it. We can easily add one when
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
we have a board that requires it.
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/fsl-imx6.h | 6 ++++++
12
hw/arm/fsl-imx6.c | 36 ++++++++++++++++++++++++++++++++++++
13
2 files changed, 42 insertions(+)
15
14
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 1506092407-26985-14-git-send-email-peter.maydell@linaro.org
19
---
20
target/arm/cpu.h | 10 +++++
21
hw/intc/armv7m_nvic.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++
22
target/arm/cpu.c | 27 ++++++++++++
23
target/arm/machine.c | 14 ++++++
24
4 files changed, 167 insertions(+)
25
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
17
--- a/include/hw/arm/fsl-imx6.h
29
+++ b/target/arm/cpu.h
18
+++ b/include/hw/arm/fsl-imx6.h
30
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
19
@@ -XXX,XX +XXX,XX @@
31
uint32_t mair1[M_REG_NUM_BANKS];
20
#include "hw/sd/sdhci.h"
32
} pmsav8;
21
#include "hw/ssi/imx_spi.h"
33
22
#include "hw/net/imx_fec.h"
34
+ /* v8M SAU */
23
+#include "hw/usb/chipidea.h"
35
+ struct {
24
+#include "hw/usb/imx-usb-phy.h"
36
+ uint32_t *rbar;
25
#include "exec/memory.h"
37
+ uint32_t *rlar;
26
#include "cpu.h"
38
+ uint32_t rnr;
27
39
+ uint32_t ctrl;
28
@@ -XXX,XX +XXX,XX @@
40
+ } sau;
29
#define FSL_IMX6_NUM_ESDHCS 4
41
+
30
#define FSL_IMX6_NUM_ECSPIS 5
42
void *nvic;
31
#define FSL_IMX6_NUM_WDTS 2
43
const struct arm_boot_info *boot_info;
32
+#define FSL_IMX6_NUM_USB_PHYS 2
44
/* Store GICv3CPUState to access from this struct */
33
+#define FSL_IMX6_NUM_USBS 4
45
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
34
46
bool has_mpu;
35
typedef struct FslIMX6State {
47
/* PMSAv7 MPU number of supported regions */
36
/*< private >*/
48
uint32_t pmsav7_dregion;
37
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX6State {
49
+ /* v8M SAU number of supported regions */
38
SDHCIState esdhc[FSL_IMX6_NUM_ESDHCS];
50
+ uint32_t sau_sregion;
39
IMXSPIState spi[FSL_IMX6_NUM_ECSPIS];
51
40
IMX2WdtState wdt[FSL_IMX6_NUM_WDTS];
52
/* PSCI conduit used to invoke PSCI methods
41
+ IMXUSBPHYState usbphy[FSL_IMX6_NUM_USB_PHYS];
53
* 0 - disabled, 1 - smc, 2 - hvc
42
+ ChipideaState usb[FSL_IMX6_NUM_USBS];
54
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
43
IMXFECState eth;
44
MemoryRegion rom;
45
MemoryRegion caam;
46
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
55
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/intc/armv7m_nvic.c
48
--- a/hw/arm/fsl-imx6.c
57
+++ b/hw/intc/armv7m_nvic.c
49
+++ b/hw/arm/fsl-imx6.c
58
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
50
@@ -XXX,XX +XXX,XX @@
59
goto bad_offset;
51
#include "qemu/osdep.h"
60
}
52
#include "qapi/error.h"
61
return cpu->env.pmsav8.mair1[attrs.secure];
53
#include "hw/arm/fsl-imx6.h"
62
+ case 0xdd0: /* SAU_CTRL */
54
+#include "hw/usb/imx-usb-phy.h"
63
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
55
#include "hw/boards.h"
64
+ goto bad_offset;
56
#include "hw/qdev-properties.h"
65
+ }
57
#include "sysemu/sysemu.h"
66
+ if (!attrs.secure) {
58
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6_init(Object *obj)
67
+ return 0;
59
TYPE_IMX_USDHC);
68
+ }
60
}
69
+ return cpu->env.sau.ctrl;
61
70
+ case 0xdd4: /* SAU_TYPE */
62
+ for (i = 0; i < FSL_IMX6_NUM_USB_PHYS; i++) {
71
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
63
+ snprintf(name, NAME_SIZE, "usbphy%d", i);
72
+ goto bad_offset;
64
+ sysbus_init_child_obj(obj, name, &s->usbphy[i], sizeof(s->usbphy[i]),
73
+ }
65
+ TYPE_IMX_USBPHY);
74
+ if (!attrs.secure) {
75
+ return 0;
76
+ }
77
+ return cpu->sau_sregion;
78
+ case 0xdd8: /* SAU_RNR */
79
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
80
+ goto bad_offset;
81
+ }
82
+ if (!attrs.secure) {
83
+ return 0;
84
+ }
85
+ return cpu->env.sau.rnr;
86
+ case 0xddc: /* SAU_RBAR */
87
+ {
88
+ int region = cpu->env.sau.rnr;
89
+
90
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
91
+ goto bad_offset;
92
+ }
93
+ if (!attrs.secure) {
94
+ return 0;
95
+ }
96
+ if (region >= cpu->sau_sregion) {
97
+ return 0;
98
+ }
99
+ return cpu->env.sau.rbar[region];
100
+ }
66
+ }
101
+ case 0xde0: /* SAU_RLAR */
67
+ for (i = 0; i < FSL_IMX6_NUM_USBS; i++) {
102
+ {
68
+ snprintf(name, NAME_SIZE, "usb%d", i);
103
+ int region = cpu->env.sau.rnr;
69
+ sysbus_init_child_obj(obj, name, &s->usb[i], sizeof(s->usb[i]),
104
+
70
+ TYPE_CHIPIDEA);
105
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
106
+ goto bad_offset;
107
+ }
108
+ if (!attrs.secure) {
109
+ return 0;
110
+ }
111
+ if (region >= cpu->sau_sregion) {
112
+ return 0;
113
+ }
114
+ return cpu->env.sau.rlar[region];
115
+ }
116
case 0xde4: /* SFSR */
117
if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
118
goto bad_offset;
119
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
120
* only affect cacheability, and we don't implement caching.
121
*/
122
break;
123
+ case 0xdd0: /* SAU_CTRL */
124
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
125
+ goto bad_offset;
126
+ }
127
+ if (!attrs.secure) {
128
+ return;
129
+ }
130
+ cpu->env.sau.ctrl = value & 3;
131
+ case 0xdd4: /* SAU_TYPE */
132
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
133
+ goto bad_offset;
134
+ }
135
+ break;
136
+ case 0xdd8: /* SAU_RNR */
137
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
138
+ goto bad_offset;
139
+ }
140
+ if (!attrs.secure) {
141
+ return;
142
+ }
143
+ if (value >= cpu->sau_sregion) {
144
+ qemu_log_mask(LOG_GUEST_ERROR, "SAU region out of range %"
145
+ PRIu32 "/%" PRIu32 "\n",
146
+ value, cpu->sau_sregion);
147
+ } else {
148
+ cpu->env.sau.rnr = value;
149
+ }
150
+ break;
151
+ case 0xddc: /* SAU_RBAR */
152
+ {
153
+ int region = cpu->env.sau.rnr;
154
+
155
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
156
+ goto bad_offset;
157
+ }
158
+ if (!attrs.secure) {
159
+ return;
160
+ }
161
+ if (region >= cpu->sau_sregion) {
162
+ return;
163
+ }
164
+ cpu->env.sau.rbar[region] = value & ~0x1f;
165
+ tlb_flush(CPU(cpu));
166
+ break;
167
+ }
168
+ case 0xde0: /* SAU_RLAR */
169
+ {
170
+ int region = cpu->env.sau.rnr;
171
+
172
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
173
+ goto bad_offset;
174
+ }
175
+ if (!attrs.secure) {
176
+ return;
177
+ }
178
+ if (region >= cpu->sau_sregion) {
179
+ return;
180
+ }
181
+ cpu->env.sau.rlar[region] = value & ~0x1c;
182
+ tlb_flush(CPU(cpu));
183
+ break;
184
+ }
185
case 0xde4: /* SFSR */
186
if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
187
goto bad_offset;
188
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
189
index XXXXXXX..XXXXXXX 100644
190
--- a/target/arm/cpu.c
191
+++ b/target/arm/cpu.c
192
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
193
env->pmsav8.mair1[M_REG_S] = 0;
194
}
195
196
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
197
+ if (cpu->sau_sregion > 0) {
198
+ memset(env->sau.rbar, 0, sizeof(*env->sau.rbar) * cpu->sau_sregion);
199
+ memset(env->sau.rlar, 0, sizeof(*env->sau.rlar) * cpu->sau_sregion);
200
+ }
201
+ env->sau.rnr = 0;
202
+ /* SAU_CTRL reset value is IMPDEF; we choose 0, which is what
203
+ * the Cortex-M33 does.
204
+ */
205
+ env->sau.ctrl = 0;
206
+ }
71
+ }
207
+
72
+
208
set_flush_to_zero(1, &env->vfp.standard_fp_status);
73
for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) {
209
set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
74
snprintf(name, NAME_SIZE, "spi%d", i + 1);
210
set_default_nan_mode(1, &env->vfp.standard_fp_status);
75
sysbus_init_child_obj(obj, name, &s->spi[i], sizeof(s->spi[i]),
211
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
76
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
212
}
77
esdhc_table[i].irq));
213
}
78
}
214
79
215
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
80
+ /* USB */
216
+ uint32_t nr = cpu->sau_sregion;
81
+ for (i = 0; i < FSL_IMX6_NUM_USB_PHYS; i++) {
82
+ object_property_set_bool(OBJECT(&s->usbphy[i]), true, "realized",
83
+ &error_abort);
84
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usbphy[i]), 0,
85
+ FSL_IMX6_USBPHY1_ADDR + i * 0x1000);
86
+ }
87
+ for (i = 0; i < FSL_IMX6_NUM_USBS; i++) {
88
+ static const int FSL_IMX6_USBn_IRQ[] = {
89
+ FSL_IMX6_USB_OTG_IRQ,
90
+ FSL_IMX6_USB_HOST1_IRQ,
91
+ FSL_IMX6_USB_HOST2_IRQ,
92
+ FSL_IMX6_USB_HOST3_IRQ,
93
+ };
217
+
94
+
218
+ if (nr > 0xff) {
95
+ object_property_set_bool(OBJECT(&s->usb[i]), true, "realized",
219
+ error_setg(errp, "v8M SAU #regions invalid %" PRIu32, nr);
96
+ &error_abort);
220
+ return;
97
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0,
221
+ }
98
+ FSL_IMX6_USBOH3_USB_ADDR + i * 0x200);
222
+
99
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
223
+ if (nr) {
100
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
224
+ env->sau.rbar = g_new0(uint32_t, nr);
101
+ FSL_IMX6_USBn_IRQ[i]));
225
+ env->sau.rlar = g_new0(uint32_t, nr);
226
+ }
227
+ }
102
+ }
228
+
103
+
229
if (arm_feature(env, ARM_FEATURE_EL3)) {
104
/* Initialize all ECSPI */
230
set_feature(env, ARM_FEATURE_VBAR);
105
for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) {
231
}
106
static const struct {
232
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
233
cpu->midr = 0x410fc240; /* r0p0 */
234
cpu->pmsav7_dregion = 8;
235
}
236
+
237
static void arm_v7m_class_init(ObjectClass *oc, void *data)
238
{
239
CPUClass *cc = CPU_CLASS(oc);
240
diff --git a/target/arm/machine.c b/target/arm/machine.c
241
index XXXXXXX..XXXXXXX 100644
242
--- a/target/arm/machine.c
243
+++ b/target/arm/machine.c
244
@@ -XXX,XX +XXX,XX @@ static bool s_rnr_vmstate_validate(void *opaque, int version_id)
245
return cpu->env.pmsav7.rnr[M_REG_S] < cpu->pmsav7_dregion;
246
}
247
248
+static bool sau_rnr_vmstate_validate(void *opaque, int version_id)
249
+{
250
+ ARMCPU *cpu = opaque;
251
+
252
+ return cpu->env.sau.rnr < cpu->sau_sregion;
253
+}
254
+
255
static bool m_security_needed(void *opaque)
256
{
257
ARMCPU *cpu = opaque;
258
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
259
VMSTATE_UINT32(env.v7m.cfsr[M_REG_S], ARMCPU),
260
VMSTATE_UINT32(env.v7m.sfsr, ARMCPU),
261
VMSTATE_UINT32(env.v7m.sfar, ARMCPU),
262
+ VMSTATE_VARRAY_UINT32(env.sau.rbar, ARMCPU, sau_sregion, 0,
263
+ vmstate_info_uint32, uint32_t),
264
+ VMSTATE_VARRAY_UINT32(env.sau.rlar, ARMCPU, sau_sregion, 0,
265
+ vmstate_info_uint32, uint32_t),
266
+ VMSTATE_UINT32(env.sau.rnr, ARMCPU),
267
+ VMSTATE_VALIDATE("SAU_RNR is valid", sau_rnr_vmstate_validate),
268
+ VMSTATE_UINT32(env.sau.ctrl, ARMCPU),
269
VMSTATE_END_OF_LIST()
270
}
271
};
272
--
107
--
273
2.7.4
108
2.20.1
274
109
275
110
diff view generated by jsdifflib
1
In cpu_mmu_index() we try to do this:
1
From: Chen Qun <kuhn.chenqun@huawei.com>
2
if (env->v7m.secure) {
3
mmu_idx += ARMMMUIdx_MSUser;
4
}
5
but it will give the wrong answer, because ARMMMUIdx_MSUser
6
includes the 0x40 ARM_MMU_IDX_M field, and so does the
7
mmu_idx we're adding to, and we'll end up with 0x8n rather
8
than 0x4n. This error is then nullified by the call to
9
arm_to_core_mmu_idx() which masks out the high part, but
10
we're about to factor out the code that calculates the
11
ARMMMUIdx values so it can be used without passing it through
12
arm_to_core_mmu_idx(), so fix this bug first.
13
2
3
The current code causes clang static code analyzer generate warning:
4
hw/net/imx_fec.c:858:9: warning: Value stored to 'value' is never read
5
value = value & 0x0000000f;
6
^ ~~~~~~~~~~~~~~~~~~
7
hw/net/imx_fec.c:864:9: warning: Value stored to 'value' is never read
8
value = value & 0x000000fd;
9
^ ~~~~~~~~~~~~~~~~~~
10
11
According to the definition of the function, the two “value” assignments
12
should be written to registers.
13
14
Reported-by: Euler Robot <euler.robot@huawei.com>
15
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
16
Message-id: 20200313123242.13236-1-kuhn.chenqun@huawei.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 1506092407-26985-16-git-send-email-peter.maydell@linaro.org
18
---
19
---
19
target/arm/cpu.h | 12 +++++++-----
20
hw/net/imx_fec.c | 6 ++++--
20
1 file changed, 7 insertions(+), 5 deletions(-)
21
1 file changed, 4 insertions(+), 2 deletions(-)
21
22
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
23
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
25
--- a/hw/net/imx_fec.c
25
+++ b/target/arm/cpu.h
26
+++ b/hw/net/imx_fec.c
26
@@ -XXX,XX +XXX,XX @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
27
@@ -XXX,XX +XXX,XX @@ static void imx_enet_write(IMXFECState *s, uint32_t index, uint32_t value)
27
int el = arm_current_el(env);
28
break;
28
29
case ENET_TGSR:
29
if (arm_feature(env, ARM_FEATURE_M)) {
30
/* implement clear timer flag */
30
- ARMMMUIdx mmu_idx = el == 0 ? ARMMMUIdx_MUser : ARMMMUIdx_MPriv;
31
- value = value & 0x0000000f;
31
+ ARMMMUIdx mmu_idx;
32
+ s->regs[index] &= ~(value & 0x0000000f); /* all bits W1C */
32
33
break;
33
- if (armv7m_nvic_neg_prio_requested(env->nvic, env->v7m.secure)) {
34
case ENET_TCSR0:
34
- mmu_idx = ARMMMUIdx_MNegPri;
35
case ENET_TCSR1:
35
+ if (el == 0) {
36
case ENET_TCSR2:
36
+ mmu_idx = env->v7m.secure ? ARMMMUIdx_MSUser : ARMMMUIdx_MUser;
37
case ENET_TCSR3:
37
+ } else {
38
- value = value & 0x000000fd;
38
+ mmu_idx = env->v7m.secure ? ARMMMUIdx_MSPriv : ARMMMUIdx_MPriv;
39
+ s->regs[index] &= ~(value & 0x00000080); /* W1C bits */
39
}
40
+ s->regs[index] &= ~0x0000007d; /* writable fields */
40
41
+ s->regs[index] |= (value & 0x0000007d);
41
- if (env->v7m.secure) {
42
break;
42
- mmu_idx += ARMMMUIdx_MSUser;
43
case ENET_TCCR0:
43
+ if (armv7m_nvic_neg_prio_requested(env->nvic, env->v7m.secure)) {
44
case ENET_TCCR1:
44
+ mmu_idx = env->v7m.secure ? ARMMMUIdx_MSNegPri : ARMMMUIdx_MNegPri;
45
}
46
47
return arm_to_core_mmu_idx(mmu_idx);
48
--
45
--
49
2.7.4
46
2.20.1
50
47
51
48
diff view generated by jsdifflib
1
In v8M, more bits are defined in the exception-return magic
1
From: Guenter Roeck <linux@roeck-us.net>
2
values; update the code that checks these so we accept
3
the v8M values when the CPU permits them.
4
2
3
While at it, add some trace messages to help debug problems
4
seen when running the latest Linux kernel.
5
6
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Cédric Le Goater <clg@kaod.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 1506092407-26985-11-git-send-email-peter.maydell@linaro.org
8
---
11
---
9
target/arm/helper.c | 73 ++++++++++++++++++++++++++++++++++++++++++-----------
12
hw/block/m25p80.c | 48 ++++++++++++++++++++-----------------------
10
1 file changed, 58 insertions(+), 15 deletions(-)
13
hw/block/trace-events | 16 +++++++++++++++
14
2 files changed, 38 insertions(+), 26 deletions(-)
11
15
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
18
--- a/hw/block/m25p80.c
15
+++ b/target/arm/helper.c
19
+++ b/hw/block/m25p80.c
16
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
20
@@ -XXX,XX +XXX,XX @@
17
uint32_t excret;
21
#include "qemu/module.h"
18
uint32_t xpsr;
22
#include "qemu/error-report.h"
19
bool ufault = false;
23
#include "qapi/error.h"
20
- bool return_to_sp_process = false;
24
-
21
- bool return_to_handler = false;
25
-#ifndef M25P80_ERR_DEBUG
22
+ bool sfault = false;
26
-#define M25P80_ERR_DEBUG 0
23
+ bool return_to_sp_process;
27
-#endif
24
+ bool return_to_handler;
28
-
25
bool rettobase = false;
29
-#define DB_PRINT_L(level, ...) do { \
26
bool exc_secure = false;
30
- if (M25P80_ERR_DEBUG > (level)) { \
27
bool return_to_secure;
31
- fprintf(stderr, ": %s: ", __func__); \
28
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
32
- fprintf(stderr, ## __VA_ARGS__); \
29
excret);
33
- } \
34
-} while (0)
35
+#include "trace.h"
36
37
/* Fields for FlashPartInfo->flags */
38
39
@@ -XXX,XX +XXX,XX @@ static void flash_erase(Flash *s, int offset, FlashCMD cmd)
40
abort();
30
}
41
}
31
42
32
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
43
- DB_PRINT_L(0, "offset = %#x, len = %d\n", offset, len);
33
+ /* EXC_RETURN.ES validation check (R_SMFL). We must do this before
44
+ trace_m25p80_flash_erase(s, offset, len);
34
+ * we pick which FAULTMASK to clear.
35
+ */
36
+ if (!env->v7m.secure &&
37
+ ((excret & R_V7M_EXCRET_ES_MASK) ||
38
+ !(excret & R_V7M_EXCRET_DCRS_MASK))) {
39
+ sfault = 1;
40
+ /* For all other purposes, treat ES as 0 (R_HXSR) */
41
+ excret &= ~R_V7M_EXCRET_ES_MASK;
42
+ }
43
+ }
44
+
45
+
45
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
46
if ((s->pi->flags & capa_to_assert) != capa_to_assert) {
46
/* Auto-clear FAULTMASK on return from other than NMI.
47
qemu_log_mask(LOG_GUEST_ERROR, "M25P80: %d erase size not supported by"
47
* If the security extension is implemented then this only
48
" device\n", len);
48
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
49
@@ -XXX,XX +XXX,XX @@ void flash_write8(Flash *s, uint32_t addr, uint8_t data)
49
g_assert_not_reached();
50
}
50
}
51
51
52
+ return_to_handler = !(excret & R_V7M_EXCRET_MODE_MASK);
52
if ((prev ^ data) & data) {
53
+ return_to_sp_process = excret & R_V7M_EXCRET_SPSEL_MASK;
53
- DB_PRINT_L(1, "programming zero to one! addr=%" PRIx32 " %" PRIx8
54
return_to_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
54
- " -> %" PRIx8 "\n", addr, prev, data);
55
(excret & R_V7M_EXCRET_S_MASK);
55
+ trace_m25p80_programming_zero_to_one(s, addr, prev, data);
56
56
}
57
- switch (excret & 0xf) {
57
58
- case 1: /* Return to Handler */
58
if (s->pi->flags & EEPROM) {
59
- return_to_handler = true;
59
@@ -XXX,XX +XXX,XX @@ static void complete_collecting_data(Flash *s)
60
- break;
60
61
- case 13: /* Return to Thread using Process stack */
61
s->state = STATE_IDLE;
62
- return_to_sp_process = true;
62
63
- /* fall through */
63
+ trace_m25p80_complete_collecting(s, s->cmd_in_progress, n, s->ear,
64
- case 9: /* Return to Thread using Main stack */
64
+ s->cur_addr);
65
- if (!rettobase &&
65
+
66
- !(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_NONBASETHRDENA_MASK)) {
66
switch (s->cmd_in_progress) {
67
+ if (arm_feature(env, ARM_FEATURE_V8)) {
67
case DPP:
68
+ if (!arm_feature(env, ARM_FEATURE_M_SECURITY)) {
68
case QPP:
69
+ /* UNPREDICTABLE if S == 1 or DCRS == 0 or ES == 1 (R_XLCP);
69
@@ -XXX,XX +XXX,XX @@ static void reset_memory(Flash *s)
70
+ * we choose to take the UsageFault.
70
break;
71
+ */
71
}
72
+ if ((excret & R_V7M_EXCRET_S_MASK) ||
72
73
+ (excret & R_V7M_EXCRET_ES_MASK) ||
73
- DB_PRINT_L(0, "Reset done.\n");
74
+ !(excret & R_V7M_EXCRET_DCRS_MASK)) {
74
+ trace_m25p80_reset_done(s);
75
+ ufault = true;
75
}
76
+ }
76
77
+ }
77
static void decode_fast_read_cmd(Flash *s)
78
+ if (excret & R_V7M_EXCRET_RES0_MASK) {
78
@@ -XXX,XX +XXX,XX @@ static void decode_qio_read_cmd(Flash *s)
79
ufault = true;
79
80
static void decode_new_cmd(Flash *s, uint32_t value)
81
{
82
- s->cmd_in_progress = value;
83
int i;
84
- DB_PRINT_L(0, "decoded new command:%x\n", value);
85
+
86
+ s->cmd_in_progress = value;
87
+ trace_m25p80_command_decoded(s, value);
88
89
if (value != RESET_MEMORY) {
90
s->reset_enable = false;
91
@@ -XXX,XX +XXX,XX @@ static void decode_new_cmd(Flash *s, uint32_t value)
92
break;
93
94
case JEDEC_READ:
95
- DB_PRINT_L(0, "populated jedec code\n");
96
+ trace_m25p80_populated_jedec(s);
97
for (i = 0; i < s->pi->id_len; i++) {
98
s->data[i] = s->pi->id[i];
80
}
99
}
81
- break;
100
@@ -XXX,XX +XXX,XX @@ static void decode_new_cmd(Flash *s, uint32_t value)
82
- default:
101
case BULK_ERASE_60:
83
- ufault = true;
102
case BULK_ERASE:
84
+ } else {
103
if (s->write_enable) {
85
+ /* For v7M we only recognize certain combinations of the low bits */
104
- DB_PRINT_L(0, "chip erase\n");
86
+ switch (excret & 0xf) {
105
+ trace_m25p80_chip_erase(s);
87
+ case 1: /* Return to Handler */
106
flash_erase(s, 0, BULK_ERASE);
88
+ break;
107
} else {
89
+ case 13: /* Return to Thread using Process stack */
108
qemu_log_mask(LOG_GUEST_ERROR, "M25P80: chip erase with write "
90
+ case 9: /* Return to Thread using Main stack */
109
@@ -XXX,XX +XXX,XX @@ static int m25p80_cs(SSISlave *ss, bool select)
91
+ /* We only need to check NONBASETHRDENA for v7M, because in
110
s->data_read_loop = false;
92
+ * v8M this bit does not exist (it is RES1).
111
}
93
+ */
112
94
+ if (!rettobase &&
113
- DB_PRINT_L(0, "%sselect\n", select ? "de" : "");
95
+ !(env->v7m.ccr[env->v7m.secure] &
114
+ trace_m25p80_select(s, select ? "de" : "");
96
+ R_V7M_CCR_NONBASETHRDENA_MASK)) {
115
97
+ ufault = true;
116
return 0;
98
+ }
117
}
99
+ break;
118
@@ -XXX,XX +XXX,XX @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
100
+ default:
119
Flash *s = M25P80(ss);
101
+ ufault = true;
120
uint32_t r = 0;
102
+ }
121
103
+ }
122
+ trace_m25p80_transfer(s, s->state, s->len, s->needed_bytes, s->pos,
123
+ s->cur_addr, (uint8_t)tx);
104
+
124
+
105
+ if (sfault) {
125
switch (s->state) {
106
+ env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
126
107
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
127
case STATE_PAGE_PROGRAM:
108
+ v7m_exception_taken(cpu, excret);
128
- DB_PRINT_L(1, "page program cur_addr=%#" PRIx32 " data=%" PRIx8 "\n",
109
+ qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
129
- s->cur_addr, (uint8_t)tx);
110
+ "stackframe: failed EXC_RETURN.ES validity check\n");
130
+ trace_m25p80_page_program(s, s->cur_addr, (uint8_t)tx);
111
+ return;
131
flash_write8(s, s->cur_addr, (uint8_t)tx);
132
s->cur_addr = (s->cur_addr + 1) & (s->size - 1);
133
break;
134
135
case STATE_READ:
136
r = s->storage[s->cur_addr];
137
- DB_PRINT_L(1, "READ 0x%" PRIx32 "=%" PRIx8 "\n", s->cur_addr,
138
- (uint8_t)r);
139
+ trace_m25p80_read_byte(s, s->cur_addr, (uint8_t)r);
140
s->cur_addr = (s->cur_addr + 1) & (s->size - 1);
141
break;
142
143
@@ -XXX,XX +XXX,XX @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
144
}
145
146
r = s->data[s->pos];
147
+ trace_m25p80_read_data(s, s->pos, (uint8_t)r);
148
s->pos++;
149
if (s->pos == s->len) {
150
s->pos = 0;
151
@@ -XXX,XX +XXX,XX @@ static void m25p80_realize(SSISlave *ss, Error **errp)
152
return;
153
}
154
155
- DB_PRINT_L(0, "Binding to IF_MTD drive\n");
156
+ trace_m25p80_binding(s);
157
s->storage = blk_blockalign(s->blk, s->size);
158
159
if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
160
@@ -XXX,XX +XXX,XX @@ static void m25p80_realize(SSISlave *ss, Error **errp)
161
return;
162
}
163
} else {
164
- DB_PRINT_L(0, "No BDRV - binding to RAM\n");
165
+ trace_m25p80_binding_no_bdrv(s);
166
s->storage = blk_blockalign(NULL, s->size);
167
memset(s->storage, 0xFF, s->size);
112
}
168
}
113
169
diff --git a/hw/block/trace-events b/hw/block/trace-events
114
if (ufault) {
170
index XXXXXXX..XXXXXXX 100644
171
--- a/hw/block/trace-events
172
+++ b/hw/block/trace-events
173
@@ -XXX,XX +XXX,XX @@ xen_block_blockdev_add(char *str) "%s"
174
xen_block_blockdev_del(const char *node_name) "%s"
175
xen_block_device_create(unsigned int number) "%u"
176
xen_block_device_destroy(unsigned int number) "%u"
177
+
178
+# m25p80.c
179
+m25p80_flash_erase(void *s, int offset, uint32_t len) "[%p] offset = 0x%"PRIx32", len = %u"
180
+m25p80_programming_zero_to_one(void *s, uint32_t addr, uint8_t prev, uint8_t data) "[%p] programming zero to one! addr=0x%"PRIx32" 0x%"PRIx8" -> 0x%"PRIx8
181
+m25p80_reset_done(void *s) "[%p] Reset done."
182
+m25p80_command_decoded(void *s, uint32_t cmd) "[%p] new command:0x%"PRIx32
183
+m25p80_complete_collecting(void *s, uint32_t cmd, int n, uint8_t ear, uint32_t cur_addr) "[%p] decode cmd: 0x%"PRIx32" len %d ear 0x%"PRIx8" addr 0x%"PRIx32
184
+m25p80_populated_jedec(void *s) "[%p] populated jedec code"
185
+m25p80_chip_erase(void *s) "[%p] chip erase"
186
+m25p80_select(void *s, const char *what) "[%p] %sselect"
187
+m25p80_page_program(void *s, uint32_t addr, uint8_t tx) "[%p] page program cur_addr=0x%"PRIx32" data=0x%"PRIx8
188
+m25p80_transfer(void *s, uint8_t state, uint32_t len, uint8_t needed, uint32_t pos, uint32_t cur_addr, uint8_t t) "[%p] Transfer state 0x%"PRIx8" len 0x%"PRIx32" needed 0x%"PRIx8" pos 0x%"PRIx32" addr 0x%"PRIx32" tx 0x%"PRIx8
189
+m25p80_read_byte(void *s, uint32_t addr, uint8_t v) "[%p] Read byte 0x%"PRIx32"=0x%"PRIx8
190
+m25p80_read_data(void *s, uint32_t pos, uint8_t v) "[%p] Read data 0x%"PRIx32"=0x%"PRIx8
191
+m25p80_binding(void *s) "[%p] Binding to IF_MTD drive"
192
+m25p80_binding_no_bdrv(void *s) "[%p] No BDRV - binding to RAM"
115
--
193
--
116
2.7.4
194
2.20.1
117
195
118
196
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
The device uses serial_hds in its realize function and thus can't be
3
When requesting JEDEC data using the JEDEC_READ command, the Linux kernel
4
used twice. Apart from that, the comma in its name makes it quite hard
4
always requests 6 bytes. The current implementation only returns three
5
to use for the user anyway, since a comma is normally used to separate
5
bytes, and interprets the remaining three bytes as new commands.
6
the device name from its properties when using the "-device" parameter
6
While this does not matter most of the time, it is at the very least
7
or the "device_add" HMP command.
7
confusing. To avoid the problem, always report up to 6 bytes of JEDEC
8
data. Fill remaining data with 0.
8
9
9
Signed-off-by: Thomas Huth <thuth@redhat.com>
10
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
10
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 1506441116-16627-1-git-send-email-thuth@redhat.com
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
15
---
14
hw/arm/xlnx-zynqmp.c | 2 ++
16
hw/block/m25p80.c | 5 ++++-
15
1 file changed, 2 insertions(+)
17
1 file changed, 4 insertions(+), 1 deletion(-)
16
18
17
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
19
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/xlnx-zynqmp.c
21
--- a/hw/block/m25p80.c
20
+++ b/hw/arm/xlnx-zynqmp.c
22
+++ b/hw/block/m25p80.c
21
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
23
@@ -XXX,XX +XXX,XX @@ static void decode_new_cmd(Flash *s, uint32_t value)
22
24
for (i = 0; i < s->pi->id_len; i++) {
23
dc->props = xlnx_zynqmp_props;
25
s->data[i] = s->pi->id[i];
24
dc->realize = xlnx_zynqmp_realize;
26
}
25
+ /* Reason: Uses serial_hds in realize function, thus can't be used twice */
27
+ for (; i < SPI_NOR_MAX_ID_LEN; i++) {
26
+ dc->user_creatable = false;
28
+ s->data[i] = 0;
27
}
29
+ }
28
30
29
static const TypeInfo xlnx_zynqmp_type_info = {
31
- s->len = s->pi->id_len;
32
+ s->len = SPI_NOR_MAX_ID_LEN;
33
s->pos = 0;
34
s->state = STATE_READING_DATA;
35
break;
30
--
36
--
31
2.7.4
37
2.20.1
32
38
33
39
diff view generated by jsdifflib
1
Reset for devices does not include an automatic clear of the
1
From: Guenter Roeck <linux@roeck-us.net>
2
device state (unlike CPU state, where most of the state
3
structure is cleared to zero). Add some missing initialization
4
of NVIC state that meant that the device was left in the wrong
5
state if the guest did a warm reset.
6
2
7
(In particular, since we were resetting the computed state like
3
Whenever an unsupported command is encountered, the current code
8
s->exception_prio but not all the state it was computed
4
interprets each transferred byte as new command. Most of the time, those
9
from like s->vectors[x].active, the NVIC wound up in an
5
'commands' are interpreted as new unknown commands. However, in rare
10
inconsistent state that could later trigger assertion failures.)
6
cases, it may be that for example address or length information
7
passed with the original command is by itself a valid command.
8
If that happens, the state machine may get completely confused and,
9
worst case, start writing data into the flash or even erase it.
11
10
11
To avoid the problem, transition into STATE_READING_DATA and keep
12
sending a value of 0 until the chip is deselected after encountering
13
an unsupported command.
14
15
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 1506092407-26985-2-git-send-email-peter.maydell@linaro.org
16
---
19
---
17
hw/intc/armv7m_nvic.c | 5 +++++
20
hw/block/m25p80.c | 5 +++++
18
1 file changed, 5 insertions(+)
21
1 file changed, 5 insertions(+)
19
22
20
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
23
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
21
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/armv7m_nvic.c
25
--- a/hw/block/m25p80.c
23
+++ b/hw/intc/armv7m_nvic.c
26
+++ b/hw/block/m25p80.c
24
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
27
@@ -XXX,XX +XXX,XX @@ static void decode_new_cmd(Flash *s, uint32_t value)
25
int resetprio;
28
s->quad_enable = false;
26
NVICState *s = NVIC(dev);
29
break;
27
30
default:
28
+ memset(s->vectors, 0, sizeof(s->vectors));
31
+ s->pos = 0;
29
+ memset(s->sec_vectors, 0, sizeof(s->sec_vectors));
32
+ s->len = 1;
30
+ s->prigroup[M_REG_NS] = 0;
33
+ s->state = STATE_READING_DATA;
31
+ s->prigroup[M_REG_S] = 0;
34
+ s->data_read_loop = true;
32
+
35
+ s->data[0] = 0;
33
s->vectors[ARMV7M_EXCP_NMI].enabled = 1;
36
qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Unknown cmd %x\n", value);
34
/* MEM, BUS, and USAGE are enabled through
37
break;
35
* the System Handler Control register
38
}
36
--
39
--
37
2.7.4
40
2.20.1
38
41
39
42
diff view generated by jsdifflib
1
From: Michael Olbrich <m.olbrich@pengutronix.de>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
The current code checks if the next block exceeds the size of the card.
3
The Linux kernel recently started using FAST_READ_4 commands.
4
This generates an error while reading the last block of the card.
4
This results in flash read failures. At the same time, the m25p80
5
Do the out-of-bounds check when starting to read a new block to fix this.
5
emulation is seen to read 8 more bytes than expected. Adjusting the
6
expected number of dummy cycles to match FAST_READ fixes the problem.
6
7
7
This issue became visible with increased error checking in Linux 4.13.
8
Fixes: f95c4bffdc4c ("aspeed/smc: snoop SPI transfers to fake dummy cycles")
8
9
Reviewed-by: Cédric Le Goater <clg@kaod.org>
9
Cc: qemu-stable@nongnu.org
10
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
10
Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
12
Message-id: 20170916091611.10241-1-m.olbrich@pengutronix.de
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
13
---
15
hw/sd/sd.c | 12 ++++++------
14
hw/ssi/aspeed_smc.c | 2 +-
16
1 file changed, 6 insertions(+), 6 deletions(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
17
16
18
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
17
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/sd/sd.c
19
--- a/hw/ssi/aspeed_smc.c
21
+++ b/hw/sd/sd.c
20
+++ b/hw/ssi/aspeed_smc.c
22
@@ -XXX,XX +XXX,XX @@ uint8_t sd_read_data(SDState *sd)
21
@@ -XXX,XX +XXX,XX @@ static int aspeed_smc_num_dummies(uint8_t command)
23
break;
22
case FAST_READ:
24
23
case DOR:
25
case 18:    /* CMD18: READ_MULTIPLE_BLOCK */
24
case QOR:
26
- if (sd->data_offset == 0)
25
+ case FAST_READ_4:
27
+ if (sd->data_offset == 0) {
26
case DOR_4:
28
+ if (sd->data_start + io_len > sd->size) {
27
case QOR_4:
29
+ sd->card_status |= ADDRESS_ERROR;
28
return 1;
30
+ return 0x00;
29
case DIOR:
31
+ }
30
- case FAST_READ_4:
32
BLK_READ_BLOCK(sd->data_start, io_len);
31
case DIOR_4:
33
+ }
32
return 2;
34
ret = sd->data[sd->data_offset ++];
33
case QIOR:
35
36
if (sd->data_offset >= io_len) {
37
@@ -XXX,XX +XXX,XX @@ uint8_t sd_read_data(SDState *sd)
38
break;
39
}
40
}
41
-
42
- if (sd->data_start + io_len > sd->size) {
43
- sd->card_status |= ADDRESS_ERROR;
44
- break;
45
- }
46
}
47
break;
48
49
--
34
--
50
2.7.4
35
2.20.1
51
36
52
37
diff view generated by jsdifflib
1
From: Jan Kiszka <jan.kiszka@siemens.com>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
This properly forwards SMC events to EL2 when PSCI is provided by QEMU
3
PXA255 does not support a USB OHCI controller, so don't wire it up.
4
itself and, thus, ARM_FEATURE_EL3 is off.
5
4
6
Found and tested with the Jailhouse hypervisor. Solution based on
5
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
7
suggestions by Peter Maydell.
6
Message-id: 20200313160215.28155-1-linux@roeck-us.net
8
9
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
10
Message-id: 4f243068-aaea-776f-d18f-f9e05e7be9cd@siemens.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
9
---
14
target/arm/helper.c | 9 ++++++++-
10
hw/arm/pxa2xx.c | 3 ---
15
target/arm/op_helper.c | 27 +++++++++++++++++----------
11
1 file changed, 3 deletions(-)
16
2 files changed, 25 insertions(+), 11 deletions(-)
17
12
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
15
--- a/hw/arm/pxa2xx.c
21
+++ b/target/arm/helper.c
16
+++ b/hw/arm/pxa2xx.c
22
@@ -XXX,XX +XXX,XX @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
17
@@ -XXX,XX +XXX,XX @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
23
18
s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
24
if (arm_feature(env, ARM_FEATURE_EL3)) {
25
valid_mask &= ~HCR_HCD;
26
- } else {
27
+ } else if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_SMC) {
28
+ /* Architecturally HCR.TSC is RES0 if EL3 is not implemented.
29
+ * However, if we're using the SMC PSCI conduit then QEMU is
30
+ * effectively acting like EL3 firmware and so the guest at
31
+ * EL2 should retain the ability to prevent EL1 from being
32
+ * able to make SMC calls into the ersatz firmware, so in
33
+ * that case HCR.TSC should be read/write.
34
+ */
35
valid_mask &= ~HCR_TSC;
36
}
19
}
37
20
38
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
21
- sysbus_create_simple("sysbus-ohci", 0x4c000000,
39
index XXXXXXX..XXXXXXX 100644
22
- qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
40
--- a/target/arm/op_helper.c
41
+++ b/target/arm/op_helper.c
42
@@ -XXX,XX +XXX,XX @@ void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
43
*/
44
bool undef = arm_feature(env, ARM_FEATURE_AARCH64) ? smd : smd && !secure;
45
46
- if (arm_is_psci_call(cpu, EXCP_SMC)) {
47
- /* If PSCI is enabled and this looks like a valid PSCI call then
48
- * that overrides the architecturally mandated SMC behaviour.
49
+ if (!arm_feature(env, ARM_FEATURE_EL3) &&
50
+ cpu->psci_conduit != QEMU_PSCI_CONDUIT_SMC) {
51
+ /* If we have no EL3 then SMC always UNDEFs and can't be
52
+ * trapped to EL2. PSCI-via-SMC is a sort of ersatz EL3
53
+ * firmware within QEMU, and we want an EL2 guest to be able
54
+ * to forbid its EL1 from making PSCI calls into QEMU's
55
+ * "firmware" via HCR.TSC, so for these purposes treat
56
+ * PSCI-via-SMC as implying an EL3.
57
*/
58
- return;
59
- }
60
-
23
-
61
- if (!arm_feature(env, ARM_FEATURE_EL3)) {
24
s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
62
- /* If we have no EL3 then SMC always UNDEFs */
25
s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
63
undef = true;
26
64
} else if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
65
- /* In NS EL1, HCR controlled routing to EL2 has priority over SMD. */
66
+ /* In NS EL1, HCR controlled routing to EL2 has priority over SMD.
67
+ * We also want an EL2 guest to be able to forbid its EL1 from
68
+ * making PSCI calls into QEMU's "firmware" via HCR.TSC.
69
+ */
70
raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
71
}
72
73
- if (undef) {
74
+ /* If PSCI is enabled and this looks like a valid PSCI call then
75
+ * suppress the UNDEF -- we'll catch the SMC exception and
76
+ * implement the PSCI call behaviour there.
77
+ */
78
+ if (undef && !arm_is_psci_call(cpu, EXCP_SMC)) {
79
raise_exception(env, EXCP_UDEF, syn_uncategorized(),
80
exception_target_el(env));
81
}
82
--
27
--
83
2.7.4
28
2.20.1
84
29
85
30
diff view generated by jsdifflib
Deleted patch
1
In the v7M architecture, there is an invariant that if the CPU is
2
in Handler mode then the CONTROL.SPSEL bit cannot be nonzero.
3
This in turn means that the current stack pointer is always
4
indicated by CONTROL.SPSEL, even though Handler mode always uses
5
the Main stack pointer.
6
1
7
In v8M, this invariant is removed, and CONTROL.SPSEL may now
8
be nonzero in Handler mode (though Handler mode still always
9
uses the Main stack pointer). In preparation for this change,
10
change how we handle this bit: rename switch_v7m_sp() to
11
the now more accurate write_v7m_control_spsel(), and make it
12
check both the handler mode state and the SPSEL bit.
13
14
Note that this implicitly changes the point at which we switch
15
active SP on exception exit from before we pop the exception
16
frame to after it.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 1506092407-26985-4-git-send-email-peter.maydell@linaro.org
22
---
23
target/arm/cpu.h | 8 ++++++-
24
hw/intc/armv7m_nvic.c | 2 +-
25
target/arm/helper.c | 65 ++++++++++++++++++++++++++++++++++-----------------
26
3 files changed, 51 insertions(+), 24 deletions(-)
27
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@ void pmccntr_sync(CPUARMState *env);
33
#define PSTATE_MODE_EL1t 4
34
#define PSTATE_MODE_EL0t 0
35
36
+/* Write a new value to v7m.exception, thus transitioning into or out
37
+ * of Handler mode; this may result in a change of active stack pointer.
38
+ */
39
+void write_v7m_exception(CPUARMState *env, uint32_t new_exc);
40
+
41
/* Map EL and handler into a PSTATE_MODE. */
42
static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler)
43
{
44
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
45
env->condexec_bits |= (val >> 8) & 0xfc;
46
}
47
if (mask & XPSR_EXCP) {
48
- env->v7m.exception = val & XPSR_EXCP;
49
+ /* Note that this only happens on exception exit */
50
+ write_v7m_exception(env, val & XPSR_EXCP);
51
}
52
}
53
54
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/intc/armv7m_nvic.c
57
+++ b/hw/intc/armv7m_nvic.c
58
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
59
vec->active = 1;
60
vec->pending = 0;
61
62
- env->v7m.exception = s->vectpending;
63
+ write_v7m_exception(env, s->vectpending);
64
65
nvic_irq_update(s);
66
67
diff --git a/target/arm/helper.c b/target/arm/helper.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/helper.c
70
+++ b/target/arm/helper.c
71
@@ -XXX,XX +XXX,XX @@ static bool v7m_using_psp(CPUARMState *env)
72
env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
73
}
74
75
-/* Switch to V7M main or process stack pointer. */
76
-static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
77
+/* Write to v7M CONTROL.SPSEL bit. This may change the current
78
+ * stack pointer between Main and Process stack pointers.
79
+ */
80
+static void write_v7m_control_spsel(CPUARMState *env, bool new_spsel)
81
{
82
uint32_t tmp;
83
- uint32_t old_control = env->v7m.control[env->v7m.secure];
84
- bool old_spsel = old_control & R_V7M_CONTROL_SPSEL_MASK;
85
+ bool new_is_psp, old_is_psp = v7m_using_psp(env);
86
+
87
+ env->v7m.control[env->v7m.secure] =
88
+ deposit32(env->v7m.control[env->v7m.secure],
89
+ R_V7M_CONTROL_SPSEL_SHIFT,
90
+ R_V7M_CONTROL_SPSEL_LENGTH, new_spsel);
91
+
92
+ new_is_psp = v7m_using_psp(env);
93
94
- if (old_spsel != new_spsel) {
95
+ if (old_is_psp != new_is_psp) {
96
tmp = env->v7m.other_sp;
97
env->v7m.other_sp = env->regs[13];
98
env->regs[13] = tmp;
99
+ }
100
+}
101
+
102
+void write_v7m_exception(CPUARMState *env, uint32_t new_exc)
103
+{
104
+ /* Write a new value to v7m.exception, thus transitioning into or out
105
+ * of Handler mode; this may result in a change of active stack pointer.
106
+ */
107
+ bool new_is_psp, old_is_psp = v7m_using_psp(env);
108
+ uint32_t tmp;
109
110
- env->v7m.control[env->v7m.secure] = deposit32(old_control,
111
- R_V7M_CONTROL_SPSEL_SHIFT,
112
- R_V7M_CONTROL_SPSEL_LENGTH, new_spsel);
113
+ env->v7m.exception = new_exc;
114
+
115
+ new_is_psp = v7m_using_psp(env);
116
+
117
+ if (old_is_psp != new_is_psp) {
118
+ tmp = env->v7m.other_sp;
119
+ env->v7m.other_sp = env->regs[13];
120
+ env->regs[13] = tmp;
121
}
122
}
123
124
@@ -XXX,XX +XXX,XX @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
125
bool want_psp = threadmode && spsel;
126
127
if (secure == env->v7m.secure) {
128
- /* Currently switch_v7m_sp switches SP as it updates SPSEL,
129
- * so the SP we want is always in regs[13].
130
- * When we decouple SPSEL from the actually selected SP
131
- * we need to check want_psp against v7m_using_psp()
132
- * to see whether we need regs[13] or v7m.other_sp.
133
- */
134
- return &env->regs[13];
135
+ if (want_psp == v7m_using_psp(env)) {
136
+ return &env->regs[13];
137
+ } else {
138
+ return &env->v7m.other_sp;
139
+ }
140
} else {
141
if (want_psp) {
142
return &env->v7m.other_ss_psp;
143
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
144
uint32_t addr;
145
146
armv7m_nvic_acknowledge_irq(env->nvic);
147
- switch_v7m_sp(env, 0);
148
+ write_v7m_control_spsel(env, 0);
149
arm_clear_exclusive(env);
150
/* Clear IT bits */
151
env->condexec_bits = 0;
152
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
153
return;
154
}
155
156
- /* Set CONTROL.SPSEL from excret.SPSEL. For QEMU this currently
157
- * causes us to switch the active SP, but we will change this
158
- * later to not do that so we can support v8M.
159
+ /* Set CONTROL.SPSEL from excret.SPSEL. Since we're still in
160
+ * Handler mode (and will be until we write the new XPSR.Interrupt
161
+ * field) this does not switch around the current stack pointer.
162
*/
163
- switch_v7m_sp(env, return_to_sp_process);
164
+ write_v7m_control_spsel(env, return_to_sp_process);
165
166
{
167
/* The stack pointer we should be reading the exception frame from
168
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
169
case 20: /* CONTROL */
170
/* Writing to the SPSEL bit only has an effect if we are in
171
* thread mode; other bits can be updated by any privileged code.
172
- * switch_v7m_sp() deals with updating the SPSEL bit in
173
+ * write_v7m_control_spsel() deals with updating the SPSEL bit in
174
* env->v7m.control, so we only need update the others.
175
*/
176
if (!arm_v7m_is_handler_mode(env)) {
177
- switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
178
+ write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
179
}
180
env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
181
env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
182
--
183
2.7.4
184
185
diff view generated by jsdifflib
Deleted patch
1
Now that we can handle the CONTROL.SPSEL bit not necessarily being
2
in sync with the current stack pointer, we can restore the correct
3
security state on exception return. This happens before we start
4
to read registers off the stack frame, but after we have taken
5
possible usage faults for bad exception return magic values and
6
updated CONTROL.SPSEL.
7
1
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1506092407-26985-5-git-send-email-peter.maydell@linaro.org
11
---
12
target/arm/helper.c | 2 ++
13
1 file changed, 2 insertions(+)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
20
*/
21
write_v7m_control_spsel(env, return_to_sp_process);
22
23
+ switch_v7m_security_state(env, return_to_secure);
24
+
25
{
26
/* The stack pointer we should be reading the exception frame from
27
* depends on bits in the magic exception return type value (and
28
--
29
2.7.4
30
31
diff view generated by jsdifflib
Deleted patch
1
On exception return for v8M, the SPSEL bit in the EXC_RETURN magic
2
value should be restored to the SPSEL bit in the CONTROL register
3
banked specified by the EXC_RETURN.ES bit.
4
1
5
Add write_v7m_control_spsel_for_secstate() which behaves like
6
write_v7m_control_spsel() but allows the caller to specify which
7
CONTROL bank to use, reimplement write_v7m_control_spsel() in
8
terms of it, and use it in exception return.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 1506092407-26985-6-git-send-email-peter.maydell@linaro.org
13
---
14
target/arm/helper.c | 40 +++++++++++++++++++++++++++-------------
15
1 file changed, 27 insertions(+), 13 deletions(-)
16
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static bool v7m_using_psp(CPUARMState *env)
22
env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
23
}
24
25
-/* Write to v7M CONTROL.SPSEL bit. This may change the current
26
- * stack pointer between Main and Process stack pointers.
27
+/* Write to v7M CONTROL.SPSEL bit for the specified security bank.
28
+ * This may change the current stack pointer between Main and Process
29
+ * stack pointers if it is done for the CONTROL register for the current
30
+ * security state.
31
*/
32
-static void write_v7m_control_spsel(CPUARMState *env, bool new_spsel)
33
+static void write_v7m_control_spsel_for_secstate(CPUARMState *env,
34
+ bool new_spsel,
35
+ bool secstate)
36
{
37
- uint32_t tmp;
38
- bool new_is_psp, old_is_psp = v7m_using_psp(env);
39
+ bool old_is_psp = v7m_using_psp(env);
40
41
- env->v7m.control[env->v7m.secure] =
42
- deposit32(env->v7m.control[env->v7m.secure],
43
+ env->v7m.control[secstate] =
44
+ deposit32(env->v7m.control[secstate],
45
R_V7M_CONTROL_SPSEL_SHIFT,
46
R_V7M_CONTROL_SPSEL_LENGTH, new_spsel);
47
48
- new_is_psp = v7m_using_psp(env);
49
+ if (secstate == env->v7m.secure) {
50
+ bool new_is_psp = v7m_using_psp(env);
51
+ uint32_t tmp;
52
53
- if (old_is_psp != new_is_psp) {
54
- tmp = env->v7m.other_sp;
55
- env->v7m.other_sp = env->regs[13];
56
- env->regs[13] = tmp;
57
+ if (old_is_psp != new_is_psp) {
58
+ tmp = env->v7m.other_sp;
59
+ env->v7m.other_sp = env->regs[13];
60
+ env->regs[13] = tmp;
61
+ }
62
}
63
}
64
65
+/* Write to v7M CONTROL.SPSEL bit. This may change the current
66
+ * stack pointer between Main and Process stack pointers.
67
+ */
68
+static void write_v7m_control_spsel(CPUARMState *env, bool new_spsel)
69
+{
70
+ write_v7m_control_spsel_for_secstate(env, new_spsel, env->v7m.secure);
71
+}
72
+
73
void write_v7m_exception(CPUARMState *env, uint32_t new_exc)
74
{
75
/* Write a new value to v7m.exception, thus transitioning into or out
76
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
77
* Handler mode (and will be until we write the new XPSR.Interrupt
78
* field) this does not switch around the current stack pointer.
79
*/
80
- write_v7m_control_spsel(env, return_to_sp_process);
81
+ write_v7m_control_spsel_for_secstate(env, return_to_sp_process, exc_secure);
82
83
switch_v7m_security_state(env, return_to_secure);
84
85
--
86
2.7.4
87
88
diff view generated by jsdifflib
Deleted patch
1
ARM v8M specifies that the INVPC usage fault for mismatched
2
xPSR exception field and handler mode bit should be checked
3
before updating the PSR and SP, so that the fault is taken
4
with the existing stack frame rather than by pushing a new one.
5
Perform this check in the right place for v8M.
6
1
7
Since v7M specifies in its pseudocode that this usage fault
8
check should happen later, we have to retain the original
9
code for that check rather than being able to merge the two.
10
(The distinction is architecturally visible but only in
11
very obscure corner cases like attempting an invalid exception
12
return with an exception frame in read only memory.)
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 1506092407-26985-7-git-send-email-peter.maydell@linaro.org
17
---
18
target/arm/helper.c | 30 +++++++++++++++++++++++++++---
19
1 file changed, 27 insertions(+), 3 deletions(-)
20
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
26
}
27
xpsr = ldl_phys(cs->as, frameptr + 0x1c);
28
29
+ if (arm_feature(env, ARM_FEATURE_V8)) {
30
+ /* For v8M we have to check whether the xPSR exception field
31
+ * matches the EXCRET value for return to handler/thread
32
+ * before we commit to changing the SP and xPSR.
33
+ */
34
+ bool will_be_handler = (xpsr & XPSR_EXCP) != 0;
35
+ if (return_to_handler != will_be_handler) {
36
+ /* Take an INVPC UsageFault on the current stack.
37
+ * By this point we will have switched to the security state
38
+ * for the background state, so this UsageFault will target
39
+ * that state.
40
+ */
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
42
+ env->v7m.secure);
43
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
44
+ v7m_exception_taken(cpu, excret);
45
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
46
+ "stackframe: failed exception return integrity "
47
+ "check\n");
48
+ return;
49
+ }
50
+ }
51
+
52
/* Commit to consuming the stack frame */
53
frameptr += 0x20;
54
/* Undo stack alignment (the SPREALIGN bit indicates that the original
55
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
56
/* The restored xPSR exception field will be zero if we're
57
* resuming in Thread mode. If that doesn't match what the
58
* exception return excret specified then this is a UsageFault.
59
+ * v7M requires we make this check here; v8M did it earlier.
60
*/
61
if (return_to_handler != arm_v7m_is_handler_mode(env)) {
62
- /* Take an INVPC UsageFault by pushing the stack again.
63
- * TODO: the v8M version of this code should target the
64
- * background state for this exception.
65
+ /* Take an INVPC UsageFault by pushing the stack again;
66
+ * we know we're v7M so this is never a Secure UsageFault.
67
*/
68
+ assert(!arm_feature(env, ARM_FEATURE_V8));
69
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, false);
70
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
71
v7m_push_stack(cpu);
72
--
73
2.7.4
74
75
diff view generated by jsdifflib
Deleted patch
1
Attempting to do an exception return with an exception frame that
2
is not 8-aligned is UNPREDICTABLE in v8M; warn about this.
3
(It is not UNPREDICTABLE in v7M, and our implementation can
4
handle the merely-4-aligned case fine, so we don't need to
5
do anything except warn.)
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1506092407-26985-8-git-send-email-peter.maydell@linaro.org
11
---
12
target/arm/helper.c | 7 +++++++
13
1 file changed, 7 insertions(+)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
20
return_to_sp_process);
21
uint32_t frameptr = *frame_sp_p;
22
23
+ if (!QEMU_IS_ALIGNED(frameptr, 8) &&
24
+ arm_feature(env, ARM_FEATURE_V8)) {
25
+ qemu_log_mask(LOG_GUEST_ERROR,
26
+ "M profile exception return with non-8-aligned SP "
27
+ "for destination state is UNPREDICTABLE\n");
28
+ }
29
+
30
/* Pop registers. TODO: make these accesses use the correct
31
* attributes and address space (S/NS, priv/unpriv) and handle
32
* memory transaction failures.
33
--
34
2.7.4
35
36
diff view generated by jsdifflib
Deleted patch
1
In the v8M architecture, return from an exception to a PC which
2
has bit 0 set is not UNPREDICTABLE; it is defined that bit 0
3
is discarded [R_HRJH]. Restrict our complaint about this to v7M.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 1506092407-26985-9-git-send-email-peter.maydell@linaro.org
9
---
10
target/arm/helper.c | 22 +++++++++++++++-------
11
1 file changed, 15 insertions(+), 7 deletions(-)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
18
env->regs[12] = ldl_phys(cs->as, frameptr + 0x10);
19
env->regs[14] = ldl_phys(cs->as, frameptr + 0x14);
20
env->regs[15] = ldl_phys(cs->as, frameptr + 0x18);
21
+
22
+ /* Returning from an exception with a PC with bit 0 set is defined
23
+ * behaviour on v8M (bit 0 is ignored), but for v7M it was specified
24
+ * to be UNPREDICTABLE. In practice actual v7M hardware seems to ignore
25
+ * the lsbit, and there are several RTOSes out there which incorrectly
26
+ * assume the r15 in the stack frame should be a Thumb-style "lsbit
27
+ * indicates ARM/Thumb" value, so ignore the bit on v7M as well, but
28
+ * complain about the badly behaved guest.
29
+ */
30
if (env->regs[15] & 1) {
31
- qemu_log_mask(LOG_GUEST_ERROR,
32
- "M profile return from interrupt with misaligned "
33
- "PC is UNPREDICTABLE\n");
34
- /* Actual hardware seems to ignore the lsbit, and there are several
35
- * RTOSes out there which incorrectly assume the r15 in the stack
36
- * frame should be a Thumb-style "lsbit indicates ARM/Thumb" value.
37
- */
38
env->regs[15] &= ~1U;
39
+ if (!arm_feature(env, ARM_FEATURE_V8)) {
40
+ qemu_log_mask(LOG_GUEST_ERROR,
41
+ "M profile return from interrupt with misaligned "
42
+ "PC is UNPREDICTABLE on v7M\n");
43
+ }
44
}
45
+
46
xpsr = ldl_phys(cs->as, frameptr + 0x1c);
47
48
if (arm_feature(env, ARM_FEATURE_V8)) {
49
--
50
2.7.4
51
52
diff view generated by jsdifflib
Deleted patch
1
Add the new M profile Secure Fault Status Register
2
and Secure Fault Address Register.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 1506092407-26985-10-git-send-email-peter.maydell@linaro.org
7
---
8
target/arm/cpu.h | 12 ++++++++++++
9
hw/intc/armv7m_nvic.c | 34 ++++++++++++++++++++++++++++++++++
10
target/arm/machine.c | 2 ++
11
3 files changed, 48 insertions(+)
12
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
18
uint32_t cfsr[M_REG_NUM_BANKS]; /* Configurable Fault Status */
19
uint32_t hfsr; /* HardFault Status */
20
uint32_t dfsr; /* Debug Fault Status Register */
21
+ uint32_t sfsr; /* Secure Fault Status Register */
22
uint32_t mmfar[M_REG_NUM_BANKS]; /* MemManage Fault Address */
23
uint32_t bfar; /* BusFault Address */
24
+ uint32_t sfar; /* Secure Fault Address Register */
25
unsigned mpu_ctrl[M_REG_NUM_BANKS]; /* MPU_CTRL */
26
int exception;
27
uint32_t primask[M_REG_NUM_BANKS];
28
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_DFSR, DWTTRAP, 2, 1)
29
FIELD(V7M_DFSR, VCATCH, 3, 1)
30
FIELD(V7M_DFSR, EXTERNAL, 4, 1)
31
32
+/* V7M SFSR bits */
33
+FIELD(V7M_SFSR, INVEP, 0, 1)
34
+FIELD(V7M_SFSR, INVIS, 1, 1)
35
+FIELD(V7M_SFSR, INVER, 2, 1)
36
+FIELD(V7M_SFSR, AUVIOL, 3, 1)
37
+FIELD(V7M_SFSR, INVTRAN, 4, 1)
38
+FIELD(V7M_SFSR, LSPERR, 5, 1)
39
+FIELD(V7M_SFSR, SFARVALID, 6, 1)
40
+FIELD(V7M_SFSR, LSERR, 7, 1)
41
+
42
/* v7M MPU_CTRL bits */
43
FIELD(V7M_MPU_CTRL, ENABLE, 0, 1)
44
FIELD(V7M_MPU_CTRL, HFNMIENA, 1, 1)
45
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/intc/armv7m_nvic.c
48
+++ b/hw/intc/armv7m_nvic.c
49
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
50
goto bad_offset;
51
}
52
return cpu->env.pmsav8.mair1[attrs.secure];
53
+ case 0xde4: /* SFSR */
54
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
55
+ goto bad_offset;
56
+ }
57
+ if (!attrs.secure) {
58
+ return 0;
59
+ }
60
+ return cpu->env.v7m.sfsr;
61
+ case 0xde8: /* SFAR */
62
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
63
+ goto bad_offset;
64
+ }
65
+ if (!attrs.secure) {
66
+ return 0;
67
+ }
68
+ return cpu->env.v7m.sfar;
69
default:
70
bad_offset:
71
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
72
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
73
* only affect cacheability, and we don't implement caching.
74
*/
75
break;
76
+ case 0xde4: /* SFSR */
77
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
78
+ goto bad_offset;
79
+ }
80
+ if (!attrs.secure) {
81
+ return;
82
+ }
83
+ cpu->env.v7m.sfsr &= ~value; /* W1C */
84
+ break;
85
+ case 0xde8: /* SFAR */
86
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
87
+ goto bad_offset;
88
+ }
89
+ if (!attrs.secure) {
90
+ return;
91
+ }
92
+ cpu->env.v7m.sfsr = value;
93
+ break;
94
case 0xf00: /* Software Triggered Interrupt Register */
95
{
96
int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
97
diff --git a/target/arm/machine.c b/target/arm/machine.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/target/arm/machine.c
100
+++ b/target/arm/machine.c
101
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_security = {
102
VMSTATE_UINT32(env.v7m.ccr[M_REG_S], ARMCPU),
103
VMSTATE_UINT32(env.v7m.mmfar[M_REG_S], ARMCPU),
104
VMSTATE_UINT32(env.v7m.cfsr[M_REG_S], ARMCPU),
105
+ VMSTATE_UINT32(env.v7m.sfsr, ARMCPU),
106
+ VMSTATE_UINT32(env.v7m.sfar, ARMCPU),
107
VMSTATE_END_OF_LIST()
108
}
109
};
110
--
111
2.7.4
112
113
diff view generated by jsdifflib
Deleted patch
1
For v8M, exceptions from Secure to Non-Secure state will save
2
callee-saved registers to the exception frame as well as the
3
caller-saved registers. Add support for unstacking these
4
registers in exception exit when necessary.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 1506092407-26985-12-git-send-email-peter.maydell@linaro.org
9
---
10
target/arm/helper.c | 30 ++++++++++++++++++++++++++++++
11
1 file changed, 30 insertions(+)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
18
"for destination state is UNPREDICTABLE\n");
19
}
20
21
+ /* Do we need to pop callee-saved registers? */
22
+ if (return_to_secure &&
23
+ ((excret & R_V7M_EXCRET_ES_MASK) == 0 ||
24
+ (excret & R_V7M_EXCRET_DCRS_MASK) == 0)) {
25
+ uint32_t expected_sig = 0xfefa125b;
26
+ uint32_t actual_sig = ldl_phys(cs->as, frameptr);
27
+
28
+ if (expected_sig != actual_sig) {
29
+ /* Take a SecureFault on the current stack */
30
+ env->v7m.sfsr |= R_V7M_SFSR_INVIS_MASK;
31
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
32
+ v7m_exception_taken(cpu, excret);
33
+ qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
34
+ "stackframe: failed exception return integrity "
35
+ "signature check\n");
36
+ return;
37
+ }
38
+
39
+ env->regs[4] = ldl_phys(cs->as, frameptr + 0x8);
40
+ env->regs[5] = ldl_phys(cs->as, frameptr + 0xc);
41
+ env->regs[6] = ldl_phys(cs->as, frameptr + 0x10);
42
+ env->regs[7] = ldl_phys(cs->as, frameptr + 0x14);
43
+ env->regs[8] = ldl_phys(cs->as, frameptr + 0x18);
44
+ env->regs[9] = ldl_phys(cs->as, frameptr + 0x1c);
45
+ env->regs[10] = ldl_phys(cs->as, frameptr + 0x20);
46
+ env->regs[11] = ldl_phys(cs->as, frameptr + 0x24);
47
+
48
+ frameptr += 0x28;
49
+ }
50
+
51
/* Pop registers. TODO: make these accesses use the correct
52
* attributes and address space (S/NS, priv/unpriv) and handle
53
* memory transaction failures.
54
--
55
2.7.4
56
57
diff view generated by jsdifflib
Deleted patch
1
Add support for v8M and in particular the security extension
2
to the exception entry code. This requires changes to:
3
* calculation of the exception-return magic LR value
4
* push the callee-saves registers in certain cases
5
* clear registers when taking non-secure exceptions to avoid
6
leaking information from the interrupted secure code
7
* switch to the correct security state on entry
8
* use the vector table for the security state we're targeting
9
1
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 1506092407-26985-13-git-send-email-peter.maydell@linaro.org
13
---
14
target/arm/helper.c | 165 +++++++++++++++++++++++++++++++++++++++++++++-------
15
1 file changed, 145 insertions(+), 20 deletions(-)
16
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
22
}
23
}
24
25
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
26
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu, bool targets_secure)
27
{
28
CPUState *cs = CPU(cpu);
29
CPUARMState *env = &cpu->env;
30
MemTxResult result;
31
- hwaddr vec = env->v7m.vecbase[env->v7m.secure] + env->v7m.exception * 4;
32
+ hwaddr vec = env->v7m.vecbase[targets_secure] + env->v7m.exception * 4;
33
uint32_t addr;
34
35
addr = address_space_ldl(cs->as, vec,
36
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
37
* Since we don't model Lockup, we just report this guest error
38
* via cpu_abort().
39
*/
40
- cpu_abort(cs, "Failed to read from exception vector table "
41
- "entry %08x\n", (unsigned)vec);
42
+ cpu_abort(cs, "Failed to read from %s exception vector table "
43
+ "entry %08x\n", targets_secure ? "secure" : "nonsecure",
44
+ (unsigned)vec);
45
}
46
return addr;
47
}
48
49
-static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
50
+static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain)
51
+{
52
+ /* For v8M, push the callee-saves register part of the stack frame.
53
+ * Compare the v8M pseudocode PushCalleeStack().
54
+ * In the tailchaining case this may not be the current stack.
55
+ */
56
+ CPUARMState *env = &cpu->env;
57
+ CPUState *cs = CPU(cpu);
58
+ uint32_t *frame_sp_p;
59
+ uint32_t frameptr;
60
+
61
+ if (dotailchain) {
62
+ frame_sp_p = get_v7m_sp_ptr(env, true,
63
+ lr & R_V7M_EXCRET_MODE_MASK,
64
+ lr & R_V7M_EXCRET_SPSEL_MASK);
65
+ } else {
66
+ frame_sp_p = &env->regs[13];
67
+ }
68
+
69
+ frameptr = *frame_sp_p - 0x28;
70
+
71
+ stl_phys(cs->as, frameptr, 0xfefa125b);
72
+ stl_phys(cs->as, frameptr + 0x8, env->regs[4]);
73
+ stl_phys(cs->as, frameptr + 0xc, env->regs[5]);
74
+ stl_phys(cs->as, frameptr + 0x10, env->regs[6]);
75
+ stl_phys(cs->as, frameptr + 0x14, env->regs[7]);
76
+ stl_phys(cs->as, frameptr + 0x18, env->regs[8]);
77
+ stl_phys(cs->as, frameptr + 0x1c, env->regs[9]);
78
+ stl_phys(cs->as, frameptr + 0x20, env->regs[10]);
79
+ stl_phys(cs->as, frameptr + 0x24, env->regs[11]);
80
+
81
+ *frame_sp_p = frameptr;
82
+}
83
+
84
+static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
85
{
86
/* Do the "take the exception" parts of exception entry,
87
* but not the pushing of state to the stack. This is
88
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
89
*/
90
CPUARMState *env = &cpu->env;
91
uint32_t addr;
92
+ bool targets_secure;
93
+
94
+ targets_secure = armv7m_nvic_acknowledge_irq(env->nvic);
95
96
- armv7m_nvic_acknowledge_irq(env->nvic);
97
+ if (arm_feature(env, ARM_FEATURE_V8)) {
98
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
99
+ (lr & R_V7M_EXCRET_S_MASK)) {
100
+ /* The background code (the owner of the registers in the
101
+ * exception frame) is Secure. This means it may either already
102
+ * have or now needs to push callee-saves registers.
103
+ */
104
+ if (targets_secure) {
105
+ if (dotailchain && !(lr & R_V7M_EXCRET_ES_MASK)) {
106
+ /* We took an exception from Secure to NonSecure
107
+ * (which means the callee-saved registers got stacked)
108
+ * and are now tailchaining to a Secure exception.
109
+ * Clear DCRS so eventual return from this Secure
110
+ * exception unstacks the callee-saved registers.
111
+ */
112
+ lr &= ~R_V7M_EXCRET_DCRS_MASK;
113
+ }
114
+ } else {
115
+ /* We're going to a non-secure exception; push the
116
+ * callee-saves registers to the stack now, if they're
117
+ * not already saved.
118
+ */
119
+ if (lr & R_V7M_EXCRET_DCRS_MASK &&
120
+ !(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) {
121
+ v7m_push_callee_stack(cpu, lr, dotailchain);
122
+ }
123
+ lr |= R_V7M_EXCRET_DCRS_MASK;
124
+ }
125
+ }
126
+
127
+ lr &= ~R_V7M_EXCRET_ES_MASK;
128
+ if (targets_secure || !arm_feature(env, ARM_FEATURE_M_SECURITY)) {
129
+ lr |= R_V7M_EXCRET_ES_MASK;
130
+ }
131
+ lr &= ~R_V7M_EXCRET_SPSEL_MASK;
132
+ if (env->v7m.control[targets_secure] & R_V7M_CONTROL_SPSEL_MASK) {
133
+ lr |= R_V7M_EXCRET_SPSEL_MASK;
134
+ }
135
+
136
+ /* Clear registers if necessary to prevent non-secure exception
137
+ * code being able to see register values from secure code.
138
+ * Where register values become architecturally UNKNOWN we leave
139
+ * them with their previous values.
140
+ */
141
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
142
+ if (!targets_secure) {
143
+ /* Always clear the caller-saved registers (they have been
144
+ * pushed to the stack earlier in v7m_push_stack()).
145
+ * Clear callee-saved registers if the background code is
146
+ * Secure (in which case these regs were saved in
147
+ * v7m_push_callee_stack()).
148
+ */
149
+ int i;
150
+
151
+ for (i = 0; i < 13; i++) {
152
+ /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
153
+ if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
154
+ env->regs[i] = 0;
155
+ }
156
+ }
157
+ /* Clear EAPSR */
158
+ xpsr_write(env, 0, XPSR_NZCV | XPSR_Q | XPSR_GE | XPSR_IT);
159
+ }
160
+ }
161
+ }
162
+
163
+ /* Switch to target security state -- must do this before writing SPSEL */
164
+ switch_v7m_security_state(env, targets_secure);
165
write_v7m_control_spsel(env, 0);
166
arm_clear_exclusive(env);
167
/* Clear IT bits */
168
env->condexec_bits = 0;
169
env->regs[14] = lr;
170
- addr = arm_v7m_load_vector(cpu);
171
+ addr = arm_v7m_load_vector(cpu, targets_secure);
172
env->regs[15] = addr & 0xfffffffe;
173
env->thumb = addr & 1;
174
}
175
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
176
if (sfault) {
177
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
178
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
179
- v7m_exception_taken(cpu, excret);
180
+ v7m_exception_taken(cpu, excret, true);
181
qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
182
"stackframe: failed EXC_RETURN.ES validity check\n");
183
return;
184
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
185
*/
186
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
187
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
188
- v7m_exception_taken(cpu, excret);
189
+ v7m_exception_taken(cpu, excret, true);
190
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
191
"stackframe: failed exception return integrity check\n");
192
return;
193
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
194
/* Take a SecureFault on the current stack */
195
env->v7m.sfsr |= R_V7M_SFSR_INVIS_MASK;
196
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
197
- v7m_exception_taken(cpu, excret);
198
+ v7m_exception_taken(cpu, excret, true);
199
qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
200
"stackframe: failed exception return integrity "
201
"signature check\n");
202
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
203
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
204
env->v7m.secure);
205
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
206
- v7m_exception_taken(cpu, excret);
207
+ v7m_exception_taken(cpu, excret, true);
208
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
209
"stackframe: failed exception return integrity "
210
"check\n");
211
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
212
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, false);
213
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
214
v7m_push_stack(cpu);
215
- v7m_exception_taken(cpu, excret);
216
+ v7m_exception_taken(cpu, excret, false);
217
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
218
"failed exception return integrity check\n");
219
return;
220
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
221
return; /* Never happens. Keep compiler happy. */
222
}
223
224
- lr = R_V7M_EXCRET_RES1_MASK |
225
- R_V7M_EXCRET_S_MASK |
226
- R_V7M_EXCRET_DCRS_MASK |
227
- R_V7M_EXCRET_FTYPE_MASK |
228
- R_V7M_EXCRET_ES_MASK;
229
- if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK) {
230
- lr |= R_V7M_EXCRET_SPSEL_MASK;
231
+ if (arm_feature(env, ARM_FEATURE_V8)) {
232
+ lr = R_V7M_EXCRET_RES1_MASK |
233
+ R_V7M_EXCRET_DCRS_MASK |
234
+ R_V7M_EXCRET_FTYPE_MASK;
235
+ /* The S bit indicates whether we should return to Secure
236
+ * or NonSecure (ie our current state).
237
+ * The ES bit indicates whether we're taking this exception
238
+ * to Secure or NonSecure (ie our target state). We set it
239
+ * later, in v7m_exception_taken().
240
+ * The SPSEL bit is also set in v7m_exception_taken() for v8M.
241
+ * This corresponds to the ARM ARM pseudocode for v8M setting
242
+ * some LR bits in PushStack() and some in ExceptionTaken();
243
+ * the distinction matters for the tailchain cases where we
244
+ * can take an exception without pushing the stack.
245
+ */
246
+ if (env->v7m.secure) {
247
+ lr |= R_V7M_EXCRET_S_MASK;
248
+ }
249
+ } else {
250
+ lr = R_V7M_EXCRET_RES1_MASK |
251
+ R_V7M_EXCRET_S_MASK |
252
+ R_V7M_EXCRET_DCRS_MASK |
253
+ R_V7M_EXCRET_FTYPE_MASK |
254
+ R_V7M_EXCRET_ES_MASK;
255
+ if (env->v7m.control[M_REG_NS] & R_V7M_CONTROL_SPSEL_MASK) {
256
+ lr |= R_V7M_EXCRET_SPSEL_MASK;
257
+ }
258
}
259
if (!arm_v7m_is_handler_mode(env)) {
260
lr |= R_V7M_EXCRET_MODE_MASK;
261
}
262
263
v7m_push_stack(cpu);
264
- v7m_exception_taken(cpu, lr);
265
+ v7m_exception_taken(cpu, lr, false);
266
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
267
}
268
269
--
270
2.7.4
271
272
diff view generated by jsdifflib