1
ARM queu; includes all the NVIC rewrite patches.
1
Latest arm queue, half minor code cleanups and half minor
2
The QOMify-armv7m patchset hasn't got enough review just
2
bug fixes.
3
yet but I may be able to sneak it in before freeze
4
tomorrow if it gets review. Didn't want to hold this lot
5
up waiting, anyway.
6
3
7
thanks
8
-- PMM
4
-- PMM
9
5
6
The following changes since commit 5d0e5694470d2952b4f257bc985cac8c89b4fd92:
10
7
11
The following changes since commit 8f2d7c341184a95d05476ea3c45dbae2b9ddbe51:
8
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2019-06-17 11:55:14 +0100)
12
9
13
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-02-27-1' into staging (2017-02-27 15:33:21 +0000)
10
are available in the Git repository at:
14
11
15
are available in the git repository at:
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190617
16
13
17
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170227
14
for you to fetch changes up to 1120827fa182f0e76226df7ffe7a86598d1df54f:
18
15
19
for you to fetch changes up to 94d5bcf5a7f3799660b62098a5183f161aad0601:
16
target/arm: Only implement doubles if the FPU supports them (2019-06-17 15:15:06 +0100)
20
21
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID (2017-02-27 17:23:16 +0000)
22
17
23
----------------------------------------------------------------
18
----------------------------------------------------------------
24
target-arm queue:
19
target-arm queue:
25
* raspi2: implement RNG module, GPIO and new SD card controller
20
* support large kernel images in bootloader (by avoiding
26
(sufficient to boot new raspbian kernels)
21
putting the initrd over the top of them)
27
* sdhci: bugfixes for block transfers
22
* correctly disable FPU/DSP in the CPU for the mps2-an521, musca-a boards
28
* virt: fix cpu object reference leak
23
* arm_gicv3: Fix decoding of ID register range
29
* Add missing fp_access_check() to aarch64 crypto instructions
24
* arm_gicv3: GICD_TYPER.SecurityExtn is RAZ if GICD_CTLR.DS == 1
30
* cputlb: Don't assume do_unassigned_access() never returns
25
* some code cleanups following on from the VFP decodetree conversion
31
* virt: Add a user option to disallow ITS instantiation
26
* Only implement doubles if the FPU supports them
32
* i.MX timers: fix reset handling
27
(so we now correctly model Cortex-M4, -M33 as single precision only)
33
* ARMv7M NVIC: rewrite to fix broken priority handling and masking
34
* exynos: Fix proper mapping of CPUs by providing real cluster ID
35
* exynos: Fix Linux kernel division by zero for PLLs
36
28
37
----------------------------------------------------------------
29
----------------------------------------------------------------
38
Clement Deschamps (4):
30
Peter Maydell (24):
39
bcm2835_sdhost: add bcm2835 sdhost controller
31
hw/arm/boot: Don't assume RAM starts at address zero
40
hw/sd: add card-reparenting function
32
hw/arm/boot: Diagnose layouts that put initrd or DTB off the end of RAM
41
bcm2835_gpio: add bcm2835 gpio controller
33
hw/arm/boot: Avoid placing the initrd on top of the kernel
42
bcm2835: add sdhost and gpio controllers
34
hw/arm/boot: Honour image size field in AArch64 Image format kernels
35
target/arm: Allow VFP and Neon to be disabled via a CPU property
36
target/arm: Allow M-profile CPUs to disable the DSP extension via CPU property
37
hw/arm/armv7m: Forward "vfp" and "dsp" properties to CPU
38
hw/arm: Correctly disable FPU/DSP for some ARMSSE-based boards
39
hw/intc/arm_gicv3: Fix decoding of ID register range
40
hw/intc/arm_gicv3: GICD_TYPER.SecurityExtn is RAZ if GICD_CTLR.DS == 1
41
target/arm: Move vfp_expand_imm() to translate.[ch]
42
target/arm: Use vfp_expand_imm() for AArch32 VFP VMOV_imm
43
target/arm: Stop using cpu_F0s for NEON_2RM_VABS_F
44
target/arm: Stop using cpu_F0s for NEON_2RM_VNEG_F
45
target/arm: Stop using cpu_F0s for NEON_2RM_VRINT*
46
target/arm: Stop using cpu_F0s for NEON_2RM_VCVT[ANPM][US]
47
target/arm: Stop using cpu_F0s for NEON_2RM_VRECPE_F and NEON_2RM_VRSQRTE_F
48
target/arm: Stop using cpu_F0s for Neon f32/s32 VCVT
49
target/arm: Stop using cpu_F0s in Neon VCVT fixed-point ops
50
target/arm: stop using deprecated functions in NEON_2RM_VCVT_F16_F32
51
target/arm: Stop using deprecated functions in NEON_2RM_VCVT_F32_F16
52
target/arm: Remove unused cpu_F0s, cpu_F0d, cpu_F1s, cpu_F1d
53
target/arm: Fix typos in trans function prototypes
54
target/arm: Only implement doubles if the FPU supports them
43
55
44
Eric Auger (1):
56
include/hw/arm/armsse.h | 7 ++
45
hw/arm/virt: Add a user option to disallow ITS instantiation
57
include/hw/arm/armv7m.h | 4 +
58
target/arm/cpu.h | 12 +++
59
target/arm/translate-a64.h | 1 -
60
target/arm/translate.h | 7 ++
61
hw/arm/armsse.c | 58 +++++++---
62
hw/arm/armv7m.c | 18 ++++
63
hw/arm/boot.c | 83 ++++++++++----
64
hw/arm/musca.c | 8 ++
65
hw/intc/arm_gicv3_dist.c | 12 ++-
66
hw/intc/arm_gicv3_redist.c | 4 +-
67
target/arm/cpu.c | 179 ++++++++++++++++++++++++++++--
68
target/arm/translate-a64.c | 32 ------
69
target/arm/translate-vfp.inc.c | 173 ++++++++++++++++++++++-------
70
target/arm/translate.c | 240 ++++++++++++++---------------------------
71
target/arm/vfp.decode | 10 +-
72
16 files changed, 572 insertions(+), 276 deletions(-)
46
73
47
Igor Mammedov (1):
48
hw/arm/virt: fix cpu object reference leak
49
50
Krzysztof Kozlowski (2):
51
hw/arm/exynos: Fix Linux kernel division by zero for PLLs
52
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID
53
54
Kurban Mallachiev (1):
55
ARM i.MX timers: fix reset handling
56
57
Marcin Chojnacki (1):
58
target-arm: Implement BCM2835 hardware RNG
59
60
Michael Davidsaver (5):
61
armv7m: Rewrite NVIC to not use any GIC code
62
arm: gic: Remove references to NVIC
63
armv7m: Escalate exceptions to HardFault if necessary
64
armv7m: Simpler and faster exception start
65
armv7m: VECTCLRACTIVE and VECTRESET are UNPREDICTABLE
66
67
Nick Reilly (1):
68
Add missing fp_access_check() to aarch64 crypto instructions
69
70
Peter Maydell (10):
71
bcm2835_rng: Use qcrypto_random_bytes() rather than rand()
72
cputlb: Don't assume do_unassigned_access() never returns
73
armv7m: Rename nvic_state to NVICState
74
armv7m: Implement reading and writing of PRIGROUP
75
armv7m: Fix condition check for taking exceptions
76
armv7m: Remove unused armv7m_nvic_acknowledge_irq() return value
77
armv7m: Extract "exception taken" code into functions
78
armv7m: Check exception return consistency
79
armv7m: Raise correct kind of UsageFault for attempts to execute ARM code
80
armv7m: Allow SHCSR writes to change pending and active bits
81
82
Prasad J Pandit (4):
83
sd: sdhci: mask transfer mode register value
84
sd: sdhci: check transfer mode register in multi block transfer
85
sd: sdhci: conditionally invoke multi block transfer
86
sd: sdhci: Remove block count enable check in single block transfers
87
88
hw/gpio/Makefile.objs | 1 +
89
hw/misc/Makefile.objs | 3 +-
90
hw/sd/Makefile.objs | 1 +
91
hw/intc/gic_internal.h | 7 +-
92
include/hw/arm/bcm2835_peripherals.h | 6 +
93
include/hw/arm/virt.h | 1 +
94
include/hw/gpio/bcm2835_gpio.h | 39 ++
95
include/hw/misc/bcm2835_rng.h | 27 ++
96
include/hw/sd/bcm2835_sdhost.h | 48 ++
97
include/hw/sd/sd.h | 11 +
98
target/arm/cpu.h | 23 +-
99
cputlb.c | 15 +-
100
hw/arm/bcm2835_peripherals.c | 58 ++-
101
hw/arm/exynos4210.c | 18 +
102
hw/arm/virt.c | 32 +-
103
hw/gpio/bcm2835_gpio.c | 353 ++++++++++++++
104
hw/intc/arm_gic.c | 31 +-
105
hw/intc/arm_gic_common.c | 23 +-
106
hw/intc/armv7m_nvic.c | 885 ++++++++++++++++++++++++++++-------
107
hw/misc/bcm2835_rng.c | 149 ++++++
108
hw/misc/exynos4210_clk.c | 164 +++++++
109
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++
110
hw/sd/core.c | 30 ++
111
hw/sd/sdhci.c | 25 +-
112
hw/timer/imx_gpt.c | 33 +-
113
linux-user/main.c | 1 +
114
target/arm/cpu.c | 16 +-
115
target/arm/helper.c | 245 +++++++---
116
target/arm/translate-a64.c | 12 +
117
target/arm/translate.c | 8 +-
118
hw/intc/trace-events | 15 +
119
31 files changed, 2376 insertions(+), 333 deletions(-)
120
create mode 100644 include/hw/gpio/bcm2835_gpio.h
121
create mode 100644 include/hw/misc/bcm2835_rng.h
122
create mode 100644 include/hw/sd/bcm2835_sdhost.h
123
create mode 100644 hw/gpio/bcm2835_gpio.c
124
create mode 100644 hw/misc/bcm2835_rng.c
125
create mode 100644 hw/misc/exynos4210_clk.c
126
create mode 100644 hw/sd/bcm2835_sdhost.c
127
diff view generated by jsdifflib
Deleted patch
1
From: Marcin Chojnacki <marcinch7@gmail.com>
2
1
3
Recent vanilla Raspberry Pi kernels started to make use of
4
the hardware random number generator in BCM2835 SoC. As a
5
result, those kernels wouldn't work anymore under QEMU
6
but rather just freeze during the boot process.
7
8
This patch implements a trivial BCM2835 compatible RNG,
9
and adds it as a peripheral to BCM2835 platform, which
10
allows to boot a vanilla Raspberry Pi kernel under Qemu.
11
12
Changes since v1:
13
* Prevented guest from writing [31..20] bits in rng_status
14
* Removed redundant minimum_version_id_old
15
* Added field entries for the state
16
* Changed realize function to reset
17
18
Signed-off-by: Marcin Chojnacki <marcinch7@gmail.com>
19
Message-id: 20170210210857.47893-1-marcinch7@gmail.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/misc/Makefile.objs | 1 +
24
include/hw/arm/bcm2835_peripherals.h | 2 +
25
include/hw/misc/bcm2835_rng.h | 27 ++++++++
26
hw/arm/bcm2835_peripherals.c | 15 +++++
27
hw/misc/bcm2835_rng.c | 124 +++++++++++++++++++++++++++++++++++
28
5 files changed, 169 insertions(+)
29
create mode 100644 include/hw/misc/bcm2835_rng.h
30
create mode 100644 hw/misc/bcm2835_rng.c
31
32
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/misc/Makefile.objs
35
+++ b/hw/misc/Makefile.objs
36
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_sdrc.o
37
obj-$(CONFIG_OMAP) += omap_tap.o
38
obj-$(CONFIG_RASPI) += bcm2835_mbox.o
39
obj-$(CONFIG_RASPI) += bcm2835_property.o
40
+obj-$(CONFIG_RASPI) += bcm2835_rng.o
41
obj-$(CONFIG_SLAVIO) += slavio_misc.o
42
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
43
obj-$(CONFIG_ZYNQ) += zynq-xadc.o
44
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/bcm2835_peripherals.h
47
+++ b/include/hw/arm/bcm2835_peripherals.h
48
@@ -XXX,XX +XXX,XX @@
49
#include "hw/dma/bcm2835_dma.h"
50
#include "hw/intc/bcm2835_ic.h"
51
#include "hw/misc/bcm2835_property.h"
52
+#include "hw/misc/bcm2835_rng.h"
53
#include "hw/misc/bcm2835_mbox.h"
54
#include "hw/sd/sdhci.h"
55
56
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
57
BCM2835DMAState dma;
58
BCM2835ICState ic;
59
BCM2835PropertyState property;
60
+ BCM2835RngState rng;
61
BCM2835MboxState mboxes;
62
SDHCIState sdhci;
63
} BCM2835PeripheralState;
64
diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/bcm2835_rng.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * BCM2835 Random Number Generator emulation
72
+ *
73
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
74
+ *
75
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
76
+ * See the COPYING file in the top-level directory.
77
+ */
78
+
79
+#ifndef BCM2835_RNG_H
80
+#define BCM2835_RNG_H
81
+
82
+#include "hw/sysbus.h"
83
+
84
+#define TYPE_BCM2835_RNG "bcm2835-rng"
85
+#define BCM2835_RNG(obj) \
86
+ OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG)
87
+
88
+typedef struct {
89
+ SysBusDevice busdev;
90
+ MemoryRegion iomem;
91
+
92
+ uint32_t rng_ctrl;
93
+ uint32_t rng_status;
94
+} BCM2835RngState;
95
+
96
+#endif
97
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/hw/arm/bcm2835_peripherals.c
100
+++ b/hw/arm/bcm2835_peripherals.c
101
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
102
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
103
OBJECT(&s->gpu_bus_mr), &error_abort);
104
105
+ /* Random Number Generator */
106
+ object_initialize(&s->rng, sizeof(s->rng), TYPE_BCM2835_RNG);
107
+ object_property_add_child(obj, "rng", OBJECT(&s->rng), NULL);
108
+ qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default());
109
+
110
/* Extended Mass Media Controller */
111
object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
112
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
113
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
114
sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
115
qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
116
117
+ /* Random Number Generator */
118
+ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
119
+ if (err) {
120
+ error_propagate(errp, err);
121
+ return;
122
+ }
123
+
124
+ memory_region_add_subregion(&s->peri_mr, RNG_OFFSET,
125
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
126
+
127
/* Extended Mass Media Controller */
128
object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
129
&err);
130
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
131
new file mode 100644
132
index XXXXXXX..XXXXXXX
133
--- /dev/null
134
+++ b/hw/misc/bcm2835_rng.c
135
@@ -XXX,XX +XXX,XX @@
136
+/*
137
+ * BCM2835 Random Number Generator emulation
138
+ *
139
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
140
+ *
141
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
142
+ * See the COPYING file in the top-level directory.
143
+ */
144
+
145
+#include "qemu/osdep.h"
146
+#include "qemu/log.h"
147
+#include "hw/misc/bcm2835_rng.h"
148
+
149
+static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
150
+ unsigned size)
151
+{
152
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
153
+ uint32_t res = 0;
154
+
155
+ assert(size == 4);
156
+
157
+ switch (offset) {
158
+ case 0x0: /* rng_ctrl */
159
+ res = s->rng_ctrl;
160
+ break;
161
+ case 0x4: /* rng_status */
162
+ res = s->rng_status | (1 << 24);
163
+ break;
164
+ case 0x8: /* rng_data */
165
+ res = rand();
166
+ break;
167
+
168
+ default:
169
+ qemu_log_mask(LOG_GUEST_ERROR,
170
+ "bcm2835_rng_read: Bad offset %x\n",
171
+ (int)offset);
172
+ res = 0;
173
+ break;
174
+ }
175
+
176
+ return res;
177
+}
178
+
179
+static void bcm2835_rng_write(void *opaque, hwaddr offset,
180
+ uint64_t value, unsigned size)
181
+{
182
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
183
+
184
+ assert(size == 4);
185
+
186
+ switch (offset) {
187
+ case 0x0: /* rng_ctrl */
188
+ s->rng_ctrl = value;
189
+ break;
190
+ case 0x4: /* rng_status */
191
+ /* we shouldn't let the guest write to bits [31..20] */
192
+ s->rng_status &= ~0xFFFFF; /* clear 20 lower bits */
193
+ s->rng_status |= value & 0xFFFFF; /* set them to new value */
194
+ break;
195
+
196
+ default:
197
+ qemu_log_mask(LOG_GUEST_ERROR,
198
+ "bcm2835_rng_write: Bad offset %x\n",
199
+ (int)offset);
200
+ break;
201
+ }
202
+}
203
+
204
+static const MemoryRegionOps bcm2835_rng_ops = {
205
+ .read = bcm2835_rng_read,
206
+ .write = bcm2835_rng_write,
207
+ .endianness = DEVICE_NATIVE_ENDIAN,
208
+};
209
+
210
+static const VMStateDescription vmstate_bcm2835_rng = {
211
+ .name = TYPE_BCM2835_RNG,
212
+ .version_id = 1,
213
+ .minimum_version_id = 1,
214
+ .fields = (VMStateField[]) {
215
+ VMSTATE_UINT32(rng_ctrl, BCM2835RngState),
216
+ VMSTATE_UINT32(rng_status, BCM2835RngState),
217
+ VMSTATE_END_OF_LIST()
218
+ }
219
+};
220
+
221
+static void bcm2835_rng_init(Object *obj)
222
+{
223
+ BCM2835RngState *s = BCM2835_RNG(obj);
224
+
225
+ memory_region_init_io(&s->iomem, obj, &bcm2835_rng_ops, s,
226
+ TYPE_BCM2835_RNG, 0x10);
227
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
228
+}
229
+
230
+static void bcm2835_rng_reset(DeviceState *dev)
231
+{
232
+ BCM2835RngState *s = BCM2835_RNG(dev);
233
+
234
+ s->rng_ctrl = 0;
235
+ s->rng_status = 0;
236
+}
237
+
238
+static void bcm2835_rng_class_init(ObjectClass *klass, void *data)
239
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
242
+ dc->reset = bcm2835_rng_reset;
243
+ dc->vmsd = &vmstate_bcm2835_rng;
244
+}
245
+
246
+static TypeInfo bcm2835_rng_info = {
247
+ .name = TYPE_BCM2835_RNG,
248
+ .parent = TYPE_SYS_BUS_DEVICE,
249
+ .instance_size = sizeof(BCM2835RngState),
250
+ .class_init = bcm2835_rng_class_init,
251
+ .instance_init = bcm2835_rng_init,
252
+};
253
+
254
+static void bcm2835_rng_register_types(void)
255
+{
256
+ type_register_static(&bcm2835_rng_info);
257
+}
258
+
259
+type_init(bcm2835_rng_register_types)
260
--
261
2.7.4
262
263
diff view generated by jsdifflib
1
Implement the NVIC SHCSR write behaviour which allows pending and
1
In the Arm kernel/initrd loading code, in some places we make the
2
active status of some exceptions to be changed.
2
incorrect assumption that info->ram_size can be treated as the
3
address of the end of RAM, as for instance when we calculate the
4
available space for the initrd using "info->ram_size - info->initrd_start".
5
This is wrong, because many Arm boards (including "virt") specify
6
a non-zero info->loader_start to indicate that their RAM area
7
starts at a non-zero physical address.
8
9
Correct the places which make this incorrect assumption.
3
10
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Tested-by: Mark Rutland <mark.rutland@arm.com>
14
Message-id: 20190516144733.32399-2-peter.maydell@linaro.org
6
---
15
---
7
hw/intc/armv7m_nvic.c | 13 +++++++++++--
16
hw/arm/boot.c | 9 ++++-----
8
1 file changed, 11 insertions(+), 2 deletions(-)
17
1 file changed, 4 insertions(+), 5 deletions(-)
9
18
10
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
11
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/intc/armv7m_nvic.c
21
--- a/hw/arm/boot.c
13
+++ b/hw/intc/armv7m_nvic.c
22
+++ b/hw/arm/boot.c
14
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
23
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
15
cpu->env.v7m.ccr = value;
24
int elf_machine;
16
break;
25
hwaddr entry;
17
case 0xd24: /* System Handler Control. */
26
static const ARMInsnFixup *primary_loader;
18
- /* TODO: Real hardware allows you to set/clear the active bits
27
+ uint64_t ram_end = info->loader_start + info->ram_size;
19
- under some circumstances. We don't implement this. */
28
20
+ s->vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
29
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
21
+ s->vectors[ARMV7M_EXCP_BUS].active = (value & (1 << 1)) != 0;
30
primary_loader = bootloader_aarch64;
22
+ s->vectors[ARMV7M_EXCP_USAGE].active = (value & (1 << 3)) != 0;
31
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
23
+ s->vectors[ARMV7M_EXCP_SVC].active = (value & (1 << 7)) != 0;
32
/* 32-bit ARM */
24
+ s->vectors[ARMV7M_EXCP_DEBUG].active = (value & (1 << 8)) != 0;
33
entry = info->loader_start + KERNEL_LOAD_ADDR;
25
+ s->vectors[ARMV7M_EXCP_PENDSV].active = (value & (1 << 10)) != 0;
34
kernel_size = load_image_targphys_as(info->kernel_filename, entry,
26
+ s->vectors[ARMV7M_EXCP_SYSTICK].active = (value & (1 << 11)) != 0;
35
- info->ram_size - KERNEL_LOAD_ADDR,
27
+ s->vectors[ARMV7M_EXCP_USAGE].pending = (value & (1 << 12)) != 0;
36
- as);
28
+ s->vectors[ARMV7M_EXCP_MEM].pending = (value & (1 << 13)) != 0;
37
+ ram_end - KERNEL_LOAD_ADDR, as);
29
+ s->vectors[ARMV7M_EXCP_BUS].pending = (value & (1 << 14)) != 0;
38
is_linux = 1;
30
+ s->vectors[ARMV7M_EXCP_SVC].pending = (value & (1 << 15)) != 0;
39
}
31
s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
40
if (kernel_size < 0) {
32
s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
41
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
33
s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
42
if (info->initrd_filename) {
43
initrd_size = load_ramdisk_as(info->initrd_filename,
44
info->initrd_start,
45
- info->ram_size - info->initrd_start,
46
- as);
47
+ ram_end - info->initrd_start, as);
48
if (initrd_size < 0) {
49
initrd_size = load_image_targphys_as(info->initrd_filename,
50
info->initrd_start,
51
- info->ram_size -
52
+ ram_end -
53
info->initrd_start,
54
as);
55
}
34
--
56
--
35
2.7.4
57
2.20.1
36
58
37
59
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
We calculate the locations in memory where we want to put the
2
initrd and the DTB based on the size of the kernel, since they
3
come after it. Add some explicit checks that these aren't off the
4
end of RAM entirely.
2
5
3
The v7M exception architecture requires that if a synchronous
6
(At the moment the way we calculate the initrd_start means that
4
exception cannot be taken immediately (because it is disabled
7
it can't ever be off the end of RAM, but that will change with
5
or at too low a priority) then it should be escalated to
8
the next commit.)
6
HardFault (and the HardFault exception is then taken).
7
Implement this escalation logic.
8
9
9
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
10
[PMM: extracted from another patch]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Tested-by: Mark Rutland <mark.rutland@arm.com>
13
Message-id: 20190516144733.32399-3-peter.maydell@linaro.org
13
---
14
---
14
hw/intc/armv7m_nvic.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
15
hw/arm/boot.c | 23 +++++++++++++++++++++++
15
target/arm/helper.c | 2 --
16
1 file changed, 23 insertions(+)
16
2 files changed, 53 insertions(+), 2 deletions(-)
17
17
18
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
18
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/armv7m_nvic.c
20
--- a/hw/arm/boot.c
21
+++ b/hw/intc/armv7m_nvic.c
21
+++ b/hw/arm/boot.c
22
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
22
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
23
23
error_report("could not load kernel '%s'", info->kernel_filename);
24
vec = &s->vectors[irq];
24
exit(1);
25
trace_nvic_set_pending(irq, vec->enabled, vec->prio);
25
}
26
+
26
+
27
+ if (kernel_size > info->ram_size) {
28
+ error_report("kernel '%s' is too large to fit in RAM "
29
+ "(kernel size %d, RAM size %" PRId64 ")",
30
+ info->kernel_filename, kernel_size, info->ram_size);
31
+ exit(1);
32
+ }
27
+
33
+
28
+ if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
34
info->entry = entry;
29
+ /* If a synchronous exception is pending then it may be
35
if (is_linux) {
30
+ * escalated to HardFault if:
36
uint32_t fixupcontext[FIXUP_MAX];
31
+ * * it is equal or lower priority to current execution
37
32
+ * * it is disabled
38
if (info->initrd_filename) {
33
+ * (ie we need to take it immediately but we can't do so).
34
+ * Asynchronous exceptions (and interrupts) simply remain pending.
35
+ *
36
+ * For QEMU, we don't have any imprecise (asynchronous) faults,
37
+ * so we can assume that PREFETCH_ABORT and DATA_ABORT are always
38
+ * synchronous.
39
+ * Debug exceptions are awkward because only Debug exceptions
40
+ * resulting from the BKPT instruction should be escalated,
41
+ * but we don't currently implement any Debug exceptions other
42
+ * than those that result from BKPT, so we treat all debug exceptions
43
+ * as needing escalation.
44
+ *
45
+ * This all means we can identify whether to escalate based only on
46
+ * the exception number and don't (yet) need the caller to explicitly
47
+ * tell us whether this exception is synchronous or not.
48
+ */
49
+ int running = nvic_exec_prio(s);
50
+ bool escalate = false;
51
+
39
+
52
+ if (vec->prio >= running) {
40
+ if (info->initrd_start >= ram_end) {
53
+ trace_nvic_escalate_prio(irq, vec->prio, running);
41
+ error_report("not enough space after kernel to load initrd");
54
+ escalate = true;
42
+ exit(1);
55
+ } else if (!vec->enabled) {
56
+ trace_nvic_escalate_disabled(irq);
57
+ escalate = true;
58
+ }
59
+
60
+ if (escalate) {
61
+ if (running < 0) {
62
+ /* We want to escalate to HardFault but we can't take a
63
+ * synchronous HardFault at this point either. This is a
64
+ * Lockup condition due to a guest bug. We don't model
65
+ * Lockup, so report via cpu_abort() instead.
66
+ */
67
+ cpu_abort(&s->cpu->parent_obj,
68
+ "Lockup: can't escalate %d to HardFault "
69
+ "(current priority %d)\n", irq, running);
70
+ }
43
+ }
71
+
44
+
72
+ /* We can do the escalation, so we take HardFault instead */
45
initrd_size = load_ramdisk_as(info->initrd_filename,
73
+ irq = ARMV7M_EXCP_HARD;
46
info->initrd_start,
74
+ vec = &s->vectors[irq];
47
ram_end - info->initrd_start, as);
75
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
48
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
76
+ }
49
info->initrd_filename);
77
+ }
50
exit(1);
78
+
51
}
79
if (!vec->pending) {
52
+ if (info->initrd_start + initrd_size > info->ram_size) {
80
vec->pending = 1;
53
+ error_report("could not load initrd '%s': "
81
nvic_irq_update(s);
54
+ "too big to fit into RAM after the kernel",
82
diff --git a/target/arm/helper.c b/target/arm/helper.c
55
+ info->initrd_filename);
83
index XXXXXXX..XXXXXXX 100644
56
+ }
84
--- a/target/arm/helper.c
57
} else {
85
+++ b/target/arm/helper.c
58
initrd_size = 0;
86
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
59
}
87
60
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
88
/* For exceptions we just mark as pending on the NVIC, and let that
61
/* Place the DTB after the initrd in memory with alignment. */
89
handle it. */
62
info->dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
90
- /* TODO: Need to escalate if the current priority is higher than the
63
align);
91
- one we're raising. */
64
+ if (info->dtb_start >= ram_end) {
92
switch (cs->exception_index) {
65
+ error_report("Not enough space for DTB after kernel/initrd");
93
case EXCP_UDEF:
66
+ exit(1);
94
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
67
+ }
68
fixupcontext[FIXUP_ARGPTR_LO] = info->dtb_start;
69
fixupcontext[FIXUP_ARGPTR_HI] = info->dtb_start >> 32;
70
} else {
95
--
71
--
96
2.7.4
72
2.20.1
97
73
98
74
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
We currently put the initrd at the smaller of:
2
* 128MB into RAM
3
* halfway into the RAM
4
(with the dtb following it).
2
5
3
All the places in armv7m_cpu_do_interrupt() which pend an
6
However for large kernels this might mean that the kernel
4
exception in the NVIC are doing so for synchronous
7
overlaps the initrd. For some kinds of kernel (self-decompressing
5
exceptions. We know that we will always take some
8
32-bit kernels, and ELF images with a BSS section at the end)
6
exception in this case, so we can just acknowledge it
9
we don't know the exact size, but even there we have a
7
immediately, rather than returning and then immediately
10
minimum size. Put the initrd at least further into RAM than
8
being called again because the NVIC has raised its outbound
11
that. For image formats that can give us an exact kernel size, this
9
IRQ line.
12
will mean that we definitely avoid overlaying kernel and initrd.
10
13
11
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
12
[PMM: tweaked commit message; added DEBUG to the set of
13
exceptions we handle immediately, since it is synchronous
14
when it results from the BKPT instruction]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
16
Tested-by: Mark Rutland <mark.rutland@arm.com>
17
Message-id: 20190516144733.32399-4-peter.maydell@linaro.org
17
---
18
---
18
target/arm/helper.c | 15 +++++++++------
19
hw/arm/boot.c | 34 ++++++++++++++++++++--------------
19
1 file changed, 9 insertions(+), 6 deletions(-)
20
1 file changed, 20 insertions(+), 14 deletions(-)
20
21
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
--- a/hw/arm/boot.c
24
+++ b/target/arm/helper.c
25
+++ b/hw/arm/boot.c
25
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
26
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
26
case EXCP_UDEF:
27
if (info->nb_cpus == 0)
27
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
28
info->nb_cpus = 1;
28
env->v7m.cfsr |= R_V7M_CFSR_UNDEFINSTR_MASK;
29
29
- return;
30
- /*
30
+ break;
31
- * We want to put the initrd far enough into RAM that when the
31
case EXCP_NOCP:
32
- * kernel is uncompressed it will not clobber the initrd. However
32
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
33
- * on boards without much RAM we must ensure that we still leave
33
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
34
- * enough room for a decent sized initrd, and on boards with large
34
- return;
35
- * amounts of RAM we must avoid the initrd being so far up in RAM
35
+ break;
36
- * that it is outside lowmem and inaccessible to the kernel.
36
case EXCP_SWI:
37
- * So for boards with less than 256MB of RAM we put the initrd
37
/* The PC already points to the next instruction. */
38
- * halfway into RAM, and for boards with 256MB of RAM or more we put
38
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
39
- * the initrd at 128MB.
39
- return;
40
- */
40
+ break;
41
- info->initrd_start = info->loader_start +
41
case EXCP_PREFETCH_ABORT:
42
- MIN(info->ram_size / 2, 128 * 1024 * 1024);
42
case EXCP_DATA_ABORT:
43
-
43
/* TODO: if we implemented the MPU registers, this is where we
44
/* Assume that raw images are linux kernels, and ELF images are not. */
44
* should set the MMFAR, etc from exception.fsr and exception.vaddress.
45
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
45
*/
46
&elf_high_addr, elf_machine, as);
46
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
47
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
47
- return;
48
+ break;
49
case EXCP_BKPT:
50
if (semihosting_enabled()) {
51
int nr;
52
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
53
}
54
}
55
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
56
- return;
57
+ break;
58
case EXCP_IRQ:
59
- armv7m_nvic_acknowledge_irq(env->nvic);
60
break;
61
case EXCP_EXCEPTION_EXIT:
62
do_v7m_exception_exit(env);
63
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
64
return; /* Never happens. Keep compiler happy. */
65
}
48
}
66
49
67
+ armv7m_nvic_acknowledge_irq(env->nvic);
50
info->entry = entry;
68
+
51
+
69
+ qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
52
+ /*
53
+ * We want to put the initrd far enough into RAM that when the
54
+ * kernel is uncompressed it will not clobber the initrd. However
55
+ * on boards without much RAM we must ensure that we still leave
56
+ * enough room for a decent sized initrd, and on boards with large
57
+ * amounts of RAM we must avoid the initrd being so far up in RAM
58
+ * that it is outside lowmem and inaccessible to the kernel.
59
+ * So for boards with less than 256MB of RAM we put the initrd
60
+ * halfway into RAM, and for boards with 256MB of RAM or more we put
61
+ * the initrd at 128MB.
62
+ * We also refuse to put the initrd somewhere that will definitely
63
+ * overlay the kernel we just loaded, though for kernel formats which
64
+ * don't tell us their exact size (eg self-decompressing 32-bit kernels)
65
+ * we might still make a bad choice here.
66
+ */
67
+ info->initrd_start = info->loader_start +
68
+ MAX(MIN(info->ram_size / 2, 128 * 1024 * 1024), kernel_size);
69
+ info->initrd_start = TARGET_PAGE_ALIGN(info->initrd_start);
70
+
70
+
71
/* Align stack pointer if the guest wants that */
71
if (is_linux) {
72
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
72
uint32_t fixupcontext[FIXUP_MAX];
73
env->regs[13] -= 4;
73
74
--
74
--
75
2.7.4
75
2.20.1
76
76
77
77
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
Since Linux v3.17, the kernel's Image header includes a field image_size,
2
which gives the total size of the kernel including unpopulated data
3
sections such as the BSS). If this is present, then return it from
4
load_aarch64_image() as the true size of the kernel rather than
5
just using the size of the Image file itself. This allows the code
6
which calculates where to put the initrd to avoid putting it in
7
the kernel's BSS area.
2
8
3
This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform.
9
This means that we should be able to reliably load kernel images
10
which are larger than 128MB without accidentally putting the
11
initrd or dtb in locations that clash with the kernel itself.
4
12
5
For supporting the SD controller selection (alternate function of GPIOs
13
Fixes: https://bugs.launchpad.net/qemu/+bug/1823998
6
48-53), the bcm2835_gpio now exposes an sdbus.
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
It also has a link to both the sdbus of sdhci and sdhost controllers,
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
and the card is reparented from one bus to another when the alternate
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
function of GPIOs 48-53 is modified.
17
Tested-by: Mark Rutland <mark.rutland@arm.com>
18
Message-id: 20190516144733.32399-5-peter.maydell@linaro.org
19
---
20
hw/arm/boot.c | 17 +++++++++++++++--
21
1 file changed, 15 insertions(+), 2 deletions(-)
10
22
11
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
23
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
12
Message-id: 20170224164021.9066-5-clement.deschamps@antfield.fr
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
include/hw/arm/bcm2835_peripherals.h | 4 ++++
17
hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++++--
18
2 files changed, 45 insertions(+), 2 deletions(-)
19
20
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
21
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2835_peripherals.h
25
--- a/hw/arm/boot.c
23
+++ b/include/hw/arm/bcm2835_peripherals.h
26
+++ b/hw/arm/boot.c
24
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
25
#include "hw/misc/bcm2835_rng.h"
28
hwaddr *entry, AddressSpace *as)
26
#include "hw/misc/bcm2835_mbox.h"
29
{
27
#include "hw/sd/sdhci.h"
30
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
28
+#include "hw/sd/bcm2835_sdhost.h"
31
+ uint64_t kernel_size = 0;
29
+#include "hw/gpio/bcm2835_gpio.h"
32
uint8_t *buffer;
30
33
int size;
31
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
34
32
#define BCM2835_PERIPHERALS(obj) \
35
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
33
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
36
* is only valid if the image_size is non-zero.
34
BCM2835RngState rng;
37
*/
35
BCM2835MboxState mboxes;
38
memcpy(&hdrvals, buffer + ARM64_TEXT_OFFSET_OFFSET, sizeof(hdrvals));
36
SDHCIState sdhci;
39
- if (hdrvals[1] != 0) {
37
+ BCM2835SDHostState sdhost;
38
+ BCM2835GpioState gpio;
39
} BCM2835PeripheralState;
40
41
#endif /* BCM2835_PERIPHERALS_H */
42
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/bcm2835_peripherals.c
45
+++ b/hw/arm/bcm2835_peripherals.c
46
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
47
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
48
qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
49
50
+ /* SDHOST */
51
+ object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST);
52
+ object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL);
53
+ qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default());
54
+
40
+
55
/* DMA Channels */
41
+ kernel_size = le64_to_cpu(hdrvals[1]);
56
object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA);
57
object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL);
58
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
59
60
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
61
OBJECT(&s->gpu_bus_mr), &error_abort);
62
+
42
+
63
+ /* GPIO */
43
+ if (kernel_size != 0) {
64
+ object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO);
44
kernel_load_offset = le64_to_cpu(hdrvals[0]);
65
+ object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL);
45
66
+ qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default());
46
/*
67
+
47
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
68
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
48
}
69
+ OBJECT(&s->sdhci.sdbus), &error_abort);
70
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
71
+ OBJECT(&s->sdhost.sdbus), &error_abort);
72
}
73
74
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
75
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
76
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
77
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
78
INTERRUPT_ARASANSDIO));
79
- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-bus",
80
- &err);
81
+
82
+ /* SDHOST */
83
+ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err);
84
if (err) {
85
error_propagate(errp, err);
86
return;
87
}
49
}
88
50
89
+ memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET,
51
+ /*
90
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0));
52
+ * Kernels before v3.17 don't populate the image_size field, and
91
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0,
53
+ * raw images have no header. For those our best guess at the size
92
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
54
+ * is the size of the Image file itself.
93
+ INTERRUPT_SDIO));
55
+ */
94
+
56
+ if (kernel_size == 0) {
95
/* DMA Channels */
57
+ kernel_size = size;
96
object_property_set_bool(OBJECT(&s->dma), true, "realized", &err);
97
if (err) {
98
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
99
BCM2835_IC_GPU_IRQ,
100
INTERRUPT_DMA0 + n));
101
}
102
+
103
+ /* GPIO */
104
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
105
+ if (err) {
106
+ error_propagate(errp, err);
107
+ return;
108
+ }
58
+ }
109
+
59
+
110
+ memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
60
*entry = mem_base + kernel_load_offset;
111
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
61
rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
112
+
62
113
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus",
63
g_free(buffer);
114
+ &err);
64
115
+ if (err) {
65
- return size;
116
+ error_propagate(errp, err);
66
+ return kernel_size;
117
+ return;
118
+ }
119
}
67
}
120
68
121
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
69
static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
122
--
70
--
123
2.7.4
71
2.20.1
124
72
125
73
diff view generated by jsdifflib
1
The M profile condition for when we can take a pending exception or
1
Allow VFP and neon to be disabled via a CPU property. As with
2
interrupt is not the same as that for A/R profile. The code
2
the "pmu" property, we only allow these features to be removed
3
originally copied from the A/R profile version of the
3
from CPUs which have it by default, not added to CPUs which
4
cpu_exec_interrupt function only worked by chance for the
4
don't have it.
5
very simple case of exceptions being masked by PRIMASK.
5
6
Replace it with a call to a function in the NVIC code that
6
The primary motivation here is to be able to optionally
7
correctly compares the priority of the pending exception
7
create Cortex-M33 CPUs with no FPU, but we provide switches
8
against the current execution priority of the CPU.
8
for both VFP and Neon because the two interact:
9
9
* AArch64 can't have one without the other
10
[Michael Davidsaver's patchset had a patch to do something
10
* Some ID register fields only change if both are disabled
11
similar but the implementation ended up being a rewrite.]
12
11
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Message-id: 20190517174046.11146-2-peter.maydell@linaro.org
15
---
16
---
16
target/arm/cpu.h | 8 ++++++++
17
target/arm/cpu.h | 4 ++
17
hw/intc/armv7m_nvic.c | 7 +++++++
18
target/arm/cpu.c | 150 +++++++++++++++++++++++++++++++++++++++++++++--
18
target/arm/cpu.c | 16 ++++++++--------
19
2 files changed, 148 insertions(+), 6 deletions(-)
19
3 files changed, 23 insertions(+), 8 deletions(-)
20
20
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
23
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
25
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
26
uint32_t cur_el, bool secure);
26
bool has_el3;
27
27
/* CPU has PMU (Performance Monitor Unit) */
28
/* Interface between CPU and Interrupt controller. */
28
bool has_pmu;
29
+#ifndef CONFIG_USER_ONLY
29
+ /* CPU has VFP */
30
+bool armv7m_nvic_can_take_pending_exception(void *opaque);
30
+ bool has_vfp;
31
+#else
31
+ /* CPU has Neon */
32
+static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
32
+ bool has_neon;
33
+{
33
34
+ return true;
34
/* CPU has memory protection unit */
35
+}
35
bool has_mpu;
36
+#endif
37
void armv7m_nvic_set_pending(void *opaque, int irq);
38
int armv7m_nvic_acknowledge_irq(void *opaque);
39
void armv7m_nvic_complete_irq(void *opaque, int irq);
40
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/armv7m_nvic.c
43
+++ b/hw/intc/armv7m_nvic.c
44
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
45
return MIN(running, s->exception_prio);
46
}
47
48
+bool armv7m_nvic_can_take_pending_exception(void *opaque)
49
+{
50
+ NVICState *s = opaque;
51
+
52
+ return nvic_exec_prio(s) > nvic_pending_prio(s);
53
+}
54
+
55
/* caller must call nvic_irq_update() after this */
56
static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
57
{
58
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
36
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/cpu.c
38
--- a/target/arm/cpu.c
61
+++ b/target/arm/cpu.c
39
+++ b/target/arm/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
40
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_cfgend_property =
63
CPUARMState *env = &cpu->env;
41
static Property arm_cpu_has_pmu_property =
64
bool ret = false;
42
DEFINE_PROP_BOOL("pmu", ARMCPU, has_pmu, true);
65
43
66
-
44
+static Property arm_cpu_has_vfp_property =
67
- if (interrupt_request & CPU_INTERRUPT_FIQ
45
+ DEFINE_PROP_BOOL("vfp", ARMCPU, has_vfp, true);
68
- && !(env->daif & PSTATE_F)) {
46
+
69
- cs->exception_index = EXCP_FIQ;
47
+static Property arm_cpu_has_neon_property =
70
- cc->do_interrupt(cs);
48
+ DEFINE_PROP_BOOL("neon", ARMCPU, has_neon, true);
71
- ret = true;
49
+
50
static Property arm_cpu_has_mpu_property =
51
DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
52
53
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
54
if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
55
set_feature(&cpu->env, ARM_FEATURE_PMSA);
56
}
57
+ /* Similarly for the VFP feature bits */
58
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP4)) {
59
+ set_feature(&cpu->env, ARM_FEATURE_VFP3);
60
+ }
61
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP3)) {
62
+ set_feature(&cpu->env, ARM_FEATURE_VFP);
63
+ }
64
65
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
66
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
67
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
68
&error_abort);
69
}
70
71
+ /*
72
+ * Allow user to turn off VFP and Neon support, but only for TCG --
73
+ * KVM does not currently allow us to lie to the guest about its
74
+ * ID/feature registers, so the guest always sees what the host has.
75
+ */
76
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
77
+ cpu->has_vfp = true;
78
+ if (!kvm_enabled()) {
79
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_has_vfp_property,
80
+ &error_abort);
81
+ }
82
+ }
83
+
84
+ if (arm_feature(&cpu->env, ARM_FEATURE_NEON)) {
85
+ cpu->has_neon = true;
86
+ if (!kvm_enabled()) {
87
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_has_neon_property,
88
+ &error_abort);
89
+ }
90
+ }
91
+
92
if (arm_feature(&cpu->env, ARM_FEATURE_PMSA)) {
93
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_mpu_property,
94
&error_abort);
95
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
96
return;
97
}
98
99
+ if (arm_feature(env, ARM_FEATURE_AARCH64) &&
100
+ cpu->has_vfp != cpu->has_neon) {
101
+ /*
102
+ * This is an architectural requirement for AArch64; AArch32 is
103
+ * more flexible and permits VFP-no-Neon and Neon-no-VFP.
104
+ */
105
+ error_setg(errp,
106
+ "AArch64 CPUs must have both VFP and Neon or neither");
107
+ return;
108
+ }
109
+
110
+ if (!cpu->has_vfp) {
111
+ uint64_t t;
112
+ uint32_t u;
113
+
114
+ unset_feature(env, ARM_FEATURE_VFP);
115
+ unset_feature(env, ARM_FEATURE_VFP3);
116
+ unset_feature(env, ARM_FEATURE_VFP4);
117
+
118
+ t = cpu->isar.id_aa64isar1;
119
+ t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0);
120
+ cpu->isar.id_aa64isar1 = t;
121
+
122
+ t = cpu->isar.id_aa64pfr0;
123
+ t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf);
124
+ cpu->isar.id_aa64pfr0 = t;
125
+
126
+ u = cpu->isar.id_isar6;
127
+ u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0);
128
+ cpu->isar.id_isar6 = u;
129
+
130
+ u = cpu->isar.mvfr0;
131
+ u = FIELD_DP32(u, MVFR0, FPSP, 0);
132
+ u = FIELD_DP32(u, MVFR0, FPDP, 0);
133
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
134
+ u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
135
+ u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
136
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
137
+ u = FIELD_DP32(u, MVFR0, FPROUND, 0);
138
+ cpu->isar.mvfr0 = u;
139
+
140
+ u = cpu->isar.mvfr1;
141
+ u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
142
+ u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
143
+ u = FIELD_DP32(u, MVFR1, FPHP, 0);
144
+ cpu->isar.mvfr1 = u;
145
+
146
+ u = cpu->isar.mvfr2;
147
+ u = FIELD_DP32(u, MVFR2, FPMISC, 0);
148
+ cpu->isar.mvfr2 = u;
149
+ }
150
+
151
+ if (!cpu->has_neon) {
152
+ uint64_t t;
153
+ uint32_t u;
154
+
155
+ unset_feature(env, ARM_FEATURE_NEON);
156
+
157
+ t = cpu->isar.id_aa64isar0;
158
+ t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0);
159
+ cpu->isar.id_aa64isar0 = t;
160
+
161
+ t = cpu->isar.id_aa64isar1;
162
+ t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0);
163
+ cpu->isar.id_aa64isar1 = t;
164
+
165
+ t = cpu->isar.id_aa64pfr0;
166
+ t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf);
167
+ cpu->isar.id_aa64pfr0 = t;
168
+
169
+ u = cpu->isar.id_isar5;
170
+ u = FIELD_DP32(u, ID_ISAR5, RDM, 0);
171
+ u = FIELD_DP32(u, ID_ISAR5, VCMA, 0);
172
+ cpu->isar.id_isar5 = u;
173
+
174
+ u = cpu->isar.id_isar6;
175
+ u = FIELD_DP32(u, ID_ISAR6, DP, 0);
176
+ u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
177
+ cpu->isar.id_isar6 = u;
178
+
179
+ u = cpu->isar.mvfr1;
180
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
181
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
182
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
183
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
184
+ u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0);
185
+ cpu->isar.mvfr1 = u;
186
+
187
+ u = cpu->isar.mvfr2;
188
+ u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
189
+ cpu->isar.mvfr2 = u;
190
+ }
191
+
192
+ if (!cpu->has_neon && !cpu->has_vfp) {
193
+ uint64_t t;
194
+ uint32_t u;
195
+
196
+ t = cpu->isar.id_aa64isar0;
197
+ t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0);
198
+ cpu->isar.id_aa64isar0 = t;
199
+
200
+ t = cpu->isar.id_aa64isar1;
201
+ t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0);
202
+ cpu->isar.id_aa64isar1 = t;
203
+
204
+ u = cpu->isar.mvfr0;
205
+ u = FIELD_DP32(u, MVFR0, SIMDREG, 0);
206
+ cpu->isar.mvfr0 = u;
207
+ }
208
+
209
/* Some features automatically imply others: */
210
if (arm_feature(env, ARM_FEATURE_V8)) {
211
if (arm_feature(env, ARM_FEATURE_M)) {
212
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
213
if (arm_feature(env, ARM_FEATURE_V5)) {
214
set_feature(env, ARM_FEATURE_V4T);
215
}
216
- if (arm_feature(env, ARM_FEATURE_VFP4)) {
217
- set_feature(env, ARM_FEATURE_VFP3);
72
- }
218
- }
73
/* ARMv7-M interrupt return works by loading a magic value
219
- if (arm_feature(env, ARM_FEATURE_VFP3)) {
74
* into the PC. On real hardware the load causes the
220
- set_feature(env, ARM_FEATURE_VFP);
75
* return to occur. The qemu implementation performs the
221
- }
76
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
222
if (arm_feature(env, ARM_FEATURE_LPAE)) {
77
* the stack if an interrupt occurred at the wrong time.
223
set_feature(env, ARM_FEATURE_V7MP);
78
* We avoid this by disabling interrupts when
224
set_feature(env, ARM_FEATURE_PXN);
79
* pc contains a magic address.
80
+ *
81
+ * ARMv7-M interrupt masking works differently than -A or -R.
82
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
83
+ * masking FIQ and IRQ interrupts, an exception is taken only
84
+ * if it is higher priority than the current execution priority
85
+ * (which depends on state like BASEPRI, FAULTMASK and the
86
+ * currently active exception).
87
*/
88
if (interrupt_request & CPU_INTERRUPT_HARD
89
- && !(env->daif & PSTATE_I)
90
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))
91
&& (env->regs[15] < 0xfffffff0)) {
92
cs->exception_index = EXCP_IRQ;
93
cc->do_interrupt(cs);
94
--
225
--
95
2.7.4
226
2.20.1
96
227
97
228
diff view generated by jsdifflib
1
Implement the exception return consistency checks
1
Allow the DSP extension to be disabled via a CPU property for
2
described in the v7M pseudocode ExceptionReturn().
2
M-profile CPUs. (A and R-profile CPUs don't have this extension
3
3
as a defined separate optional architecture extension, so
4
Inspired by a patch from Michael Davidsaver's series, but
4
they don't need the property.)
5
this is a reimplementation from scratch based on the
6
ARM ARM pseudocode.
7
5
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20190517174046.11146-3-peter.maydell@linaro.org
10
---
10
---
11
target/arm/cpu.h | 12 +++++-
11
target/arm/cpu.h | 2 ++
12
hw/intc/armv7m_nvic.c | 12 +++++-
12
target/arm/cpu.c | 29 +++++++++++++++++++++++++++++
13
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++++++-----
13
2 files changed, 31 insertions(+)
14
3 files changed, 123 insertions(+), 13 deletions(-)
15
14
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
19
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
#endif
20
bool has_vfp;
22
void armv7m_nvic_set_pending(void *opaque, int irq);
21
/* CPU has Neon */
23
void armv7m_nvic_acknowledge_irq(void *opaque);
22
bool has_neon;
24
-void armv7m_nvic_complete_irq(void *opaque, int irq);
23
+ /* CPU has M-profile DSP extension */
25
+/**
24
+ bool has_dsp;
26
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
25
27
+ * @opaque: the NVIC
26
/* CPU has memory protection unit */
28
+ * @irq: the exception number to complete
27
bool has_mpu;
29
+ *
28
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
+ * Returns: -1 if the irq was not active
31
+ * 1 if completing this irq brought us back to base (no active irqs)
32
+ * 0 if there is still an irq active after this one was completed
33
+ * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
34
+ */
35
+int armv7m_nvic_complete_irq(void *opaque, int irq);
36
37
/* Interface for defining coprocessor registers.
38
* Registers are defined in tables of arm_cp_reginfo structs
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
30
--- a/target/arm/cpu.c
42
+++ b/hw/intc/armv7m_nvic.c
31
+++ b/target/arm/cpu.c
43
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque)
32
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_has_vfp_property =
44
nvic_irq_update(s);
33
static Property arm_cpu_has_neon_property =
45
}
34
DEFINE_PROP_BOOL("neon", ARMCPU, has_neon, true);
46
35
47
-void armv7m_nvic_complete_irq(void *opaque, int irq)
36
+static Property arm_cpu_has_dsp_property =
48
+int armv7m_nvic_complete_irq(void *opaque, int irq)
37
+ DEFINE_PROP_BOOL("dsp", ARMCPU, has_dsp, true);
49
{
38
+
50
NVICState *s = (NVICState *)opaque;
39
static Property arm_cpu_has_mpu_property =
51
VecInfo *vec;
40
DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
52
+ int ret;
41
53
42
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
54
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
43
}
55
44
}
56
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
45
57
46
+ if (arm_feature(&cpu->env, ARM_FEATURE_M) &&
58
trace_nvic_complete_irq(irq);
47
+ arm_feature(&cpu->env, ARM_FEATURE_THUMB_DSP)) {
59
48
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_has_dsp_property,
60
+ if (!vec->active) {
49
+ &error_abort);
61
+ /* Tell the caller this was an illegal exception return */
62
+ return -1;
63
+ }
50
+ }
64
+
51
+
65
+ ret = nvic_rettobase(s);
52
if (arm_feature(&cpu->env, ARM_FEATURE_PMSA)) {
53
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_mpu_property,
54
&error_abort);
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
56
cpu->isar.mvfr0 = u;
57
}
58
59
+ if (arm_feature(env, ARM_FEATURE_M) && !cpu->has_dsp) {
60
+ uint32_t u;
66
+
61
+
67
vec->active = 0;
62
+ unset_feature(env, ARM_FEATURE_THUMB_DSP);
68
if (vec->level) {
69
/* Re-pend the exception if it's still held high; only
70
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
71
}
72
73
nvic_irq_update(s);
74
+
63
+
75
+ return ret;
64
+ u = cpu->isar.id_isar1;
76
}
65
+ u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1);
77
66
+ cpu->isar.id_isar1 = u;
78
/* callback when external interrupt line is changed */
79
diff --git a/target/arm/helper.c b/target/arm/helper.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/helper.c
82
+++ b/target/arm/helper.c
83
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
84
v7m_push(env, env->regs[0]);
85
}
86
87
-static void do_v7m_exception_exit(CPUARMState *env)
88
+static void do_v7m_exception_exit(ARMCPU *cpu)
89
{
90
+ CPUARMState *env = &cpu->env;
91
uint32_t type;
92
uint32_t xpsr;
93
-
94
+ bool ufault = false;
95
+ bool return_to_sp_process = false;
96
+ bool return_to_handler = false;
97
+ bool rettobase = false;
98
+
67
+
99
+ /* We can only get here from an EXCP_EXCEPTION_EXIT, and
68
+ u = cpu->isar.id_isar2;
100
+ * arm_v7m_do_unassigned_access() enforces the architectural rule
69
+ u = FIELD_DP32(u, ID_ISAR2, MULTU, 1);
101
+ * that jumps to magic addresses don't have magic behaviour unless
70
+ u = FIELD_DP32(u, ID_ISAR2, MULTS, 1);
102
+ * we're in Handler mode (compare pseudocode BXWritePC()).
71
+ cpu->isar.id_isar2 = u;
103
+ */
104
+ assert(env->v7m.exception != 0);
105
+
72
+
106
+ /* In the spec pseudocode ExceptionReturn() is called directly
73
+ u = cpu->isar.id_isar3;
107
+ * from BXWritePC() and gets the full target PC value including
74
+ u = FIELD_DP32(u, ID_ISAR3, SIMD, 1);
108
+ * bit zero. In QEMU's implementation we treat it as a normal
75
+ u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0);
109
+ * jump-to-register (which is then caught later on), and so split
76
+ cpu->isar.id_isar3 = u;
110
+ * the target value up between env->regs[15] and env->thumb in
111
+ * gen_bx(). Reconstitute it.
112
+ */
113
type = env->regs[15];
114
+ if (env->thumb) {
115
+ type |= 1;
116
+ }
77
+ }
117
+
78
+
118
+ qemu_log_mask(CPU_LOG_INT, "Exception return: magic PC %" PRIx32
79
/* Some features automatically imply others: */
119
+ " previous exception %d\n",
80
if (arm_feature(env, ARM_FEATURE_V8)) {
120
+ type, env->v7m.exception);
81
if (arm_feature(env, ARM_FEATURE_M)) {
121
+
122
+ if (extract32(type, 5, 23) != extract32(-1, 5, 23)) {
123
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero high bits in exception "
124
+ "exit PC value 0x%" PRIx32 " are UNPREDICTABLE\n", type);
125
+ }
126
+
127
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
128
/* Auto-clear FAULTMASK on return from other than NMI */
129
env->daif &= ~PSTATE_F;
130
}
131
- if (env->v7m.exception != 0) {
132
- armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
133
+
134
+ switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
135
+ case -1:
136
+ /* attempt to exit an exception that isn't active */
137
+ ufault = true;
138
+ break;
139
+ case 0:
140
+ /* still an irq active now */
141
+ break;
142
+ case 1:
143
+ /* we returned to base exception level, no nesting.
144
+ * (In the pseudocode this is written using "NestedActivation != 1"
145
+ * where we have 'rettobase == false'.)
146
+ */
147
+ rettobase = true;
148
+ break;
149
+ default:
150
+ g_assert_not_reached();
151
+ }
152
+
153
+ switch (type & 0xf) {
154
+ case 1: /* Return to Handler */
155
+ return_to_handler = true;
156
+ break;
157
+ case 13: /* Return to Thread using Process stack */
158
+ return_to_sp_process = true;
159
+ /* fall through */
160
+ case 9: /* Return to Thread using Main stack */
161
+ if (!rettobase &&
162
+ !(env->v7m.ccr & R_V7M_CCR_NONBASETHRDENA_MASK)) {
163
+ ufault = true;
164
+ }
165
+ break;
166
+ default:
167
+ ufault = true;
168
+ }
169
+
170
+ if (ufault) {
171
+ /* Bad exception return: instead of popping the exception
172
+ * stack, directly take a usage fault on the current stack.
173
+ */
174
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
175
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
176
+ v7m_exception_taken(cpu, type | 0xf0000000);
177
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
178
+ "stackframe: failed exception return integrity check\n");
179
+ return;
180
}
181
182
/* Switch to the target stack. */
183
- switch_v7m_sp(env, (type & 4) != 0);
184
+ switch_v7m_sp(env, return_to_sp_process);
185
/* Pop registers. */
186
env->regs[0] = v7m_pop(env);
187
env->regs[1] = v7m_pop(env);
188
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(CPUARMState *env)
189
/* Undo stack alignment. */
190
if (xpsr & 0x200)
191
env->regs[13] |= 4;
192
- /* ??? The exception return type specifies Thread/Handler mode. However
193
- this is also implied by the xPSR value. Not sure what to do
194
- if there is a mismatch. */
195
- /* ??? Likewise for mismatches between the CONTROL register and the stack
196
- pointer. */
197
+
198
+ /* The restored xPSR exception field will be zero if we're
199
+ * resuming in Thread mode. If that doesn't match what the
200
+ * exception return type specified then this is a UsageFault.
201
+ */
202
+ if (return_to_handler == (env->v7m.exception == 0)) {
203
+ /* Take an INVPC UsageFault by pushing the stack again. */
204
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
205
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
206
+ v7m_push_stack(cpu);
207
+ v7m_exception_taken(cpu, type | 0xf0000000);
208
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
209
+ "failed exception return integrity check\n");
210
+ return;
211
+ }
212
+
213
+ /* Otherwise, we have a successful exception exit. */
214
+ qemu_log_mask(CPU_LOG_INT, "...successful exception return\n");
215
}
216
217
static void arm_log_exception(int idx)
218
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
219
case EXCP_IRQ:
220
break;
221
case EXCP_EXCEPTION_EXIT:
222
- do_v7m_exception_exit(env);
223
+ do_v7m_exception_exit(cpu);
224
return;
225
default:
226
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
227
--
82
--
228
2.7.4
83
2.20.1
229
84
230
85
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
Create "vfp" and "dsp" properties on the armv7m container object
2
which will be forwarded to its CPU object, so that SoCs can
3
configure whether the CPU has these features.
2
4
3
This adds the BCM2835 GPIO controller.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20190517174046.11146-4-peter.maydell@linaro.org
9
---
10
include/hw/arm/armv7m.h | 4 ++++
11
hw/arm/armv7m.c | 18 ++++++++++++++++++
12
2 files changed, 22 insertions(+)
4
13
5
It currently implements:
14
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
6
- The 54 GPIOs as outputs (qemu_irq)
7
- The SD controller selection via alternate function of GPIOs 48-53
8
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
10
Message-id: 20170224164021.9066-4-clement.deschamps@antfield.fr
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/gpio/Makefile.objs | 1 +
15
include/hw/gpio/bcm2835_gpio.h | 39 +++++
16
hw/gpio/bcm2835_gpio.c | 353 +++++++++++++++++++++++++++++++++++++++++
17
3 files changed, 393 insertions(+)
18
create mode 100644 include/hw/gpio/bcm2835_gpio.h
19
create mode 100644 hw/gpio/bcm2835_gpio.c
20
21
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/gpio/Makefile.objs
16
--- a/include/hw/arm/armv7m.h
24
+++ b/hw/gpio/Makefile.objs
17
+++ b/include/hw/arm/armv7m.h
25
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
18
@@ -XXX,XX +XXX,XX @@ typedef struct {
26
19
* devices will be automatically layered on top of this view.)
27
obj-$(CONFIG_OMAP) += omap_gpio.o
20
* + Property "idau": IDAU interface (forwarded to CPU object)
28
obj-$(CONFIG_IMX) += imx_gpio.o
21
* + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
29
+obj-$(CONFIG_RASPI) += bcm2835_gpio.o
22
+ * + Property "vfp": enable VFP (forwarded to CPU object)
30
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
23
+ * + Property "dsp": enable DSP (forwarded to CPU object)
31
new file mode 100644
24
* + Property "enable-bitband": expose bitbanded IO
32
index XXXXXXX..XXXXXXX
25
*/
33
--- /dev/null
26
typedef struct ARMv7MState {
34
+++ b/include/hw/gpio/bcm2835_gpio.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
35
@@ -XXX,XX +XXX,XX @@
28
uint32_t init_svtor;
36
+/*
29
bool enable_bitband;
37
+ * Raspberry Pi (BCM2835) GPIO Controller
30
bool start_powered_off;
38
+ *
31
+ bool vfp;
39
+ * Copyright (c) 2017 Antfield SAS
32
+ bool dsp;
40
+ *
33
} ARMv7MState;
41
+ * Authors:
34
42
+ * Clement Deschamps <clement.deschamps@antfield.fr>
35
#endif
43
+ * Luc Michel <luc.michel@antfield.fr>
36
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
44
+ *
37
index XXXXXXX..XXXXXXX 100644
45
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
38
--- a/hw/arm/armv7m.c
46
+ * See the COPYING file in the top-level directory.
39
+++ b/hw/arm/armv7m.c
47
+ */
40
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
48
+
41
return;
49
+#ifndef BCM2835_GPIO_H
42
}
50
+#define BCM2835_GPIO_H
43
}
51
+
44
+ if (object_property_find(OBJECT(s->cpu), "vfp", NULL)) {
52
+#include "hw/sd/sd.h"
45
+ object_property_set_bool(OBJECT(s->cpu), s->vfp,
53
+
46
+ "vfp", &err);
54
+typedef struct BCM2835GpioState {
47
+ if (err != NULL) {
55
+ SysBusDevice parent_obj;
48
+ error_propagate(errp, err);
56
+
49
+ return;
57
+ MemoryRegion iomem;
58
+
59
+ /* SDBus selector */
60
+ SDBus sdbus;
61
+ SDBus *sdbus_sdhci;
62
+ SDBus *sdbus_sdhost;
63
+
64
+ uint8_t fsel[54];
65
+ uint32_t lev0, lev1;
66
+ uint8_t sd_fsel;
67
+ qemu_irq out[54];
68
+} BCM2835GpioState;
69
+
70
+#define TYPE_BCM2835_GPIO "bcm2835_gpio"
71
+#define BCM2835_GPIO(obj) \
72
+ OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO)
73
+
74
+#endif
75
diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c
76
new file mode 100644
77
index XXXXXXX..XXXXXXX
78
--- /dev/null
79
+++ b/hw/gpio/bcm2835_gpio.c
80
@@ -XXX,XX +XXX,XX @@
81
+/*
82
+ * Raspberry Pi (BCM2835) GPIO Controller
83
+ *
84
+ * Copyright (c) 2017 Antfield SAS
85
+ *
86
+ * Authors:
87
+ * Clement Deschamps <clement.deschamps@antfield.fr>
88
+ * Luc Michel <luc.michel@antfield.fr>
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qemu/timer.h"
97
+#include "qapi/error.h"
98
+#include "hw/sysbus.h"
99
+#include "hw/sd/sd.h"
100
+#include "hw/gpio/bcm2835_gpio.h"
101
+
102
+#define GPFSEL0 0x00
103
+#define GPFSEL1 0x04
104
+#define GPFSEL2 0x08
105
+#define GPFSEL3 0x0C
106
+#define GPFSEL4 0x10
107
+#define GPFSEL5 0x14
108
+#define GPSET0 0x1C
109
+#define GPSET1 0x20
110
+#define GPCLR0 0x28
111
+#define GPCLR1 0x2C
112
+#define GPLEV0 0x34
113
+#define GPLEV1 0x38
114
+#define GPEDS0 0x40
115
+#define GPEDS1 0x44
116
+#define GPREN0 0x4C
117
+#define GPREN1 0x50
118
+#define GPFEN0 0x58
119
+#define GPFEN1 0x5C
120
+#define GPHEN0 0x64
121
+#define GPHEN1 0x68
122
+#define GPLEN0 0x70
123
+#define GPLEN1 0x74
124
+#define GPAREN0 0x7C
125
+#define GPAREN1 0x80
126
+#define GPAFEN0 0x88
127
+#define GPAFEN1 0x8C
128
+#define GPPUD 0x94
129
+#define GPPUDCLK0 0x98
130
+#define GPPUDCLK1 0x9C
131
+
132
+static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg)
133
+{
134
+ int i;
135
+ uint32_t value = 0;
136
+ for (i = 0; i < 10; i++) {
137
+ uint32_t index = 10 * reg + i;
138
+ if (index < sizeof(s->fsel)) {
139
+ value |= (s->fsel[index] & 0x7) << (3 * i);
140
+ }
50
+ }
141
+ }
51
+ }
142
+ return value;
52
+ if (object_property_find(OBJECT(s->cpu), "dsp", NULL)) {
143
+}
53
+ object_property_set_bool(OBJECT(s->cpu), s->dsp,
144
+
54
+ "dsp", &err);
145
+static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value)
55
+ if (err != NULL) {
146
+{
56
+ error_propagate(errp, err);
147
+ int i;
57
+ return;
148
+ for (i = 0; i < 10; i++) {
149
+ uint32_t index = 10 * reg + i;
150
+ if (index < sizeof(s->fsel)) {
151
+ int fsel = (value >> (3 * i)) & 0x7;
152
+ s->fsel[index] = fsel;
153
+ }
58
+ }
154
+ }
59
+ }
155
+
60
156
+ /* SD controller selection (48-53) */
61
/*
157
+ if (s->sd_fsel != 0
62
* Tell the CPU where the NVIC is; it will fail realize if it doesn't
158
+ && (s->fsel[48] == 0) /* SD_CLK_R */
63
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
159
+ && (s->fsel[49] == 0) /* SD_CMD_R */
64
DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
160
+ && (s->fsel[50] == 0) /* SD_DATA0_R */
65
DEFINE_PROP_BOOL("start-powered-off", ARMv7MState, start_powered_off,
161
+ && (s->fsel[51] == 0) /* SD_DATA1_R */
66
false),
162
+ && (s->fsel[52] == 0) /* SD_DATA2_R */
67
+ DEFINE_PROP_BOOL("vfp", ARMv7MState, vfp, true),
163
+ && (s->fsel[53] == 0) /* SD_DATA3_R */
68
+ DEFINE_PROP_BOOL("dsp", ARMv7MState, dsp, true),
164
+ ) {
69
DEFINE_PROP_END_OF_LIST(),
165
+ /* SDHCI controller selected */
70
};
166
+ sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
71
167
+ s->sd_fsel = 0;
168
+ } else if (s->sd_fsel != 4
169
+ && (s->fsel[48] == 4) /* SD_CLK_R */
170
+ && (s->fsel[49] == 4) /* SD_CMD_R */
171
+ && (s->fsel[50] == 4) /* SD_DATA0_R */
172
+ && (s->fsel[51] == 4) /* SD_DATA1_R */
173
+ && (s->fsel[52] == 4) /* SD_DATA2_R */
174
+ && (s->fsel[53] == 4) /* SD_DATA3_R */
175
+ ) {
176
+ /* SDHost controller selected */
177
+ sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
178
+ s->sd_fsel = 4;
179
+ }
180
+}
181
+
182
+static int gpfsel_is_out(BCM2835GpioState *s, int index)
183
+{
184
+ if (index >= 0 && index < 54) {
185
+ return s->fsel[index] == 1;
186
+ }
187
+ return 0;
188
+}
189
+
190
+static void gpset(BCM2835GpioState *s,
191
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
192
+{
193
+ uint32_t changes = val & ~*lev;
194
+ uint32_t cur = 1;
195
+
196
+ int i;
197
+ for (i = 0; i < count; i++) {
198
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
199
+ qemu_set_irq(s->out[start + i], 1);
200
+ }
201
+ cur <<= 1;
202
+ }
203
+
204
+ *lev |= val;
205
+}
206
+
207
+static void gpclr(BCM2835GpioState *s,
208
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
209
+{
210
+ uint32_t changes = val & *lev;
211
+ uint32_t cur = 1;
212
+
213
+ int i;
214
+ for (i = 0; i < count; i++) {
215
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
216
+ qemu_set_irq(s->out[start + i], 0);
217
+ }
218
+ cur <<= 1;
219
+ }
220
+
221
+ *lev &= ~val;
222
+}
223
+
224
+static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset,
225
+ unsigned size)
226
+{
227
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
228
+
229
+ switch (offset) {
230
+ case GPFSEL0:
231
+ case GPFSEL1:
232
+ case GPFSEL2:
233
+ case GPFSEL3:
234
+ case GPFSEL4:
235
+ case GPFSEL5:
236
+ return gpfsel_get(s, offset / 4);
237
+ case GPSET0:
238
+ case GPSET1:
239
+ /* Write Only */
240
+ return 0;
241
+ case GPCLR0:
242
+ case GPCLR1:
243
+ /* Write Only */
244
+ return 0;
245
+ case GPLEV0:
246
+ return s->lev0;
247
+ case GPLEV1:
248
+ return s->lev1;
249
+ case GPEDS0:
250
+ case GPEDS1:
251
+ case GPREN0:
252
+ case GPREN1:
253
+ case GPFEN0:
254
+ case GPFEN1:
255
+ case GPHEN0:
256
+ case GPHEN1:
257
+ case GPLEN0:
258
+ case GPLEN1:
259
+ case GPAREN0:
260
+ case GPAREN1:
261
+ case GPAFEN0:
262
+ case GPAFEN1:
263
+ case GPPUD:
264
+ case GPPUDCLK0:
265
+ case GPPUDCLK1:
266
+ /* Not implemented */
267
+ return 0;
268
+ default:
269
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
270
+ __func__, offset);
271
+ break;
272
+ }
273
+
274
+ return 0;
275
+}
276
+
277
+static void bcm2835_gpio_write(void *opaque, hwaddr offset,
278
+ uint64_t value, unsigned size)
279
+{
280
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
281
+
282
+ switch (offset) {
283
+ case GPFSEL0:
284
+ case GPFSEL1:
285
+ case GPFSEL2:
286
+ case GPFSEL3:
287
+ case GPFSEL4:
288
+ case GPFSEL5:
289
+ gpfsel_set(s, offset / 4, value);
290
+ break;
291
+ case GPSET0:
292
+ gpset(s, value, 0, 32, &s->lev0);
293
+ break;
294
+ case GPSET1:
295
+ gpset(s, value, 32, 22, &s->lev1);
296
+ break;
297
+ case GPCLR0:
298
+ gpclr(s, value, 0, 32, &s->lev0);
299
+ break;
300
+ case GPCLR1:
301
+ gpclr(s, value, 32, 22, &s->lev1);
302
+ break;
303
+ case GPLEV0:
304
+ case GPLEV1:
305
+ /* Read Only */
306
+ break;
307
+ case GPEDS0:
308
+ case GPEDS1:
309
+ case GPREN0:
310
+ case GPREN1:
311
+ case GPFEN0:
312
+ case GPFEN1:
313
+ case GPHEN0:
314
+ case GPHEN1:
315
+ case GPLEN0:
316
+ case GPLEN1:
317
+ case GPAREN0:
318
+ case GPAREN1:
319
+ case GPAFEN0:
320
+ case GPAFEN1:
321
+ case GPPUD:
322
+ case GPPUDCLK0:
323
+ case GPPUDCLK1:
324
+ /* Not implemented */
325
+ break;
326
+ default:
327
+ goto err_out;
328
+ }
329
+ return;
330
+
331
+err_out:
332
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
333
+ __func__, offset);
334
+}
335
+
336
+static void bcm2835_gpio_reset(DeviceState *dev)
337
+{
338
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
339
+
340
+ int i;
341
+ for (i = 0; i < 6; i++) {
342
+ gpfsel_set(s, i, 0);
343
+ }
344
+
345
+ s->sd_fsel = 0;
346
+
347
+ /* SDHCI is selected by default */
348
+ sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci);
349
+
350
+ s->lev0 = 0;
351
+ s->lev1 = 0;
352
+}
353
+
354
+static const MemoryRegionOps bcm2835_gpio_ops = {
355
+ .read = bcm2835_gpio_read,
356
+ .write = bcm2835_gpio_write,
357
+ .endianness = DEVICE_NATIVE_ENDIAN,
358
+};
359
+
360
+static const VMStateDescription vmstate_bcm2835_gpio = {
361
+ .name = "bcm2835_gpio",
362
+ .version_id = 1,
363
+ .minimum_version_id = 1,
364
+ .fields = (VMStateField[]) {
365
+ VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54),
366
+ VMSTATE_UINT32(lev0, BCM2835GpioState),
367
+ VMSTATE_UINT32(lev1, BCM2835GpioState),
368
+ VMSTATE_UINT8(sd_fsel, BCM2835GpioState),
369
+ VMSTATE_END_OF_LIST()
370
+ }
371
+};
372
+
373
+static void bcm2835_gpio_init(Object *obj)
374
+{
375
+ BCM2835GpioState *s = BCM2835_GPIO(obj);
376
+ DeviceState *dev = DEVICE(obj);
377
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
378
+
379
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
380
+ TYPE_SD_BUS, DEVICE(s), "sd-bus");
381
+
382
+ memory_region_init_io(&s->iomem, obj,
383
+ &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000);
384
+ sysbus_init_mmio(sbd, &s->iomem);
385
+ qdev_init_gpio_out(dev, s->out, 54);
386
+}
387
+
388
+static void bcm2835_gpio_realize(DeviceState *dev, Error **errp)
389
+{
390
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
391
+ Object *obj;
392
+ Error *err = NULL;
393
+
394
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err);
395
+ if (obj == NULL) {
396
+ error_setg(errp, "%s: required sdhci link not found: %s",
397
+ __func__, error_get_pretty(err));
398
+ return;
399
+ }
400
+ s->sdbus_sdhci = SD_BUS(obj);
401
+
402
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err);
403
+ if (obj == NULL) {
404
+ error_setg(errp, "%s: required sdhost link not found: %s",
405
+ __func__, error_get_pretty(err));
406
+ return;
407
+ }
408
+ s->sdbus_sdhost = SD_BUS(obj);
409
+}
410
+
411
+static void bcm2835_gpio_class_init(ObjectClass *klass, void *data)
412
+{
413
+ DeviceClass *dc = DEVICE_CLASS(klass);
414
+
415
+ dc->vmsd = &vmstate_bcm2835_gpio;
416
+ dc->realize = &bcm2835_gpio_realize;
417
+ dc->reset = &bcm2835_gpio_reset;
418
+}
419
+
420
+static const TypeInfo bcm2835_gpio_info = {
421
+ .name = TYPE_BCM2835_GPIO,
422
+ .parent = TYPE_SYS_BUS_DEVICE,
423
+ .instance_size = sizeof(BCM2835GpioState),
424
+ .instance_init = bcm2835_gpio_init,
425
+ .class_init = bcm2835_gpio_class_init,
426
+};
427
+
428
+static void bcm2835_gpio_register_types(void)
429
+{
430
+ type_register_static(&bcm2835_gpio_info);
431
+}
432
+
433
+type_init(bcm2835_gpio_register_types)
434
--
72
--
435
2.7.4
73
2.20.1
436
74
437
75
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
The SSE-200 hardware has configurable integration settings which
2
determine whether its two CPUs have the FPU and DSP:
3
* CPU0_FPU (default 0)
4
* CPU0_DSP (default 0)
5
* CPU1_FPU (default 1)
6
* CPU1_DSP (default 1)
2
7
3
Without any clock controller, the Linux kernel was hitting division by
8
Similarly, the IoTKit has settings for its single CPU:
4
zero during boot or with clk_summary:
9
* CPU0_FPU (default 1)
5
[ 0.000000] [<c031054c>] (unwind_backtrace) from [<c030ba6c>] (show_stack+0x10/0x14)
10
* CPU0_DSP (default 1)
6
[ 0.000000] [<c030ba6c>] (show_stack) from [<c05b2660>] (dump_stack+0x88/0x9c)
7
[ 0.000000] [<c05b2660>] (dump_stack) from [<c05b11a4>] (Ldiv0+0x8/0x10)
8
[ 0.000000] [<c05b11a4>] (Ldiv0) from [<c06ad1e0>] (samsung_pll45xx_recalc_rate+0x58/0x74)
9
[ 0.000000] [<c06ad1e0>] (samsung_pll45xx_recalc_rate) from [<c0692ec0>] (clk_register+0x39c/0x63c)
10
[ 0.000000] [<c0692ec0>] (clk_register) from [<c125d360>] (samsung_clk_register_pll+0x2e0/0x3d4)
11
[ 0.000000] [<c125d360>] (samsung_clk_register_pll) from [<c125d7e8>] (exynos4_clk_init+0x1b0/0x5e4)
12
[ 0.000000] [<c125d7e8>] (exynos4_clk_init) from [<c12335f4>] (of_clk_init+0x17c/0x210)
13
[ 0.000000] [<c12335f4>] (of_clk_init) from [<c1204700>] (time_init+0x24/0x2c)
14
[ 0.000000] [<c1204700>] (time_init) from [<c1200b2c>] (start_kernel+0x24c/0x38c)
15
[ 0.000000] [<c1200b2c>] (start_kernel) from [<4020807c>] (0x4020807c)
16
11
17
Provide stub for clock controller returning reset values for PLLs.
12
Of our four boards that use either the IoTKit or the SSE-200:
13
* mps2-an505, mps2-an521 and musca-a use the default settings
14
* musca-b1 enables FPU and DSP on both CPUs
18
15
19
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
16
Currently QEMU models all these boards using CPUs with
20
Message-id: 20170226200142.31169-1-krzk@kernel.org
17
both FPU and DSP enabled. This means that we are incorrect
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
for mps2-an521 and musca-a, which should not have FPU or DSP
19
on CPU0.
20
21
Create QOM properties on the ARMSSE devices corresponding to the
22
default h/w integration settings, and make the Musca-B1 board
23
enable FPU and DSP on both CPUs. This fixes the mps2-an521
24
and musca-a behaviour, and leaves the musca-b1 and mps2-an505
25
behaviour unchanged.
26
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
29
Message-id: 20190517174046.11146-5-peter.maydell@linaro.org
23
---
30
---
24
hw/misc/Makefile.objs | 2 +-
31
include/hw/arm/armsse.h | 7 +++++
25
hw/arm/exynos4210.c | 6 ++
32
hw/arm/armsse.c | 58 ++++++++++++++++++++++++++++++++---------
26
hw/misc/exynos4210_clk.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++
33
hw/arm/musca.c | 8 ++++++
27
3 files changed, 171 insertions(+), 1 deletion(-)
34
3 files changed, 61 insertions(+), 12 deletions(-)
28
create mode 100644 hw/misc/exynos4210_clk.c
29
35
30
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
36
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
31
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/Makefile.objs
38
--- a/include/hw/arm/armsse.h
33
+++ b/hw/misc/Makefile.objs
39
+++ b/include/hw/arm/armsse.h
34
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
40
@@ -XXX,XX +XXX,XX @@
35
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
41
* address of each SRAM bank (and thus the total amount of internal SRAM)
36
obj-$(CONFIG_NSERIES) += cbus.o
42
* + QOM property "init-svtor" sets the initial value of the CPU SVTOR register
37
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
43
* (where it expects to load the PC and SP from the vector table on reset)
38
-obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
44
+ * + QOM properties "CPU0_FPU", "CPU0_DSP", "CPU1_FPU" and "CPU1_DSP" which
39
+obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o
45
+ * set whether the CPUs have the FPU and DSP features present. The default
40
obj-$(CONFIG_IMX) += imx_ccm.o
46
+ * (matching the hardware) is that for CPU0 in an IoTKit and CPU1 in an
41
obj-$(CONFIG_IMX) += imx31_ccm.o
47
+ * SSE-200 both are present; CPU0 in an SSE-200 has neither.
42
obj-$(CONFIG_IMX) += imx25_ccm.o
48
+ * Since the IoTKit has only one CPU, it does not have the CPU1_* properties.
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
49
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
50
* which are wired to its NVIC lines 32 .. n+32
51
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
52
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
53
uint32_t mainclk_frq;
54
uint32_t sram_addr_width;
55
uint32_t init_svtor;
56
+ bool cpu_fpu[SSE_MAX_CPUS];
57
+ bool cpu_dsp[SSE_MAX_CPUS];
58
} ARMSSE;
59
60
typedef struct ARMSSEInfo ARMSSEInfo;
61
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
44
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
63
--- a/hw/arm/armsse.c
46
+++ b/hw/arm/exynos4210.c
64
+++ b/hw/arm/armsse.c
47
@@ -XXX,XX +XXX,XX @@
65
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
48
#include "qemu/osdep.h"
66
bool has_cachectrl;
49
#include "qapi/error.h"
67
bool has_cpusecctrl;
50
#include "qemu-common.h"
68
bool has_cpuid;
51
+#include "qemu/log.h"
69
+ Property *props;
52
#include "cpu.h"
53
#include "hw/boards.h"
54
#include "sysemu/sysemu.h"
55
@@ -XXX,XX +XXX,XX @@
56
/* PMU SFR base address */
57
#define EXYNOS4210_PMU_BASE_ADDR 0x10020000
58
59
+/* Clock controller SFR base address */
60
+#define EXYNOS4210_CLK_BASE_ADDR 0x10030000
61
+
62
/* Display controllers (FIMD) */
63
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
64
65
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
66
*/
67
sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
68
69
+ sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
70
+
71
/* PWM */
72
sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
73
s->irq_table[exynos4210_get_irq(22, 0)],
74
diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/hw/misc/exynos4210_clk.c
79
@@ -XXX,XX +XXX,XX @@
80
+/*
81
+ * Exynos4210 Clock Controller Emulation
82
+ *
83
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
84
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
86
+ * under the terms of the GNU General Public License as published by the
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
89
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ *
95
+ * You should have received a copy of the GNU General Public License along
96
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
97
+ */
98
+
99
+#include "qemu/osdep.h"
100
+#include "hw/sysbus.h"
101
+#include "qemu/log.h"
102
+
103
+#define TYPE_EXYNOS4210_CLK "exynos4210.clk"
104
+#define EXYNOS4210_CLK(obj) \
105
+ OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK)
106
+
107
+#define CLK_PLL_LOCKED BIT(29)
108
+
109
+#define EXYNOS4210_CLK_REGS_MEM_SIZE 0x15104
110
+
111
+typedef struct Exynos4210Reg {
112
+ const char *name; /* for debug only */
113
+ uint32_t offset;
114
+ uint32_t reset_value;
115
+} Exynos4210Reg;
116
+
117
+/* Clock controller register base: 0x10030000 */
118
+static const Exynos4210Reg exynos4210_clk_regs[] = {
119
+ {"EPLL_LOCK", 0xc010, 0x00000fff},
120
+ {"VPLL_LOCK", 0xc020, 0x00000fff},
121
+ {"EPLL_CON0", 0xc110, 0x00300301 | CLK_PLL_LOCKED},
122
+ {"EPLL_CON1", 0xc114, 0x00000000},
123
+ {"VPLL_CON0", 0xc120, 0x00240201 | CLK_PLL_LOCKED},
124
+ {"VPLL_CON1", 0xc124, 0x66010464},
125
+ {"APLL_LOCK", 0x14000, 0x00000fff},
126
+ {"MPLL_LOCK", 0x14004, 0x00000fff},
127
+ {"APLL_CON0", 0x14100, 0x00c80601 | CLK_PLL_LOCKED},
128
+ {"APLL_CON1", 0x14104, 0x0000001c},
129
+ {"MPLL_CON0", 0x14108, 0x00c80601 | CLK_PLL_LOCKED},
130
+ {"MPLL_CON1", 0x1410c, 0x0000001c},
131
+};
70
+};
132
+
71
+
133
+#define EXYNOS4210_REGS_NUM ARRAY_SIZE(exynos4210_clk_regs)
72
+static Property iotkit_properties[] = {
134
+
73
+ DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
135
+typedef struct Exynos4210ClkState {
74
+ MemoryRegion *),
136
+ SysBusDevice parent_obj;
75
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
137
+
76
+ DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
138
+ MemoryRegion iomem;
77
+ DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
139
+ uint32_t reg[EXYNOS4210_REGS_NUM];
78
+ DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
140
+} Exynos4210ClkState;
79
+ DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
141
+
80
+ DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
142
+static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset,
81
+ DEFINE_PROP_END_OF_LIST()
143
+ unsigned size)
144
+{
145
+ const Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
146
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
147
+ unsigned int i;
148
+
149
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
150
+ if (regs->offset == offset) {
151
+ return s->reg[i];
152
+ }
153
+ regs++;
154
+ }
155
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read offset 0x%04x\n",
156
+ __func__, (uint32_t)offset);
157
+ return 0;
158
+}
159
+
160
+static void exynos4210_clk_write(void *opaque, hwaddr offset,
161
+ uint64_t val, unsigned size)
162
+{
163
+ Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
164
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
165
+ unsigned int i;
166
+
167
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
168
+ if (regs->offset == offset) {
169
+ s->reg[i] = val;
170
+ return;
171
+ }
172
+ regs++;
173
+ }
174
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write offset 0x%04x\n",
175
+ __func__, (uint32_t)offset);
176
+}
177
+
178
+static const MemoryRegionOps exynos4210_clk_ops = {
179
+ .read = exynos4210_clk_read,
180
+ .write = exynos4210_clk_write,
181
+ .endianness = DEVICE_NATIVE_ENDIAN,
182
+ .valid = {
183
+ .min_access_size = 4,
184
+ .max_access_size = 4,
185
+ .unaligned = false
186
+ }
187
+};
82
+};
188
+
83
+
189
+static void exynos4210_clk_reset(DeviceState *dev)
84
+static Property armsse_properties[] = {
190
+{
85
+ DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
191
+ Exynos4210ClkState *s = EXYNOS4210_CLK(dev);
86
+ MemoryRegion *),
192
+ unsigned int i;
87
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
193
+
88
+ DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
194
+ /* Set default values for registers */
89
+ DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
195
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
90
+ DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
196
+ s->reg[i] = exynos4210_clk_regs[i].reset_value;
91
+ DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
92
+ DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], false),
93
+ DEFINE_PROP_BOOL("CPU1_FPU", ARMSSE, cpu_fpu[1], true),
94
+ DEFINE_PROP_BOOL("CPU1_DSP", ARMSSE, cpu_dsp[1], true),
95
+ DEFINE_PROP_END_OF_LIST()
96
};
97
98
static const ARMSSEInfo armsse_variants[] = {
99
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
100
.has_cachectrl = false,
101
.has_cpusecctrl = false,
102
.has_cpuid = false,
103
+ .props = iotkit_properties,
104
},
105
{
106
.name = TYPE_SSE200,
107
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
108
.has_cachectrl = true,
109
.has_cpusecctrl = true,
110
.has_cpuid = true,
111
+ .props = armsse_properties,
112
},
113
};
114
115
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
116
return;
117
}
118
}
119
+ if (!s->cpu_fpu[i]) {
120
+ object_property_set_bool(cpuobj, false, "vfp", &err);
121
+ if (err) {
122
+ error_propagate(errp, err);
123
+ return;
124
+ }
125
+ }
126
+ if (!s->cpu_dsp[i]) {
127
+ object_property_set_bool(cpuobj, false, "dsp", &err);
128
+ if (err) {
129
+ error_propagate(errp, err);
130
+ return;
131
+ }
132
+ }
133
134
if (i > 0) {
135
memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
136
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription armsse_vmstate = {
137
}
138
};
139
140
-static Property armsse_properties[] = {
141
- DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
142
- MemoryRegion *),
143
- DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
144
- DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
145
- DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
146
- DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
147
- DEFINE_PROP_END_OF_LIST()
148
-};
149
-
150
static void armsse_reset(DeviceState *dev)
151
{
152
ARMSSE *s = ARMSSE(dev);
153
@@ -XXX,XX +XXX,XX @@ static void armsse_class_init(ObjectClass *klass, void *data)
154
DeviceClass *dc = DEVICE_CLASS(klass);
155
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
156
ARMSSEClass *asc = ARMSSE_CLASS(klass);
157
+ const ARMSSEInfo *info = data;
158
159
dc->realize = armsse_realize;
160
dc->vmsd = &armsse_vmstate;
161
- dc->props = armsse_properties;
162
+ dc->props = info->props;
163
dc->reset = armsse_reset;
164
iic->check = armsse_idau_check;
165
- asc->info = data;
166
+ asc->info = info;
167
}
168
169
static const TypeInfo armsse_info = {
170
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/hw/arm/musca.c
173
+++ b/hw/arm/musca.c
174
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
175
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
176
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
177
qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
178
+ /*
179
+ * Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
180
+ * CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
181
+ */
182
+ if (mmc->type == MUSCA_B1) {
183
+ qdev_prop_set_bit(ssedev, "CPU0_FPU", true);
184
+ qdev_prop_set_bit(ssedev, "CPU0_DSP", true);
197
+ }
185
+ }
198
+}
186
object_property_set_bool(OBJECT(&mms->sse), true, "realized",
199
+
187
&error_fatal);
200
+static void exynos4210_clk_init(Object *obj)
188
201
+{
202
+ Exynos4210ClkState *s = EXYNOS4210_CLK(obj);
203
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
204
+
205
+ /* memory mapping */
206
+ memory_region_init_io(&s->iomem, obj, &exynos4210_clk_ops, s,
207
+ TYPE_EXYNOS4210_CLK, EXYNOS4210_CLK_REGS_MEM_SIZE);
208
+ sysbus_init_mmio(dev, &s->iomem);
209
+}
210
+
211
+static const VMStateDescription exynos4210_clk_vmstate = {
212
+ .name = TYPE_EXYNOS4210_CLK,
213
+ .version_id = 1,
214
+ .minimum_version_id = 1,
215
+ .fields = (VMStateField[]) {
216
+ VMSTATE_UINT32_ARRAY(reg, Exynos4210ClkState, EXYNOS4210_REGS_NUM),
217
+ VMSTATE_END_OF_LIST()
218
+ }
219
+};
220
+
221
+static void exynos4210_clk_class_init(ObjectClass *klass, void *data)
222
+{
223
+ DeviceClass *dc = DEVICE_CLASS(klass);
224
+
225
+ dc->reset = exynos4210_clk_reset;
226
+ dc->vmsd = &exynos4210_clk_vmstate;
227
+}
228
+
229
+static const TypeInfo exynos4210_clk_info = {
230
+ .name = TYPE_EXYNOS4210_CLK,
231
+ .parent = TYPE_SYS_BUS_DEVICE,
232
+ .instance_size = sizeof(Exynos4210ClkState),
233
+ .instance_init = exynos4210_clk_init,
234
+ .class_init = exynos4210_clk_class_init,
235
+};
236
+
237
+static void exynos4210_clk_register(void)
238
+{
239
+ qemu_log_mask(LOG_GUEST_ERROR, "Clock init\n");
240
+ type_register_static(&exynos4210_clk_info);
241
+}
242
+
243
+type_init(exynos4210_clk_register)
244
--
189
--
245
2.7.4
190
2.20.1
246
191
247
192
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
The GIC ID registers cover an area 0x30 bytes in size
2
(12 registers, 4 bytes each). We were incorrectly decoding
3
only the first 0x20 bytes.
2
4
3
This adds the BCM2835 SDHost controller from Arasan.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20190524124248.28394-2-peter.maydell@linaro.org
8
---
9
hw/intc/arm_gicv3_dist.c | 4 ++--
10
hw/intc/arm_gicv3_redist.c | 4 ++--
11
2 files changed, 4 insertions(+), 4 deletions(-)
4
12
5
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
13
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
6
Message-id: 20170224164021.9066-2-clement.deschamps@antfield.fr
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/sd/Makefile.objs | 1 +
11
include/hw/sd/bcm2835_sdhost.h | 48 +++++
12
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++++++++++++++++++++++++++
13
3 files changed, 478 insertions(+)
14
create mode 100644 include/hw/sd/bcm2835_sdhost.h
15
create mode 100644 hw/sd/bcm2835_sdhost.c
16
17
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/sd/Makefile.objs
15
--- a/hw/intc/arm_gicv3_dist.c
20
+++ b/hw/sd/Makefile.objs
16
+++ b/hw/intc/arm_gicv3_dist.c
21
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SDHCI) += sdhci.o
17
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
22
obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
18
}
23
obj-$(CONFIG_OMAP) += omap_mmc.o
19
return MEMTX_OK;
24
obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
20
}
25
+obj-$(CONFIG_RASPI) += bcm2835_sdhost.o
21
- case GICD_IDREGS ... GICD_IDREGS + 0x1f:
26
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
22
+ case GICD_IDREGS ... GICD_IDREGS + 0x2f:
27
new file mode 100644
23
/* ID registers */
28
index XXXXXXX..XXXXXXX
24
*data = gicv3_idreg(offset - GICD_IDREGS);
29
--- /dev/null
25
return MEMTX_OK;
30
+++ b/include/hw/sd/bcm2835_sdhost.h
26
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
31
@@ -XXX,XX +XXX,XX @@
27
gicd_write_irouter(s, attrs, irq, r);
32
+/*
28
return MEMTX_OK;
33
+ * Raspberry Pi (BCM2835) SD Host Controller
29
}
34
+ *
30
- case GICD_IDREGS ... GICD_IDREGS + 0x1f:
35
+ * Copyright (c) 2017 Antfield SAS
31
+ case GICD_IDREGS ... GICD_IDREGS + 0x2f:
36
+ *
32
case GICD_TYPER:
37
+ * Authors:
33
case GICD_IIDR:
38
+ * Clement Deschamps <clement.deschamps@antfield.fr>
34
/* RO registers, ignore the write */
39
+ * Luc Michel <luc.michel@antfield.fr>
35
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
40
+ *
36
index XXXXXXX..XXXXXXX 100644
41
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
37
--- a/hw/intc/arm_gicv3_redist.c
42
+ * See the COPYING file in the top-level directory.
38
+++ b/hw/intc/arm_gicv3_redist.c
43
+ */
39
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
44
+
40
}
45
+#ifndef BCM2835_SDHOST_H
41
*data = cs->gicr_nsacr;
46
+#define BCM2835_SDHOST_H
42
return MEMTX_OK;
47
+
43
- case GICR_IDREGS ... GICR_IDREGS + 0x1f:
48
+#include "hw/sysbus.h"
44
+ case GICR_IDREGS ... GICR_IDREGS + 0x2f:
49
+#include "hw/sd/sd.h"
45
*data = gicv3_idreg(offset - GICR_IDREGS);
50
+
46
return MEMTX_OK;
51
+#define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
47
default:
52
+#define BCM2835_SDHOST(obj) \
48
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
53
+ OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST)
49
return MEMTX_OK;
54
+
50
case GICR_IIDR:
55
+#define BCM2835_SDHOST_FIFO_LEN 16
51
case GICR_TYPER:
56
+
52
- case GICR_IDREGS ... GICR_IDREGS + 0x1f:
57
+typedef struct {
53
+ case GICR_IDREGS ... GICR_IDREGS + 0x2f:
58
+ SysBusDevice busdev;
54
/* RO registers, ignore the write */
59
+ SDBus sdbus;
55
qemu_log_mask(LOG_GUEST_ERROR,
60
+ MemoryRegion iomem;
56
"%s: invalid guest write to RO register at offset "
61
+
62
+ uint32_t cmd;
63
+ uint32_t cmdarg;
64
+ uint32_t status;
65
+ uint32_t rsp[4];
66
+ uint32_t config;
67
+ uint32_t edm;
68
+ uint32_t vdd;
69
+ uint32_t hbct;
70
+ uint32_t hblc;
71
+ int32_t fifo_pos;
72
+ int32_t fifo_len;
73
+ uint32_t fifo[BCM2835_SDHOST_FIFO_LEN];
74
+ uint32_t datacnt;
75
+
76
+ qemu_irq irq;
77
+} BCM2835SDHostState;
78
+
79
+#endif
80
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
81
new file mode 100644
82
index XXXXXXX..XXXXXXX
83
--- /dev/null
84
+++ b/hw/sd/bcm2835_sdhost.c
85
@@ -XXX,XX +XXX,XX @@
86
+/*
87
+ * Raspberry Pi (BCM2835) SD Host Controller
88
+ *
89
+ * Copyright (c) 2017 Antfield SAS
90
+ *
91
+ * Authors:
92
+ * Clement Deschamps <clement.deschamps@antfield.fr>
93
+ * Luc Michel <luc.michel@antfield.fr>
94
+ *
95
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
96
+ * See the COPYING file in the top-level directory.
97
+ */
98
+
99
+#include "qemu/osdep.h"
100
+#include "qemu/log.h"
101
+#include "sysemu/blockdev.h"
102
+#include "hw/sd/bcm2835_sdhost.h"
103
+
104
+#define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus"
105
+#define BCM2835_SDHOST_BUS(obj) \
106
+ OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS)
107
+
108
+#define SDCMD 0x00 /* Command to SD card - 16 R/W */
109
+#define SDARG 0x04 /* Argument to SD card - 32 R/W */
110
+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
111
+#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
112
+#define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */
113
+#define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */
114
+#define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */
115
+#define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */
116
+#define SDHSTS 0x20 /* SD host status - 11 R */
117
+#define SDVDD 0x30 /* SD card power control - 1 R/W */
118
+#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
119
+#define SDHCFG 0x38 /* Host configuration - 2 R/W */
120
+#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
121
+#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
122
+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
123
+
124
+#define SDCMD_NEW_FLAG 0x8000
125
+#define SDCMD_FAIL_FLAG 0x4000
126
+#define SDCMD_BUSYWAIT 0x800
127
+#define SDCMD_NO_RESPONSE 0x400
128
+#define SDCMD_LONG_RESPONSE 0x200
129
+#define SDCMD_WRITE_CMD 0x80
130
+#define SDCMD_READ_CMD 0x40
131
+#define SDCMD_CMD_MASK 0x3f
132
+
133
+#define SDCDIV_MAX_CDIV 0x7ff
134
+
135
+#define SDHSTS_BUSY_IRPT 0x400
136
+#define SDHSTS_BLOCK_IRPT 0x200
137
+#define SDHSTS_SDIO_IRPT 0x100
138
+#define SDHSTS_REW_TIME_OUT 0x80
139
+#define SDHSTS_CMD_TIME_OUT 0x40
140
+#define SDHSTS_CRC16_ERROR 0x20
141
+#define SDHSTS_CRC7_ERROR 0x10
142
+#define SDHSTS_FIFO_ERROR 0x08
143
+/* Reserved */
144
+/* Reserved */
145
+#define SDHSTS_DATA_FLAG 0x01
146
+
147
+#define SDHCFG_BUSY_IRPT_EN (1 << 10)
148
+#define SDHCFG_BLOCK_IRPT_EN (1 << 8)
149
+#define SDHCFG_SDIO_IRPT_EN (1 << 5)
150
+#define SDHCFG_DATA_IRPT_EN (1 << 4)
151
+#define SDHCFG_SLOW_CARD (1 << 3)
152
+#define SDHCFG_WIDE_EXT_BUS (1 << 2)
153
+#define SDHCFG_WIDE_INT_BUS (1 << 1)
154
+#define SDHCFG_REL_CMD_LINE (1 << 0)
155
+
156
+#define SDEDM_FORCE_DATA_MODE (1 << 19)
157
+#define SDEDM_CLOCK_PULSE (1 << 20)
158
+#define SDEDM_BYPASS (1 << 21)
159
+
160
+#define SDEDM_WRITE_THRESHOLD_SHIFT 9
161
+#define SDEDM_READ_THRESHOLD_SHIFT 14
162
+#define SDEDM_THRESHOLD_MASK 0x1f
163
+
164
+#define SDEDM_FSM_MASK 0xf
165
+#define SDEDM_FSM_IDENTMODE 0x0
166
+#define SDEDM_FSM_DATAMODE 0x1
167
+#define SDEDM_FSM_READDATA 0x2
168
+#define SDEDM_FSM_WRITEDATA 0x3
169
+#define SDEDM_FSM_READWAIT 0x4
170
+#define SDEDM_FSM_READCRC 0x5
171
+#define SDEDM_FSM_WRITECRC 0x6
172
+#define SDEDM_FSM_WRITEWAIT1 0x7
173
+#define SDEDM_FSM_POWERDOWN 0x8
174
+#define SDEDM_FSM_POWERUP 0x9
175
+#define SDEDM_FSM_WRITESTART1 0xa
176
+#define SDEDM_FSM_WRITESTART2 0xb
177
+#define SDEDM_FSM_GENPULSES 0xc
178
+#define SDEDM_FSM_WRITEWAIT2 0xd
179
+#define SDEDM_FSM_STARTPOWDOWN 0xf
180
+
181
+#define SDDATA_FIFO_WORDS 16
182
+
183
+static void bcm2835_sdhost_update_irq(BCM2835SDHostState *s)
184
+{
185
+ uint32_t irq = s->status &
186
+ (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | SDHSTS_SDIO_IRPT);
187
+ qemu_set_irq(s->irq, !!irq);
188
+}
189
+
190
+static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
191
+{
192
+ SDRequest request;
193
+ uint8_t rsp[16];
194
+ int rlen;
195
+
196
+ request.cmd = s->cmd & SDCMD_CMD_MASK;
197
+ request.arg = s->cmdarg;
198
+
199
+ rlen = sdbus_do_command(&s->sdbus, &request, rsp);
200
+ if (rlen < 0) {
201
+ goto error;
202
+ }
203
+ if (!(s->cmd & SDCMD_NO_RESPONSE)) {
204
+#define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \
205
+ | (rsp[n + 2] << 8) | rsp[n + 3])
206
+ if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) {
207
+ goto error;
208
+ }
209
+ if (rlen != 4 && rlen != 16) {
210
+ goto error;
211
+ }
212
+ if (rlen == 4) {
213
+ s->rsp[0] = RWORD(0);
214
+ s->rsp[1] = s->rsp[2] = s->rsp[3] = 0;
215
+ } else {
216
+ s->rsp[0] = RWORD(12);
217
+ s->rsp[1] = RWORD(8);
218
+ s->rsp[2] = RWORD(4);
219
+ s->rsp[3] = RWORD(0);
220
+ }
221
+#undef RWORD
222
+ }
223
+ return;
224
+
225
+error:
226
+ s->cmd |= SDCMD_FAIL_FLAG;
227
+ s->status |= SDHSTS_CMD_TIME_OUT;
228
+}
229
+
230
+static void bcm2835_sdhost_fifo_push(BCM2835SDHostState *s, uint32_t value)
231
+{
232
+ int n;
233
+
234
+ if (s->fifo_len == BCM2835_SDHOST_FIFO_LEN) {
235
+ /* FIFO overflow */
236
+ return;
237
+ }
238
+ n = (s->fifo_pos + s->fifo_len) & (BCM2835_SDHOST_FIFO_LEN - 1);
239
+ s->fifo_len++;
240
+ s->fifo[n] = value;
241
+}
242
+
243
+static uint32_t bcm2835_sdhost_fifo_pop(BCM2835SDHostState *s)
244
+{
245
+ uint32_t value;
246
+
247
+ if (s->fifo_len == 0) {
248
+ /* FIFO underflow */
249
+ return 0;
250
+ }
251
+ value = s->fifo[s->fifo_pos];
252
+ s->fifo_len--;
253
+ s->fifo_pos = (s->fifo_pos + 1) & (BCM2835_SDHOST_FIFO_LEN - 1);
254
+ return value;
255
+}
256
+
257
+static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
258
+{
259
+ uint32_t value = 0;
260
+ int n;
261
+ int is_read;
262
+
263
+ is_read = (s->cmd & SDCMD_READ_CMD) != 0;
264
+ if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))) {
265
+ if (is_read) {
266
+ n = 0;
267
+ while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) {
268
+ value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8);
269
+ s->datacnt--;
270
+ n++;
271
+ if (n == 4) {
272
+ bcm2835_sdhost_fifo_push(s, value);
273
+ n = 0;
274
+ value = 0;
275
+ }
276
+ }
277
+ if (n != 0) {
278
+ bcm2835_sdhost_fifo_push(s, value);
279
+ }
280
+ } else { /* write */
281
+ n = 0;
282
+ while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
283
+ if (n == 0) {
284
+ value = bcm2835_sdhost_fifo_pop(s);
285
+ n = 4;
286
+ }
287
+ n--;
288
+ s->datacnt--;
289
+ sdbus_write_data(&s->sdbus, value & 0xff);
290
+ value >>= 8;
291
+ }
292
+ }
293
+ }
294
+ if (s->datacnt == 0) {
295
+ s->status |= SDHSTS_DATA_FLAG;
296
+
297
+ s->edm &= ~0xf;
298
+ s->edm |= SDEDM_FSM_DATAMODE;
299
+
300
+ if (s->config & SDHCFG_DATA_IRPT_EN) {
301
+ s->status |= SDHSTS_SDIO_IRPT;
302
+ }
303
+
304
+ if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)) {
305
+ s->status |= SDHSTS_BUSY_IRPT;
306
+ }
307
+
308
+ if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_EN)) {
309
+ s->status |= SDHSTS_BLOCK_IRPT;
310
+ }
311
+
312
+ bcm2835_sdhost_update_irq(s);
313
+ }
314
+
315
+ s->edm &= ~(0x1f << 4);
316
+ s->edm |= ((s->fifo_len & 0x1f) << 4);
317
+}
318
+
319
+static uint64_t bcm2835_sdhost_read(void *opaque, hwaddr offset,
320
+ unsigned size)
321
+{
322
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
323
+ uint32_t res = 0;
324
+
325
+ switch (offset) {
326
+ case SDCMD:
327
+ res = s->cmd;
328
+ break;
329
+ case SDHSTS:
330
+ res = s->status;
331
+ break;
332
+ case SDRSP0:
333
+ res = s->rsp[0];
334
+ break;
335
+ case SDRSP1:
336
+ res = s->rsp[1];
337
+ break;
338
+ case SDRSP2:
339
+ res = s->rsp[2];
340
+ break;
341
+ case SDRSP3:
342
+ res = s->rsp[3];
343
+ break;
344
+ case SDEDM:
345
+ res = s->edm;
346
+ break;
347
+ case SDVDD:
348
+ res = s->vdd;
349
+ break;
350
+ case SDDATA:
351
+ res = bcm2835_sdhost_fifo_pop(s);
352
+ bcm2835_sdhost_fifo_run(s);
353
+ break;
354
+ case SDHBCT:
355
+ res = s->hbct;
356
+ break;
357
+ case SDHBLC:
358
+ res = s->hblc;
359
+ break;
360
+
361
+ default:
362
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
363
+ __func__, offset);
364
+ res = 0;
365
+ break;
366
+ }
367
+
368
+ return res;
369
+}
370
+
371
+static void bcm2835_sdhost_write(void *opaque, hwaddr offset,
372
+ uint64_t value, unsigned size)
373
+{
374
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
375
+
376
+ switch (offset) {
377
+ case SDCMD:
378
+ s->cmd = value;
379
+ if (value & SDCMD_NEW_FLAG) {
380
+ bcm2835_sdhost_send_command(s);
381
+ bcm2835_sdhost_fifo_run(s);
382
+ s->cmd &= ~SDCMD_NEW_FLAG;
383
+ }
384
+ break;
385
+ case SDTOUT:
386
+ break;
387
+ case SDCDIV:
388
+ break;
389
+ case SDHSTS:
390
+ s->status &= ~value;
391
+ bcm2835_sdhost_update_irq(s);
392
+ break;
393
+ case SDARG:
394
+ s->cmdarg = value;
395
+ break;
396
+ case SDEDM:
397
+ if ((value & 0xf) == 0xf) {
398
+ /* power down */
399
+ value &= ~0xf;
400
+ }
401
+ s->edm = value;
402
+ break;
403
+ case SDHCFG:
404
+ s->config = value;
405
+ bcm2835_sdhost_fifo_run(s);
406
+ break;
407
+ case SDVDD:
408
+ s->vdd = value;
409
+ break;
410
+ case SDDATA:
411
+ bcm2835_sdhost_fifo_push(s, value);
412
+ bcm2835_sdhost_fifo_run(s);
413
+ break;
414
+ case SDHBCT:
415
+ s->hbct = value;
416
+ break;
417
+ case SDHBLC:
418
+ s->hblc = value;
419
+ s->datacnt = s->hblc * s->hbct;
420
+ bcm2835_sdhost_fifo_run(s);
421
+ break;
422
+
423
+ default:
424
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
425
+ __func__, offset);
426
+ break;
427
+ }
428
+}
429
+
430
+static const MemoryRegionOps bcm2835_sdhost_ops = {
431
+ .read = bcm2835_sdhost_read,
432
+ .write = bcm2835_sdhost_write,
433
+ .endianness = DEVICE_NATIVE_ENDIAN,
434
+};
435
+
436
+static const VMStateDescription vmstate_bcm2835_sdhost = {
437
+ .name = TYPE_BCM2835_SDHOST,
438
+ .version_id = 1,
439
+ .minimum_version_id = 1,
440
+ .fields = (VMStateField[]) {
441
+ VMSTATE_UINT32(cmd, BCM2835SDHostState),
442
+ VMSTATE_UINT32(cmdarg, BCM2835SDHostState),
443
+ VMSTATE_UINT32(status, BCM2835SDHostState),
444
+ VMSTATE_UINT32_ARRAY(rsp, BCM2835SDHostState, 4),
445
+ VMSTATE_UINT32(config, BCM2835SDHostState),
446
+ VMSTATE_UINT32(edm, BCM2835SDHostState),
447
+ VMSTATE_UINT32(vdd, BCM2835SDHostState),
448
+ VMSTATE_UINT32(hbct, BCM2835SDHostState),
449
+ VMSTATE_UINT32(hblc, BCM2835SDHostState),
450
+ VMSTATE_INT32(fifo_pos, BCM2835SDHostState),
451
+ VMSTATE_INT32(fifo_len, BCM2835SDHostState),
452
+ VMSTATE_UINT32_ARRAY(fifo, BCM2835SDHostState, BCM2835_SDHOST_FIFO_LEN),
453
+ VMSTATE_UINT32(datacnt, BCM2835SDHostState),
454
+ VMSTATE_END_OF_LIST()
455
+ }
456
+};
457
+
458
+static void bcm2835_sdhost_init(Object *obj)
459
+{
460
+ BCM2835SDHostState *s = BCM2835_SDHOST(obj);
461
+
462
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
463
+ TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus");
464
+
465
+ memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s,
466
+ TYPE_BCM2835_SDHOST, 0x1000);
467
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
468
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
469
+}
470
+
471
+static void bcm2835_sdhost_reset(DeviceState *dev)
472
+{
473
+ BCM2835SDHostState *s = BCM2835_SDHOST(dev);
474
+
475
+ s->cmd = 0;
476
+ s->cmdarg = 0;
477
+ s->edm = 0x0000c60f;
478
+ s->config = 0;
479
+ s->hbct = 0;
480
+ s->hblc = 0;
481
+ s->datacnt = 0;
482
+ s->fifo_pos = 0;
483
+ s->fifo_len = 0;
484
+}
485
+
486
+static void bcm2835_sdhost_class_init(ObjectClass *klass, void *data)
487
+{
488
+ DeviceClass *dc = DEVICE_CLASS(klass);
489
+
490
+ dc->reset = bcm2835_sdhost_reset;
491
+ dc->vmsd = &vmstate_bcm2835_sdhost;
492
+}
493
+
494
+static TypeInfo bcm2835_sdhost_info = {
495
+ .name = TYPE_BCM2835_SDHOST,
496
+ .parent = TYPE_SYS_BUS_DEVICE,
497
+ .instance_size = sizeof(BCM2835SDHostState),
498
+ .class_init = bcm2835_sdhost_class_init,
499
+ .instance_init = bcm2835_sdhost_init,
500
+};
501
+
502
+static const TypeInfo bcm2835_sdhost_bus_info = {
503
+ .name = TYPE_BCM2835_SDHOST_BUS,
504
+ .parent = TYPE_SD_BUS,
505
+ .instance_size = sizeof(SDBus),
506
+};
507
+
508
+static void bcm2835_sdhost_register_types(void)
509
+{
510
+ type_register_static(&bcm2835_sdhost_info);
511
+ type_register_static(&bcm2835_sdhost_bus_info);
512
+}
513
+
514
+type_init(bcm2835_sdhost_register_types)
515
--
57
--
516
2.7.4
58
2.20.1
517
59
518
60
diff view generated by jsdifflib
1
Add a state field for the v7M PRIGROUP register and implent
1
The GICv3 specification says that the GICD_TYPER.SecurityExtn bit
2
reading and writing it. The current NVIC doesn't honour
2
is RAZ if GICD_CTLR.DS is 1. We were incorrectly making it RAZ
3
the values written, but the new version will.
3
if the security extension is unsupported. "Security extension
4
unsupported" always implies GICD_CTLR.DS == 1, but the guest can
5
also set DS on a GIC which does support the security extension.
6
Fix the condition to correctly check the GICD_CTLR.DS bit.
4
7
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20190524124248.28394-3-peter.maydell@linaro.org
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
---
10
---
9
hw/intc/armv7m_nvic.c | 14 ++++++++------
11
hw/intc/arm_gicv3_dist.c | 8 +++++++-
10
1 file changed, 8 insertions(+), 6 deletions(-)
12
1 file changed, 7 insertions(+), 1 deletion(-)
11
13
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
14
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
16
--- a/hw/intc/arm_gicv3_dist.c
15
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/hw/intc/arm_gicv3_dist.c
16
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
17
typedef struct NVICState {
19
* ITLinesNumber == (num external irqs / 32) - 1
18
GICState gic;
20
*/
19
ARMCPU *cpu;
21
int itlinesnumber = ((s->num_irq - GIC_INTERNAL) / 32) - 1;
20
+
22
+ /*
21
+ uint32_t prigroup;
23
+ * SecurityExtn must be RAZ if GICD_CTLR.DS == 1, and
22
+
24
+ * "security extensions not supported" always implies DS == 1,
23
struct {
25
+ * so we only need to check the DS bit.
24
uint32_t control;
26
+ */
25
uint32_t reload;
27
+ bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);
26
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
28
27
case 0xd08: /* Vector Table Offset. */
29
- *data = (1 << 25) | (1 << 24) | (s->security_extn << 10) |
28
return cpu->env.v7m.vecbase;
30
+ *data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
29
case 0xd0c: /* Application Interrupt/Reset Control. */
31
(0xf << 19) | itlinesnumber;
30
- return 0xfa050000;
32
return MEMTX_OK;
31
+ return 0xfa050000 | (s->prigroup << 8);
32
case 0xd10: /* System Control. */
33
/* TODO: Implement SLEEPONEXIT. */
34
return 0;
35
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
36
if (value & 1) {
37
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
38
}
39
- if (value & 0x700) {
40
- qemu_log_mask(LOG_UNIMP, "PRIGROUP unimplemented\n");
41
- }
42
+ s->prigroup = extract32(value, 8, 3);
43
}
44
break;
45
case 0xd10: /* System Control. */
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
47
48
static const VMStateDescription vmstate_nvic = {
49
.name = "armv7m_nvic",
50
- .version_id = 1,
51
- .minimum_version_id = 1,
52
+ .version_id = 2,
53
+ .minimum_version_id = 2,
54
.fields = (VMStateField[]) {
55
VMSTATE_UINT32(systick.control, NVICState),
56
VMSTATE_UINT32(systick.reload, NVICState),
57
VMSTATE_INT64(systick.tick, NVICState),
58
VMSTATE_TIMER_PTR(systick.timer, NVICState),
59
+ VMSTATE_UINT32(prigroup, NVICState),
60
VMSTATE_END_OF_LIST()
61
}
33
}
62
};
63
--
34
--
64
2.7.4
35
2.20.1
65
36
66
37
diff view generated by jsdifflib
1
Rename the nvic_state struct to NVICState, to match
1
We want to use vfp_expand_imm() in the AArch32 VFP decode;
2
our naming conventions.
2
move it from the a64-only header/source file to the
3
AArch32 one (which is always compiled even for AArch64).
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190613163917.28589-2-peter.maydell@linaro.org
7
---
9
---
8
hw/intc/armv7m_nvic.c | 44 ++++++++++++++++++++++----------------------
10
target/arm/translate-a64.h | 1 -
9
1 file changed, 22 insertions(+), 22 deletions(-)
11
target/arm/translate.h | 7 +++++++
12
target/arm/translate-a64.c | 32 --------------------------------
13
target/arm/translate-vfp.inc.c | 33 +++++++++++++++++++++++++++++++++
14
4 files changed, 40 insertions(+), 33 deletions(-)
10
15
11
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
16
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/armv7m_nvic.c
18
--- a/target/arm/translate-a64.h
14
+++ b/hw/intc/armv7m_nvic.c
19
+++ b/target/arm/translate-a64.h
15
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v);
16
#include "gic_internal.h"
21
TCGv_ptr get_fpstatus_ptr(bool);
17
#include "qemu/log.h"
22
bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
18
23
unsigned int imms, unsigned int immr);
19
-typedef struct {
24
-uint64_t vfp_expand_imm(int size, uint8_t imm8);
20
+typedef struct NVICState {
25
bool sve_access_check(DisasContext *s);
21
GICState gic;
26
22
ARMCPU *cpu;
27
/* We should have at some point before trying to access an FP register
23
struct {
28
diff --git a/target/arm/translate.h b/target/arm/translate.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
29
index XXXXXXX..XXXXXXX 100644
25
MemoryRegion container;
30
--- a/target/arm/translate.h
26
uint32_t num_irq;
31
+++ b/target/arm/translate.h
27
qemu_irq sysresetreq;
32
@@ -XXX,XX +XXX,XX @@ static inline void gen_ss_advance(DisasContext *s)
28
-} nvic_state;
29
+} NVICState;
30
31
#define TYPE_NVIC "armv7m_nvic"
32
/**
33
@@ -XXX,XX +XXX,XX @@ typedef struct NVICClass {
34
#define NVIC_GET_CLASS(obj) \
35
OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
36
#define NVIC(obj) \
37
- OBJECT_CHECK(nvic_state, (obj), TYPE_NVIC)
38
+ OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
39
40
static const uint8_t nvic_id[] = {
41
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
42
@@ -XXX,XX +XXX,XX @@ static const uint8_t nvic_id[] = {
43
int system_clock_scale;
44
45
/* Conversion factor from qemu timer to SysTick frequencies. */
46
-static inline int64_t systick_scale(nvic_state *s)
47
+static inline int64_t systick_scale(NVICState *s)
48
{
49
if (s->systick.control & SYSTICK_CLKSOURCE)
50
return system_clock_scale;
51
@@ -XXX,XX +XXX,XX @@ static inline int64_t systick_scale(nvic_state *s)
52
return 1000;
53
}
54
55
-static void systick_reload(nvic_state *s, int reset)
56
+static void systick_reload(NVICState *s, int reset)
57
{
58
/* The Cortex-M3 Devices Generic User Guide says that "When the
59
* ENABLE bit is set to 1, the counter loads the RELOAD value from the
60
@@ -XXX,XX +XXX,XX @@ static void systick_reload(nvic_state *s, int reset)
61
62
static void systick_timer_tick(void * opaque)
63
{
64
- nvic_state *s = (nvic_state *)opaque;
65
+ NVICState *s = (NVICState *)opaque;
66
s->systick.control |= SYSTICK_COUNTFLAG;
67
if (s->systick.control & SYSTICK_TICKINT) {
68
/* Trigger the interrupt. */
69
@@ -XXX,XX +XXX,XX @@ static void systick_timer_tick(void * opaque)
70
}
33
}
71
}
34
}
72
35
73
-static void systick_reset(nvic_state *s)
36
+/*
74
+static void systick_reset(NVICState *s)
37
+ * Given a VFP floating point constant encoded into an 8 bit immediate in an
75
{
38
+ * instruction, expand it to the actual constant value of the specified
76
s->systick.control = 0;
39
+ * size, as per the VFPExpandImm() pseudocode in the Arm ARM.
77
s->systick.reload = 0;
40
+ */
78
@@ -XXX,XX +XXX,XX @@ static void systick_reset(nvic_state *s)
41
+uint64_t vfp_expand_imm(int size, uint8_t imm8);
79
IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
42
+
80
void armv7m_nvic_set_pending(void *opaque, int irq)
43
/* Vector operations shared between ARM and AArch64. */
81
{
44
extern const GVecGen3 mla_op[4];
82
- nvic_state *s = (nvic_state *)opaque;
45
extern const GVecGen3 mls_op[4];
83
+ NVICState *s = (NVICState *)opaque;
46
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
84
if (irq >= 16)
47
index XXXXXXX..XXXXXXX 100644
85
irq += 16;
48
--- a/target/arm/translate-a64.c
86
gic_set_pending_private(&s->gic, 0, irq);
49
+++ b/target/arm/translate-a64.c
87
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
50
@@ -XXX,XX +XXX,XX @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
88
/* Make pending IRQ active. */
89
int armv7m_nvic_acknowledge_irq(void *opaque)
90
{
91
- nvic_state *s = (nvic_state *)opaque;
92
+ NVICState *s = (NVICState *)opaque;
93
uint32_t irq;
94
95
irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
96
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
97
98
void armv7m_nvic_complete_irq(void *opaque, int irq)
99
{
100
- nvic_state *s = (nvic_state *)opaque;
101
+ NVICState *s = (NVICState *)opaque;
102
if (irq >= 16)
103
irq += 16;
104
gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
105
}
106
107
-static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
108
+static uint32_t nvic_readl(NVICState *s, uint32_t offset)
109
{
110
ARMCPU *cpu = s->cpu;
111
uint32_t val;
112
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
113
}
51
}
114
}
52
}
115
53
116
-static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
54
-/* The imm8 encodes the sign bit, enough bits to represent an exponent in
117
+static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
55
- * the range 01....1xx to 10....0xx, and the most significant 4 bits of
118
{
56
- * the mantissa; see VFPExpandImm() in the v8 ARM ARM.
119
ARMCPU *cpu = s->cpu;
57
- */
120
uint32_t oldval;
58
-uint64_t vfp_expand_imm(int size, uint8_t imm8)
121
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
59
-{
122
static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
60
- uint64_t imm;
123
unsigned size)
61
-
124
{
62
- switch (size) {
125
- nvic_state *s = (nvic_state *)opaque;
63
- case MO_64:
126
+ NVICState *s = (NVICState *)opaque;
64
- imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
127
uint32_t offset = addr;
65
- (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
128
int i;
66
- extract32(imm8, 0, 6);
129
uint32_t val;
67
- imm <<= 48;
130
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
68
- break;
131
static void nvic_sysreg_write(void *opaque, hwaddr addr,
69
- case MO_32:
132
uint64_t value, unsigned size)
70
- imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
133
{
71
- (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
134
- nvic_state *s = (nvic_state *)opaque;
72
- (extract32(imm8, 0, 6) << 3);
135
+ NVICState *s = (NVICState *)opaque;
73
- imm <<= 16;
136
uint32_t offset = addr;
74
- break;
137
int i;
75
- case MO_16:
138
76
- imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
139
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
77
- (extract32(imm8, 6, 1) ? 0x3000 : 0x4000) |
140
.version_id = 1,
78
- (extract32(imm8, 0, 6) << 6);
141
.minimum_version_id = 1,
79
- break;
142
.fields = (VMStateField[]) {
80
- default:
143
- VMSTATE_UINT32(systick.control, nvic_state),
81
- g_assert_not_reached();
144
- VMSTATE_UINT32(systick.reload, nvic_state),
82
- }
145
- VMSTATE_INT64(systick.tick, nvic_state),
83
- return imm;
146
- VMSTATE_TIMER_PTR(systick.timer, nvic_state),
84
-}
147
+ VMSTATE_UINT32(systick.control, NVICState),
85
-
148
+ VMSTATE_UINT32(systick.reload, NVICState),
86
/* Floating point immediate
149
+ VMSTATE_INT64(systick.tick, NVICState),
87
* 31 30 29 28 24 23 22 21 20 13 12 10 9 5 4 0
150
+ VMSTATE_TIMER_PTR(systick.timer, NVICState),
88
* +---+---+---+-----------+------+---+------------+-------+------+------+
151
VMSTATE_END_OF_LIST()
89
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
152
}
90
index XXXXXXX..XXXXXXX 100644
153
};
91
--- a/target/arm/translate-vfp.inc.c
154
92
+++ b/target/arm/translate-vfp.inc.c
155
static void armv7m_nvic_reset(DeviceState *dev)
93
@@ -XXX,XX +XXX,XX @@
156
{
94
#include "decode-vfp.inc.c"
157
- nvic_state *s = NVIC(dev);
95
#include "decode-vfp-uncond.inc.c"
158
+ NVICState *s = NVIC(dev);
96
159
NVICClass *nc = NVIC_GET_CLASS(s);
97
+/*
160
nc->parent_reset(dev);
98
+ * The imm8 encodes the sign bit, enough bits to represent an exponent in
161
/* Common GIC reset resets to disabled; the NVIC doesn't have
99
+ * the range 01....1xx to 10....0xx, and the most significant 4 bits of
162
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
100
+ * the mantissa; see VFPExpandImm() in the v8 ARM ARM.
163
101
+ */
164
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
102
+uint64_t vfp_expand_imm(int size, uint8_t imm8)
165
{
103
+{
166
- nvic_state *s = NVIC(dev);
104
+ uint64_t imm;
167
+ NVICState *s = NVIC(dev);
105
+
168
NVICClass *nc = NVIC_GET_CLASS(s);
106
+ switch (size) {
169
Error *local_err = NULL;
107
+ case MO_64:
170
108
+ imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
171
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
109
+ (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
172
*/
110
+ extract32(imm8, 0, 6);
173
GICState *s = ARM_GIC_COMMON(obj);
111
+ imm <<= 48;
174
DeviceState *dev = DEVICE(obj);
112
+ break;
175
- nvic_state *nvic = NVIC(obj);
113
+ case MO_32:
176
+ NVICState *nvic = NVIC(obj);
114
+ imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
177
/* The ARM v7m may have anything from 0 to 496 external interrupt
115
+ (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
178
* IRQ lines. We default to 64. Other boards may differ and should
116
+ (extract32(imm8, 0, 6) << 3);
179
* set the num-irq property appropriately.
117
+ imm <<= 16;
180
@@ -XXX,XX +XXX,XX @@ static const TypeInfo armv7m_nvic_info = {
118
+ break;
181
.name = TYPE_NVIC,
119
+ case MO_16:
182
.parent = TYPE_ARM_GIC_COMMON,
120
+ imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
183
.instance_init = armv7m_nvic_instance_init,
121
+ (extract32(imm8, 6, 1) ? 0x3000 : 0x4000) |
184
- .instance_size = sizeof(nvic_state),
122
+ (extract32(imm8, 0, 6) << 6);
185
+ .instance_size = sizeof(NVICState),
123
+ break;
186
.class_init = armv7m_nvic_class_init,
124
+ default:
187
.class_size = sizeof(NVICClass),
125
+ g_assert_not_reached();
188
};
126
+ }
127
+ return imm;
128
+}
129
+
130
/*
131
* Return the offset of a 16-bit half of the specified VFP single-precision
132
* register. If top is true, returns the top 16 bits; otherwise the bottom
189
--
133
--
190
2.7.4
134
2.20.1
191
135
192
136
diff view generated by jsdifflib
1
From: Nick Reilly <nreilly@blackberry.com>
1
The AArch32 VMOV (immediate) instruction uses the same VFP encoded
2
immediate format we already handle in vfp_expand_imm(). Use that
3
function rather than hand-decoding it.
2
4
3
The aarch64 crypto instructions for AES and SHA are missing the
5
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
4
check for if the FPU is enabled.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20190613163917.28589-3-peter.maydell@linaro.org
10
---
11
target/arm/translate-vfp.inc.c | 28 ++++------------------------
12
target/arm/vfp.decode | 10 ++++++----
13
2 files changed, 10 insertions(+), 28 deletions(-)
5
14
6
Signed-off-by: Nick Reilly <nreilly@blackberry.com>
15
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/translate-a64.c | 12 ++++++++++++
11
1 file changed, 12 insertions(+)
12
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
17
--- a/target/arm/translate-vfp.inc.c
16
+++ b/target/arm/translate-a64.c
18
+++ b/target/arm/translate-vfp.inc.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
18
return;
20
uint32_t delta_d = 0;
21
int veclen = s->vec_len;
22
TCGv_i32 fd;
23
- uint32_t n, i, vd;
24
+ uint32_t vd;
25
26
vd = a->vd;
27
28
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
29
}
19
}
30
}
20
31
21
+ if (!fp_access_check(s)) {
32
- n = (a->imm4h << 28) & 0x80000000;
22
+ return;
33
- i = ((a->imm4h << 4) & 0x70) | a->imm4l;
23
+ }
34
- if (i & 0x40) {
35
- i |= 0x780;
36
- } else {
37
- i |= 0x800;
38
- }
39
- n |= i << 19;
40
-
41
- fd = tcg_temp_new_i32();
42
- tcg_gen_movi_i32(fd, n);
43
+ fd = tcg_const_i32(vfp_expand_imm(MO_32, a->imm));
44
45
for (;;) {
46
neon_store_reg32(fd, vd);
47
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
48
uint32_t delta_d = 0;
49
int veclen = s->vec_len;
50
TCGv_i64 fd;
51
- uint32_t n, i, vd;
52
+ uint32_t vd;
53
54
vd = a->vd;
55
56
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
57
}
58
}
59
60
- n = (a->imm4h << 28) & 0x80000000;
61
- i = ((a->imm4h << 4) & 0x70) | a->imm4l;
62
- if (i & 0x40) {
63
- i |= 0x3f80;
64
- } else {
65
- i |= 0x4000;
66
- }
67
- n |= i << 16;
68
-
69
- fd = tcg_temp_new_i64();
70
- tcg_gen_movi_i64(fd, ((uint64_t)n) << 32);
71
+ fd = tcg_const_i64(vfp_expand_imm(MO_64, a->imm));
72
73
for (;;) {
74
neon_store_reg64(fd, vd);
75
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/vfp.decode
78
+++ b/target/arm/vfp.decode
79
@@ -XXX,XX +XXX,XX @@
80
%vmov_idx_b 21:1 5:2
81
%vmov_idx_h 21:1 6:1
82
83
+%vmov_imm 16:4 0:4
24
+
84
+
25
/* Note that we convert the Vx register indexes into the
85
# VMOV scalar to general-purpose register; note that this does
26
* index within the vfp.regs[] array, so we can share the
86
# include some Neon cases.
27
* helper with the AArch32 instructions.
87
VMOV_to_gp ---- 1110 u:1 1. 1 .... rt:4 1011 ... 1 0000 \
28
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
88
@@ -XXX,XX +XXX,XX @@ VFM_sp ---- 1110 1.10 .... .... 1010 . o2:1 . 0 .... \
29
return;
89
VFM_dp ---- 1110 1.10 .... .... 1011 . o2:1 . 0 .... \
30
}
90
vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=2
31
91
32
+ if (!fp_access_check(s)) {
92
-VMOV_imm_sp ---- 1110 1.11 imm4h:4 .... 1010 0000 imm4l:4 \
33
+ return;
93
- vd=%vd_sp
34
+ }
94
-VMOV_imm_dp ---- 1110 1.11 imm4h:4 .... 1011 0000 imm4l:4 \
35
+
95
- vd=%vd_dp
36
tcg_rd_regno = tcg_const_i32(rd << 1);
96
+VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \
37
tcg_rn_regno = tcg_const_i32(rn << 1);
97
+ vd=%vd_sp imm=%vmov_imm
38
tcg_rm_regno = tcg_const_i32(rm << 1);
98
+VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \
39
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
99
+ vd=%vd_dp imm=%vmov_imm
40
return;
100
41
}
101
VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... \
42
102
vd=%vd_sp vm=%vm_sp
43
+ if (!fp_access_check(s)) {
44
+ return;
45
+ }
46
+
47
tcg_rd_regno = tcg_const_i32(rd << 1);
48
tcg_rn_regno = tcg_const_i32(rn << 1);
49
50
--
103
--
51
2.7.4
104
2.20.1
52
105
53
106
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
Where Neon instructions are floating point operations, we
2
mostly use the old VFP utility functions like gen_vfp_abs()
3
which work on the TCG globals cpu_F0s and cpu_F1s. The
4
Neon for-each-element loop conditionally loads the inputs
5
into either a plain old TCG temporary for most operations
6
or into cpu_F0s for float operations, and similarly stores
7
back either cpu_F0s or the temporary.
2
8
3
The Exynos4210 has cluster ID 0x9 in its MPIDR register (raw value
9
Switch NEON_2RM_VABS_F away from using cpu_F0s, and
4
0x8000090x). If this cluster ID is not provided, then Linux kernel
10
update neon_2rm_is_float_op() accordingly.
5
cannot map DeviceTree nodes to MPIDR values resulting in kernel
6
warning and lack of any secondary CPUs:
7
11
8
DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
...
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
smp: Bringing up secondary CPUs ...
14
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
smp: Brought up 1 node, 1 CPU
15
Message-id: 20190613163917.28589-4-peter.maydell@linaro.org
12
SMP: Total of 1 processors activated (24.00 BogoMIPS).
16
---
17
target/arm/translate.c | 19 ++++++++-----------
18
1 file changed, 8 insertions(+), 11 deletions(-)
13
19
14
Provide a cluster ID so Linux will see proper MPIDR and will try to
20
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
bring the secondary CPU online.
16
17
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
18
Message-id: 20170226200142.31169-2-krzk@kernel.org
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/arm/exynos4210.c | 12 ++++++++++++
23
1 file changed, 12 insertions(+)
24
25
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
26
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/exynos4210.c
22
--- a/target/arm/translate.c
28
+++ b/hw/arm/exynos4210.c
23
+++ b/target/arm/translate.c
29
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
24
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr get_fpstatus_ptr(int neon)
30
info->smp_loader_start);
25
return statusptr;
31
}
26
}
32
27
33
+static uint64_t exynos4210_calc_affinity(int cpu)
28
-static inline void gen_vfp_abs(int dp)
34
+{
29
-{
35
+ uint64_t mp_affinity;
30
- if (dp)
36
+
31
- gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
37
+ /* Exynos4210 has 0x9 as cluster ID */
32
- else
38
+ mp_affinity = (0x9 << ARM_AFF1_SHIFT) | cpu;
33
- gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
39
+
34
-}
40
+ return mp_affinity;
35
-
41
+}
36
static inline void gen_vfp_neg(int dp)
42
+
43
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
44
unsigned long ram_size)
45
{
37
{
46
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
38
if (dp)
47
}
39
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_3r_sizes[] = {
48
40
49
s->cpu[n] = ARM_CPU(cpuobj);
41
static int neon_2rm_is_float_op(int op)
50
+ object_property_set_int(cpuobj, exynos4210_calc_affinity(n),
42
{
51
+ "mp-affinity", &error_abort);
43
- /* Return true if this neon 2reg-misc op is float-to-float */
52
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
44
- return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
53
"reset-cbar", &error_abort);
45
+ /*
54
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
46
+ * Return true if this neon 2reg-misc op is float-to-float.
47
+ * This is not a property of the operation but of our code --
48
+ * what we are asking here is "does the code for this case in
49
+ * the Neon for-each-pass loop use cpu_F0s?".
50
+ */
51
+ return (op == NEON_2RM_VNEG_F ||
52
(op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
53
op == NEON_2RM_VRINTM ||
54
(op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
55
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
56
break;
57
}
58
case NEON_2RM_VABS_F:
59
- gen_vfp_abs(0);
60
+ gen_helper_vfp_abss(tmp, tmp);
61
break;
62
case NEON_2RM_VNEG_F:
63
gen_vfp_neg(0);
55
--
64
--
56
2.7.4
65
2.20.1
57
66
58
67
diff view generated by jsdifflib
1
Extract the code from the tail end of arm_v7m_do_interrupt() which
1
Switch NEON_2RM_VABS_F away from using cpu_F0s.
2
enters the exception handler into a pair of utility functions
3
v7m_exception_taken() and v7m_push_stack(), which correspond roughly
4
to the pseudocode PushStack() and ExceptionTaken().
5
6
This also requires us to move the arm_v7m_load_vector() utility
7
routine up so we can call it.
8
9
Handling illegal exception returns has some cases where we want to
10
take a UsageFault either on an existing stack frame or with a new
11
stack frame but with a specific LR value, so we want to be able to
12
call these without having to go via arm_v7m_cpu_do_interrupt().
13
2
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190613163917.28589-5-peter.maydell@linaro.org
16
---
7
---
17
target/arm/helper.c | 118 ++++++++++++++++++++++++++++++----------------------
8
target/arm/translate.c | 13 ++-----------
18
1 file changed, 68 insertions(+), 50 deletions(-)
9
1 file changed, 2 insertions(+), 11 deletions(-)
19
10
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
13
--- a/target/arm/translate.c
23
+++ b/target/arm/helper.c
14
+++ b/target/arm/translate.c
24
@@ -XXX,XX +XXX,XX @@ static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
15
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr get_fpstatus_ptr(int neon)
25
}
16
return statusptr;
26
}
17
}
27
18
28
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
19
-static inline void gen_vfp_neg(int dp)
29
+{
30
+ CPUState *cs = CPU(cpu);
31
+ CPUARMState *env = &cpu->env;
32
+ MemTxResult result;
33
+ hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
34
+ uint32_t addr;
35
+
36
+ addr = address_space_ldl(cs->as, vec,
37
+ MEMTXATTRS_UNSPECIFIED, &result);
38
+ if (result != MEMTX_OK) {
39
+ /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
40
+ * which would then be immediately followed by our failing to load
41
+ * the entry vector for that HardFault, which is a Lockup case.
42
+ * Since we don't model Lockup, we just report this guest error
43
+ * via cpu_abort().
44
+ */
45
+ cpu_abort(cs, "Failed to read from exception vector table "
46
+ "entry %08x\n", (unsigned)vec);
47
+ }
48
+ return addr;
49
+}
50
+
51
+static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
52
+{
53
+ /* Do the "take the exception" parts of exception entry,
54
+ * but not the pushing of state to the stack. This is
55
+ * similar to the pseudocode ExceptionTaken() function.
56
+ */
57
+ CPUARMState *env = &cpu->env;
58
+ uint32_t addr;
59
+
60
+ armv7m_nvic_acknowledge_irq(env->nvic);
61
+ switch_v7m_sp(env, 0);
62
+ /* Clear IT bits */
63
+ env->condexec_bits = 0;
64
+ env->regs[14] = lr;
65
+ addr = arm_v7m_load_vector(cpu);
66
+ env->regs[15] = addr & 0xfffffffe;
67
+ env->thumb = addr & 1;
68
+}
69
+
70
+static void v7m_push_stack(ARMCPU *cpu)
71
+{
72
+ /* Do the "set up stack frame" part of exception entry,
73
+ * similar to pseudocode PushStack().
74
+ */
75
+ CPUARMState *env = &cpu->env;
76
+ uint32_t xpsr = xpsr_read(env);
77
+
78
+ /* Align stack pointer if the guest wants that */
79
+ if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
80
+ env->regs[13] -= 4;
81
+ xpsr |= 0x200;
82
+ }
83
+ /* Switch to the handler mode. */
84
+ v7m_push(env, xpsr);
85
+ v7m_push(env, env->regs[15]);
86
+ v7m_push(env, env->regs[14]);
87
+ v7m_push(env, env->regs[12]);
88
+ v7m_push(env, env->regs[3]);
89
+ v7m_push(env, env->regs[2]);
90
+ v7m_push(env, env->regs[1]);
91
+ v7m_push(env, env->regs[0]);
92
+}
93
+
94
static void do_v7m_exception_exit(CPUARMState *env)
95
{
96
uint32_t type;
97
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
98
}
99
}
100
101
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
102
-
103
-{
20
-{
104
- CPUState *cs = CPU(cpu);
21
- if (dp)
105
- CPUARMState *env = &cpu->env;
22
- gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
106
- MemTxResult result;
23
- else
107
- hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
24
- gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
108
- uint32_t addr;
109
-
110
- addr = address_space_ldl(cs->as, vec,
111
- MEMTXATTRS_UNSPECIFIED, &result);
112
- if (result != MEMTX_OK) {
113
- /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
114
- * which would then be immediately followed by our failing to load
115
- * the entry vector for that HardFault, which is a Lockup case.
116
- * Since we don't model Lockup, we just report this guest error
117
- * via cpu_abort().
118
- */
119
- cpu_abort(cs, "Failed to read from exception vector table "
120
- "entry %08x\n", (unsigned)vec);
121
- }
122
- return addr;
123
-}
25
-}
124
-
26
-
125
void arm_v7m_cpu_do_interrupt(CPUState *cs)
27
#define VFP_GEN_ITOF(name) \
126
{
28
static inline void gen_vfp_##name(int dp, int neon) \
127
ARMCPU *cpu = ARM_CPU(cs);
29
{ \
128
CPUARMState *env = &cpu->env;
30
@@ -XXX,XX +XXX,XX @@ static int neon_2rm_is_float_op(int op)
129
- uint32_t xpsr = xpsr_read(env);
31
* what we are asking here is "does the code for this case in
130
uint32_t lr;
32
* the Neon for-each-pass loop use cpu_F0s?".
131
- uint32_t addr;
33
*/
132
34
- return (op == NEON_2RM_VNEG_F ||
133
arm_log_exception(cs->exception_index);
35
- (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
134
36
+ return ((op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
135
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
37
op == NEON_2RM_VRINTM ||
136
return; /* Never happens. Keep compiler happy. */
38
(op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
137
}
39
op >= NEON_2RM_VRECPE_F);
138
40
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
139
- armv7m_nvic_acknowledge_irq(env->nvic);
41
gen_helper_vfp_abss(tmp, tmp);
140
-
42
break;
141
+ v7m_push_stack(cpu);
43
case NEON_2RM_VNEG_F:
142
+ v7m_exception_taken(cpu, lr);
44
- gen_vfp_neg(0);
143
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
45
+ gen_helper_vfp_negs(tmp, tmp);
144
-
46
break;
145
- /* Align stack pointer if the guest wants that */
47
case NEON_2RM_VSWP:
146
- if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
48
tmp2 = neon_load_reg(rd, pass);
147
- env->regs[13] -= 4;
148
- xpsr |= 0x200;
149
- }
150
- /* Switch to the handler mode. */
151
- v7m_push(env, xpsr);
152
- v7m_push(env, env->regs[15]);
153
- v7m_push(env, env->regs[14]);
154
- v7m_push(env, env->regs[12]);
155
- v7m_push(env, env->regs[3]);
156
- v7m_push(env, env->regs[2]);
157
- v7m_push(env, env->regs[1]);
158
- v7m_push(env, env->regs[0]);
159
- switch_v7m_sp(env, 0);
160
- /* Clear IT bits */
161
- env->condexec_bits = 0;
162
- env->regs[14] = lr;
163
- addr = arm_v7m_load_vector(cpu);
164
- env->regs[15] = addr & 0xfffffffe;
165
- env->thumb = addr & 1;
166
}
167
168
/* Function used to synchronize QEMU's AArch64 register set with AArch32
169
--
49
--
170
2.7.4
50
2.20.1
171
51
172
52
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
Switch NEON_2RM_VRINT* away from using cpu_F0s.
2
2
3
Provide a new function sdbus_reparent_card() in sd core for reparenting
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
a card from a SDBus to another one.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190613163917.28589-6-peter.maydell@linaro.org
7
---
8
target/arm/translate.c | 8 +++-----
9
1 file changed, 3 insertions(+), 5 deletions(-)
5
10
6
This function is required by the raspi platform, where the two SD
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
7
controllers can be dynamically switched.
8
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
10
Message-id: 20170224164021.9066-3-clement.deschamps@antfield.fr
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
[PMM: added a doc comment to the header file]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
include/hw/sd/sd.h | 11 +++++++++++
16
hw/sd/core.c | 30 ++++++++++++++++++++++++++++++
17
2 files changed, 41 insertions(+)
18
19
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
20
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/sd/sd.h
13
--- a/target/arm/translate.c
22
+++ b/include/hw/sd/sd.h
14
+++ b/target/arm/translate.c
23
@@ -XXX,XX +XXX,XX @@ uint8_t sdbus_read_data(SDBus *sd);
15
@@ -XXX,XX +XXX,XX @@ static int neon_2rm_is_float_op(int op)
24
bool sdbus_data_ready(SDBus *sd);
16
* what we are asking here is "does the code for this case in
25
bool sdbus_get_inserted(SDBus *sd);
17
* the Neon for-each-pass loop use cpu_F0s?".
26
bool sdbus_get_readonly(SDBus *sd);
18
*/
27
+/**
19
- return ((op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
28
+ * sdbus_reparent_card: Reparent an SD card from one controller to another
20
- op == NEON_2RM_VRINTM ||
29
+ * @from: controller bus to remove card from
21
- (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
30
+ * @to: controller bus to move card to
22
+ return ((op >= NEON_2RM_VCVTAU && op <= NEON_2RM_VCVTMS) ||
31
+ *
23
op >= NEON_2RM_VRECPE_F);
32
+ * Reparent an SD card, effectively unplugging it from one controller
33
+ * and inserting it into another. This is useful for SoCs like the
34
+ * bcm2835 which have two SD controllers and connect a single SD card
35
+ * to them, selected by the guest reprogramming GPIO line routing.
36
+ */
37
+void sdbus_reparent_card(SDBus *from, SDBus *to);
38
39
/* Functions to be used by SD devices to report back to qdevified controllers */
40
void sdbus_set_inserted(SDBus *sd, bool inserted);
41
diff --git a/hw/sd/core.c b/hw/sd/core.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/sd/core.c
44
+++ b/hw/sd/core.c
45
@@ -XXX,XX +XXX,XX @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly)
46
}
47
}
24
}
48
25
49
+void sdbus_reparent_card(SDBus *from, SDBus *to)
26
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
50
+{
27
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
51
+ BusChild *kid = QTAILQ_FIRST(&from->qbus.children);
28
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
52
+ SDState *card;
29
cpu_env);
53
+ SDCardClass *sc;
30
- gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
54
+ bool readonly;
31
+ gen_helper_rints(tmp, tmp, fpstatus);
55
+
32
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
56
+ /* We directly reparent the card object rather than implementing this
33
cpu_env);
57
+ * as a hotpluggable connection because we don't want to expose SD cards
34
tcg_temp_free_ptr(fpstatus);
58
+ * to users as being hotpluggable, and we can get away with it in this
35
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
59
+ * limited use case. This could perhaps be implemented more cleanly in
36
case NEON_2RM_VRINTX:
60
+ * future by adding support to the hotplug infrastructure for "device
37
{
61
+ * can be hotplugged only via code, not by user".
38
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
62
+ */
39
- gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
63
+
40
+ gen_helper_rints_exact(tmp, tmp, fpstatus);
64
+ if (!kid) {
41
tcg_temp_free_ptr(fpstatus);
65
+ return;
42
break;
66
+ }
43
}
67
+
68
+ card = SD_CARD(kid->child);
69
+ sc = SD_CARD_GET_CLASS(card);
70
+ readonly = sc->get_readonly(card);
71
+
72
+ sdbus_set_inserted(from, false);
73
+ object_unparent(OBJECT(kid));
74
+ qdev_set_parent_bus(DEVICE(card), &to->qbus);
75
+ sdbus_set_inserted(to, true);
76
+ sdbus_set_readonly(to, readonly);
77
+}
78
+
79
static const TypeInfo sd_bus_info = {
80
.name = TYPE_SD_BUS,
81
.parent = TYPE_BUS,
82
--
44
--
83
2.7.4
45
2.20.1
84
46
85
47
diff view generated by jsdifflib
1
Switch to using qcrypto_random_bytes() rather than rand() as
1
Stop using cpu_F0s for the NEON_2RM_VCVT[ANPM][US] ops.
2
our source of randomness for the BCM2835 RNG.
3
4
If qcrypto_random_bytes() fails, we don't want to return the guest a
5
non-random value in case they're really using it for cryptographic
6
purposes, so the best we can do is a fatal error. This shouldn't
7
happen unless something's broken, though.
8
9
In theory we could implement this device's full FIFO and interrupt
10
semantics and then just stop filling the FIFO. That's a lot of work,
11
though, and doesn't really give a very nice diagnostic to the user
12
since the guest will just seem to hang.
13
2
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190613163917.28589-7-peter.maydell@linaro.org
16
---
7
---
17
hw/misc/bcm2835_rng.c | 27 ++++++++++++++++++++++++++-
8
target/arm/translate.c | 7 +++----
18
1 file changed, 26 insertions(+), 1 deletion(-)
9
1 file changed, 3 insertions(+), 4 deletions(-)
19
10
20
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/bcm2835_rng.c
13
--- a/target/arm/translate.c
23
+++ b/hw/misc/bcm2835_rng.c
14
+++ b/target/arm/translate.c
24
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ static int neon_2rm_is_float_op(int op)
25
16
* what we are asking here is "does the code for this case in
26
#include "qemu/osdep.h"
17
* the Neon for-each-pass loop use cpu_F0s?".
27
#include "qemu/log.h"
18
*/
28
+#include "qapi/error.h"
19
- return ((op >= NEON_2RM_VCVTAU && op <= NEON_2RM_VCVTMS) ||
29
+#include "crypto/random.h"
20
- op >= NEON_2RM_VRECPE_F);
30
#include "hw/misc/bcm2835_rng.h"
21
+ return op >= NEON_2RM_VRECPE_F;
31
22
}
32
+static uint32_t get_random_bytes(void)
23
33
+{
24
static bool neon_2rm_is_v8_op(int op)
34
+ uint32_t res;
25
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
35
+ Error *err = NULL;
26
cpu_env);
36
+
27
37
+ if (qcrypto_random_bytes((uint8_t *)&res, sizeof(res), &err) < 0) {
28
if (is_signed) {
38
+ /* On failure we don't want to return the guest a non-random
29
- gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
39
+ * value in case they're really using it for cryptographic
30
+ gen_helper_vfp_tosls(tmp, tmp,
40
+ * purposes, so the best we can do is die here.
31
tcg_shift, fpst);
41
+ * This shouldn't happen unless something's broken.
32
} else {
42
+ * In theory we could implement this device's full FIFO
33
- gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
43
+ * and interrupt semantics and then just stop filling the
34
+ gen_helper_vfp_touls(tmp, tmp,
44
+ * FIFO. That's a lot of work, though, so we assume any
35
tcg_shift, fpst);
45
+ * errors are systematic problems and trust that if we didn't
36
}
46
+ * fail as the guest inited then we won't fail later on
37
47
+ * mid-run.
48
+ */
49
+ error_report_err(err);
50
+ exit(1);
51
+ }
52
+ return res;
53
+}
54
+
55
static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
56
unsigned size)
57
{
58
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
59
res = s->rng_status | (1 << 24);
60
break;
61
case 0x8: /* rng_data */
62
- res = rand();
63
+ res = get_random_bytes();
64
break;
65
66
default:
67
--
38
--
68
2.7.4
39
2.20.1
69
40
70
41
diff view generated by jsdifflib
Deleted patch
1
From: Prasad J Pandit <pjp@fedoraproject.org>
2
1
3
In SDHCI protocol, the transfer mode register is defined
4
to be of 6 bits. Mask its value with '0x0037' so that an
5
invalid value could not be assigned.
6
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
9
Message-id: 20170214185225.7994-2-ppandit@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/sd/sdhci.c | 3 ++-
13
1 file changed, 2 insertions(+), 1 deletion(-)
14
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
18
+++ b/hw/sd/sdhci.c
19
@@ -XXX,XX +XXX,XX @@
20
(SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
21
(SDHC_CAPAB_TOCLKFREQ))
22
23
+#define MASK_TRNMOD 0x0037
24
#define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val))
25
26
static uint8_t sdhci_slotint(SDHCIState *s)
27
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
28
if (!(s->capareg & SDHC_CAN_DO_DMA)) {
29
value &= ~SDHC_TRNS_DMA;
30
}
31
- MASKED_WRITE(s->trnmod, mask, value);
32
+ MASKED_WRITE(s->trnmod, mask, value & MASK_TRNMOD);
33
MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
34
35
/* Writing to the upper byte of CMDREG triggers SD command generation */
36
--
37
2.7.4
38
39
diff view generated by jsdifflib
Deleted patch
1
From: Prasad J Pandit <pjp@fedoraproject.org>
2
1
3
In the SDHCI protocol, the transfer mode register value
4
is used during multi block transfer to check if block count
5
register is enabled and should be updated. Transfer mode
6
register could be set such that, block count register would
7
not be updated, thus leading to an infinite loop. Add check
8
to avoid it.
9
10
Reported-by: Wjjzhang <wjjzhang@tencent.com>
11
Reported-by: Jiang Xin <jiangxin1@huawei.com>
12
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
13
Message-id: 20170214185225.7994-3-ppandit@redhat.com
14
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/sd/sdhci.c | 10 +++++-----
18
1 file changed, 5 insertions(+), 5 deletions(-)
19
20
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/sd/sdhci.c
23
+++ b/hw/sd/sdhci.c
24
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
25
uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12);
26
uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk);
27
28
+ if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) {
29
+ qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n");
30
+ return;
31
+ }
32
+
33
/* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for
34
* possible stop at page boundary if initial address is not page aligned,
35
* allow them to work properly */
36
@@ -XXX,XX +XXX,XX @@ static void sdhci_data_transfer(void *opaque)
37
if (s->trnmod & SDHC_TRNS_DMA) {
38
switch (SDHC_DMA_TYPE(s->hostctl)) {
39
case SDHC_CTRL_SDMA:
40
- if ((s->trnmod & SDHC_TRNS_MULTI) &&
41
- (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) {
42
- break;
43
- }
44
-
45
if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
46
sdhci_sdma_transfer_single_block(s);
47
} else {
48
--
49
2.7.4
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Prasad J Pandit <pjp@fedoraproject.org>
2
1
3
In sdhci_write invoke multi block transfer if it is enabled
4
in the transfer mode register 's->trnmod'.
5
6
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
7
Message-id: 20170214185225.7994-4-ppandit@redhat.com
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/sd/sdhci.c | 6 +++++-
12
1 file changed, 5 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/sd/sdhci.c
17
+++ b/hw/sd/sdhci.c
18
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
19
/* Writing to last byte of sdmasysad might trigger transfer */
20
if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
21
s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
22
- sdhci_sdma_transfer_multi_blocks(s);
23
+ if (s->trnmod & SDHC_TRNS_MULTI) {
24
+ sdhci_sdma_transfer_multi_blocks(s);
25
+ } else {
26
+ sdhci_sdma_transfer_single_block(s);
27
+ }
28
}
29
break;
30
case SDHC_BLKSIZE:
31
--
32
2.7.4
33
34
diff view generated by jsdifflib
1
From: Kurban Mallachiev <mallachiev@ispras.ru>
1
Stop using cpu_F0s for NEON_2RM_VRECPE_F and NEON_2RM_VRSQRTE_F.
2
2
3
The i.MX timer device can be reset by writing to the SWR bit
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
of the CR register. This has to behave differently from hard
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
(power-on) reset because it does not reset all of the bits
5
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
in the CR register.
6
Message-id: 20190613163917.28589-8-peter.maydell@linaro.org
7
---
8
target/arm/translate.c | 6 +++---
9
1 file changed, 3 insertions(+), 3 deletions(-)
7
10
8
We were incorrectly implementing soft reset and hard reset
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
9
the same way, and in addition had a logic error which meant
10
that we were clearing the bits that soft-reset is supposed
11
to preserve and not touching the bits that soft-reset clears.
12
This was not correct behaviour for either kind of reset.
13
14
Separate out the soft reset and hard reset code paths, and
15
correct the handling of reset of the CR register so that it
16
is correct in both cases.
17
18
Signed-off-by: Kurban Mallachiev <mallachiev@ispras.ru>
19
[PMM: rephrased commit message, spacing on operators;
20
use bool rather than int for is_soft_reset]
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
hw/timer/imx_gpt.c | 33 +++++++++++++++++++++++++--------
25
1 file changed, 25 insertions(+), 8 deletions(-)
26
27
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
28
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/timer/imx_gpt.c
13
--- a/target/arm/translate.c
30
+++ b/hw/timer/imx_gpt.c
14
+++ b/target/arm/translate.c
31
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
15
@@ -XXX,XX +XXX,XX @@ static int neon_2rm_is_float_op(int op)
32
return reg_value;
16
* what we are asking here is "does the code for this case in
17
* the Neon for-each-pass loop use cpu_F0s?".
18
*/
19
- return op >= NEON_2RM_VRECPE_F;
20
+ return op >= NEON_2RM_VCVT_FS;
33
}
21
}
34
22
35
-static void imx_gpt_reset(DeviceState *dev)
23
static bool neon_2rm_is_v8_op(int op)
36
-{
24
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
37
- IMXGPTState *s = IMX_GPT(dev);
25
case NEON_2RM_VRECPE_F:
38
26
{
39
+static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
27
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
40
+{
28
- gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
41
/* stop timer */
29
+ gen_helper_recpe_f32(tmp, tmp, fpstatus);
42
ptimer_stop(s->timer);
30
tcg_temp_free_ptr(fpstatus);
43
31
break;
44
- /*
32
}
45
- * Soft reset doesn't touch some bits; hard reset clears them
33
case NEON_2RM_VRSQRTE_F:
46
+ /* Soft reset and hard reset differ only in their handling of the CR
34
{
47
+ * register -- soft reset preserves the values of some bits there.
35
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
48
*/
36
- gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
49
- s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
37
+ gen_helper_rsqrte_f32(tmp, tmp, fpstatus);
50
- GPT_CR_WAITEN|GPT_CR_DBGEN);
38
tcg_temp_free_ptr(fpstatus);
51
+ if (is_soft_reset) {
39
break;
52
+ /* Clear all CR bits except those that are preserved by soft reset. */
40
}
53
+ s->cr &= GPT_CR_EN | GPT_CR_ENMOD | GPT_CR_STOPEN | GPT_CR_DOZEN |
54
+ GPT_CR_WAITEN | GPT_CR_DBGEN |
55
+ (GPT_CR_CLKSRC_MASK << GPT_CR_CLKSRC_SHIFT);
56
+ } else {
57
+ s->cr = 0;
58
+ }
59
s->sr = 0;
60
s->pr = 0;
61
s->ir = 0;
62
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_reset(DeviceState *dev)
63
}
64
}
65
66
+static void imx_gpt_soft_reset(DeviceState *dev)
67
+{
68
+ IMXGPTState *s = IMX_GPT(dev);
69
+ imx_gpt_reset_common(s, true);
70
+}
71
+
72
+static void imx_gpt_reset(DeviceState *dev)
73
+{
74
+ IMXGPTState *s = IMX_GPT(dev);
75
+ imx_gpt_reset_common(s, false);
76
+}
77
+
78
static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
79
unsigned size)
80
{
81
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
82
s->cr = value & ~0x7c14;
83
if (s->cr & GPT_CR_SWR) { /* force reset */
84
/* handle the reset */
85
- imx_gpt_reset(DEVICE(s));
86
+ imx_gpt_soft_reset(DEVICE(s));
87
} else {
88
/* set our freq, as the source might have changed */
89
imx_gpt_set_freq(s);
90
--
41
--
91
2.7.4
42
2.20.1
92
43
93
44
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
Stop using cpu_F0s for the Neon f32/s32 VCVT operations.
2
Since this is the last user of cpu_F0s in the Neon 2rm-op
3
loop, we can remove the handling code for it too.
2
4
3
Now that the NVIC is its own separate implementation, we can
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
clean up the GIC code by removing REV_NVIC and conditionals
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
which use it.
7
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190613163917.28589-9-peter.maydell@linaro.org
9
---
10
target/arm/translate.c | 82 ++++++++++++------------------------------
11
1 file changed, 22 insertions(+), 60 deletions(-)
6
12
7
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
---
11
hw/intc/gic_internal.h | 7 ++-----
12
hw/intc/arm_gic.c | 31 +++++--------------------------
13
hw/intc/arm_gic_common.c | 23 ++++++++---------------
14
3 files changed, 15 insertions(+), 46 deletions(-)
15
16
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/gic_internal.h
15
--- a/target/arm/translate.c
19
+++ b/hw/intc/gic_internal.h
16
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr get_fpstatus_ptr(int neon)
21
18
return statusptr;
22
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
23
24
-/* The NVIC has 16 internal vectors. However these are not exposed
25
- through the normal GIC interface. */
26
-#define GIC_BASE_IRQ ((s->revision == REV_NVIC) ? 32 : 0)
27
+#define GIC_BASE_IRQ 0
28
29
#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
30
#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
31
@@ -XXX,XX +XXX,XX @@
32
33
/* The special cases for the revision property: */
34
#define REV_11MPCORE 0
35
-#define REV_NVIC 0xffffffff
36
37
void gic_set_pending_private(GICState *s, int cpu, int irq);
38
uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs);
39
@@ -XXX,XX +XXX,XX @@ void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val,
40
41
static inline bool gic_test_pending(GICState *s, int irq, int cm)
42
{
43
- if (s->revision == REV_NVIC || s->revision == REV_11MPCORE) {
44
+ if (s->revision == REV_11MPCORE) {
45
return s->irq_state[irq].pending & cm;
46
} else {
47
/* Edge-triggered interrupts are marked pending on a rising edge, but
48
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/intc/arm_gic.c
51
+++ b/hw/intc/arm_gic.c
52
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq_11mpcore(GICState *s, int irq, int level,
53
}
54
}
19
}
55
20
56
-static void gic_set_irq_nvic(GICState *s, int irq, int level,
21
-#define VFP_GEN_ITOF(name) \
57
- int cm, int target)
22
-static inline void gen_vfp_##name(int dp, int neon) \
58
-{
23
-{ \
59
- if (level) {
24
- TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
60
- GIC_SET_LEVEL(irq, cm);
25
- if (dp) { \
61
- GIC_SET_PENDING(irq, target);
26
- gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
62
- } else {
27
- } else { \
63
- GIC_CLEAR_LEVEL(irq, cm);
28
- gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
64
- }
29
- } \
30
- tcg_temp_free_ptr(statusptr); \
65
-}
31
-}
66
-
32
-
67
static void gic_set_irq_generic(GICState *s, int irq, int level,
33
-VFP_GEN_ITOF(uito)
68
int cm, int target)
34
-VFP_GEN_ITOF(sito)
35
-#undef VFP_GEN_ITOF
36
-
37
-#define VFP_GEN_FTOI(name) \
38
-static inline void gen_vfp_##name(int dp, int neon) \
39
-{ \
40
- TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
41
- if (dp) { \
42
- gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
43
- } else { \
44
- gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
45
- } \
46
- tcg_temp_free_ptr(statusptr); \
47
-}
48
-
49
-VFP_GEN_FTOI(touiz)
50
-VFP_GEN_FTOI(tosiz)
51
-#undef VFP_GEN_FTOI
52
-
53
#define VFP_GEN_FIX(name, round) \
54
static inline void gen_vfp_##name(int dp, int shift, int neon) \
55
{ \
56
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_3r_sizes[] = {
57
#define NEON_2RM_VCVT_SF 62
58
#define NEON_2RM_VCVT_UF 63
59
60
-static int neon_2rm_is_float_op(int op)
61
-{
62
- /*
63
- * Return true if this neon 2reg-misc op is float-to-float.
64
- * This is not a property of the operation but of our code --
65
- * what we are asking here is "does the code for this case in
66
- * the Neon for-each-pass loop use cpu_F0s?".
67
- */
68
- return op >= NEON_2RM_VCVT_FS;
69
-}
70
-
71
static bool neon_2rm_is_v8_op(int op)
69
{
72
{
70
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq(void *opaque, int irq, int level)
73
/* Return true if this neon 2reg-misc op is ARMv8 and up */
71
74
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
72
if (s->revision == REV_11MPCORE) {
75
default:
73
gic_set_irq_11mpcore(s, irq, level, cm, target);
76
elementwise:
74
- } else if (s->revision == REV_NVIC) {
77
for (pass = 0; pass < (q ? 4 : 2); pass++) {
75
- gic_set_irq_nvic(s, irq, level, cm, target);
78
- if (neon_2rm_is_float_op(op)) {
76
} else {
79
- tcg_gen_ld_f32(cpu_F0s, cpu_env,
77
gic_set_irq_generic(s, irq, level, cm, target);
80
- neon_reg_offset(rm, pass));
78
}
81
- tmp = NULL;
79
@@ -XXX,XX +XXX,XX @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
82
- } else {
80
return 1023;
83
- tmp = neon_load_reg(rm, pass);
81
}
84
- }
82
85
+ tmp = neon_load_reg(rm, pass);
83
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
86
switch (op) {
84
+ if (s->revision == REV_11MPCORE) {
87
case NEON_2RM_VREV32:
85
/* Clear pending flags for both level and edge triggered interrupts.
88
switch (size) {
86
* Level triggered IRQs will be reasserted once they become inactive.
89
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
87
*/
90
break;
88
@@ -XXX,XX +XXX,XX @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
91
}
89
DPRINTF("Set %d pending mask %x\n", irq, cm);
92
case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
90
GIC_SET_PENDING(irq, cm);
93
- gen_vfp_sito(0, 1);
91
}
94
+ {
92
- } else if (s->revision == REV_NVIC) {
95
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
93
- if (GIC_TEST_LEVEL(irq, cm)) {
96
+ gen_helper_vfp_sitos(tmp, tmp, fpstatus);
94
- DPRINTF("Set nvic %d pending mask %x\n", irq, cm);
97
+ tcg_temp_free_ptr(fpstatus);
95
- GIC_SET_PENDING(irq, cm);
98
break;
96
- }
99
+ }
97
}
100
case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
98
101
- gen_vfp_uito(0, 1);
99
group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
102
+ {
100
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
103
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
101
} else if (offset < 0xf10) {
104
+ gen_helper_vfp_uitos(tmp, tmp, fpstatus);
102
goto bad_reg;
105
+ tcg_temp_free_ptr(fpstatus);
103
} else if (offset < 0xf30) {
106
break;
104
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
107
+ }
105
+ if (s->revision == REV_11MPCORE) {
108
case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
106
goto bad_reg;
109
- gen_vfp_tosiz(0, 1);
107
}
110
+ {
108
111
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
109
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
112
+ gen_helper_vfp_tosizs(tmp, tmp, fpstatus);
110
case 2:
113
+ tcg_temp_free_ptr(fpstatus);
111
res = gic_id_gicv2[(offset - 0xfd0) >> 2];
114
break;
112
break;
115
+ }
113
- case REV_NVIC:
116
case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
114
- /* Shouldn't be able to get here */
117
- gen_vfp_touiz(0, 1);
115
- abort();
118
+ {
116
default:
119
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
117
res = 0;
120
+ gen_helper_vfp_touizs(tmp, tmp, fpstatus);
118
}
121
+ tcg_temp_free_ptr(fpstatus);
119
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
122
break;
120
continue; /* Ignore Non-secure access of Group0 IRQ */
123
+ }
121
}
124
default:
122
125
/* Reserved op values were caught by the
123
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
126
* neon_2rm_sizes[] check earlier.
124
+ if (s->revision == REV_11MPCORE) {
127
*/
125
if (value & (1 << (i * 2))) {
128
abort();
126
GIC_SET_MODEL(irq + i);
129
}
127
} else {
130
- if (neon_2rm_is_float_op(op)) {
128
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
131
- tcg_gen_st_f32(cpu_F0s, cpu_env,
129
goto bad_reg;
132
- neon_reg_offset(rd, pass));
130
} else if (offset < 0xf20) {
133
- } else {
131
/* GICD_CPENDSGIRn */
134
- neon_store_reg(rd, pass, tmp);
132
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
135
- }
133
+ if (s->revision == REV_11MPCORE) {
136
+ neon_store_reg(rd, pass, tmp);
134
goto bad_reg;
137
}
135
}
138
break;
136
irq = (offset - 0xf10);
139
}
137
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
138
}
139
} else if (offset < 0xf30) {
140
/* GICD_SPENDSGIRn */
141
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
142
+ if (s->revision == REV_11MPCORE) {
143
goto bad_reg;
144
}
145
irq = (offset - 0xf20);
146
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/intc/arm_gic_common.c
149
+++ b/hw/intc/arm_gic_common.c
150
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
151
* [N+32..N+63] PPIs for CPU 1
152
* ...
153
*/
154
- if (s->revision != REV_NVIC) {
155
- i += (GIC_INTERNAL * s->num_cpu);
156
- }
157
+ i += (GIC_INTERNAL * s->num_cpu);
158
qdev_init_gpio_in(DEVICE(s), handler, i);
159
160
for (i = 0; i < s->num_cpu; i++) {
161
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
162
memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
163
sysbus_init_mmio(sbd, &s->iomem);
164
165
- if (s->revision != REV_NVIC) {
166
- /* This is the main CPU interface "for this core". It is always
167
- * present because it is required by both software emulation and KVM.
168
- * NVIC is not handled here because its CPU interface is different,
169
- * neither it can use KVM.
170
- */
171
- memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
172
- s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
173
- sysbus_init_mmio(sbd, &s->cpuiomem[0]);
174
- }
175
+ /* This is the main CPU interface "for this core". It is always
176
+ * present because it is required by both software emulation and KVM.
177
+ */
178
+ memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
179
+ s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
180
+ sysbus_init_mmio(sbd, &s->cpuiomem[0]);
181
}
182
183
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
184
@@ -XXX,XX +XXX,XX @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
185
}
186
187
if (s->security_extn &&
188
- (s->revision == REV_11MPCORE || s->revision == REV_NVIC)) {
189
+ (s->revision == REV_11MPCORE)) {
190
error_setg(errp, "this GIC revision does not implement "
191
"the security extensions");
192
return;
193
@@ -XXX,XX +XXX,XX @@ static Property arm_gic_common_properties[] = {
194
DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
195
/* Revision can be 1 or 2 for GIC architecture specification
196
* versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC.
197
- * (Internally, 0xffffffff also indicates "not a GIC but an NVIC".)
198
*/
199
DEFINE_PROP_UINT32("revision", GICState, revision, 1),
200
/* True if the GIC should implement the security extensions */
201
--
140
--
202
2.7.4
141
2.20.1
203
142
204
143
diff view generated by jsdifflib
1
In get_page_addr_code(), if the guest PC doesn't correspond to RAM
1
Stop using cpu_F0s in the Neon VCVT fixed-point operations.
2
then we currently run the CPU's do_unassigned_access() hook if it has
3
one, and otherwise we give up and exit QEMU with a more-or-less
4
useful message. This code assumes that the do_unassigned_access hook
5
will never return, because if it does then we'll plough on attempting
6
to use a non-RAM TLB entry to get a RAM address and will abort() in
7
qemu_ram_addr_from_host_nofail(). Unfortunately some CPU
8
implementations of this hook do return: Microblaze, SPARC and the ARM
9
v7M.
10
11
Change the code to call report_bad_exec() if the hook returns, as
12
well as if it didn't have one. This means we can tidy it up to use
13
the cpu_unassigned_access() function which wraps the "get the CPU
14
class and call the hook if it has one" work, since we aren't trying
15
to distinguish "no hook" from "hook existed and returned" any more.
16
17
This brings the handling of this hook into line with the handling
18
used for data accesses, where "hook returned" is treated the
19
same as "no hook existed" and gets you the default behaviour.
20
2
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <rth@twiddle.net>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190613163917.28589-10-peter.maydell@linaro.org
23
---
7
---
24
cputlb.c | 15 +++++++--------
8
target/arm/translate.c | 62 +++++++++++++++++++-----------------------
25
1 file changed, 7 insertions(+), 8 deletions(-)
9
1 file changed, 28 insertions(+), 34 deletions(-)
26
10
27
diff --git a/cputlb.c b/cputlb.c
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
28
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
29
--- a/cputlb.c
13
--- a/target/arm/translate.c
30
+++ b/cputlb.c
14
+++ b/target/arm/translate.c
31
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
15
@@ -XXX,XX +XXX,XX @@ static const char * const regnames[] =
32
pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
16
/* Function prototypes for gen_ functions calling Neon helpers. */
33
mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
17
typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
34
if (memory_region_is_unassigned(mr)) {
18
TCGv_i32, TCGv_i32);
35
- CPUClass *cc = CPU_GET_CLASS(cpu);
19
+/* Function prototypes for gen_ functions for fix point conversions */
20
+typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
21
22
/* initialize TCG globals. */
23
void arm_translate_init(void)
24
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr get_fpstatus_ptr(int neon)
25
return statusptr;
26
}
27
28
-#define VFP_GEN_FIX(name, round) \
29
-static inline void gen_vfp_##name(int dp, int shift, int neon) \
30
-{ \
31
- TCGv_i32 tmp_shift = tcg_const_i32(shift); \
32
- TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
33
- if (dp) { \
34
- gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
35
- statusptr); \
36
- } else { \
37
- gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
38
- statusptr); \
39
- } \
40
- tcg_temp_free_i32(tmp_shift); \
41
- tcg_temp_free_ptr(statusptr); \
42
-}
43
-VFP_GEN_FIX(tosl, _round_to_zero)
44
-VFP_GEN_FIX(toul, _round_to_zero)
45
-VFP_GEN_FIX(slto, )
46
-VFP_GEN_FIX(ulto, )
47
-#undef VFP_GEN_FIX
36
-
48
-
37
- if (cc->do_unassigned_access) {
49
static inline long vfp_reg_offset(bool dp, unsigned reg)
38
- cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
50
{
39
- } else {
51
if (dp) {
40
- report_bad_exec(cpu, addr);
52
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
41
- exit(1);
53
}
42
- }
54
} else if (op >= 14) {
43
+ cpu_unassigned_access(cpu, addr, false, true, 0, 4);
55
/* VCVT fixed-point. */
44
+ /* The CPU's unassigned access hook might have longjumped out
56
+ TCGv_ptr fpst;
45
+ * with an exception. If it didn't (or there was no hook) then
57
+ TCGv_i32 shiftv;
46
+ * we can't proceed further.
58
+ VFPGenFixPointFn *fn;
47
+ */
59
+
48
+ report_bad_exec(cpu, addr);
60
if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
49
+ exit(1);
61
return 1;
50
}
62
}
51
p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
63
+
52
return qemu_ram_addr_from_host_nofail(p);
64
+ if (!(op & 1)) {
65
+ if (u) {
66
+ fn = gen_helper_vfp_ultos;
67
+ } else {
68
+ fn = gen_helper_vfp_sltos;
69
+ }
70
+ } else {
71
+ if (u) {
72
+ fn = gen_helper_vfp_touls_round_to_zero;
73
+ } else {
74
+ fn = gen_helper_vfp_tosls_round_to_zero;
75
+ }
76
+ }
77
+
78
/* We have already masked out the must-be-1 top bit of imm6,
79
* hence this 32-shift where the ARM ARM has 64-imm6.
80
*/
81
shift = 32 - shift;
82
+ fpst = get_fpstatus_ptr(1);
83
+ shiftv = tcg_const_i32(shift);
84
for (pass = 0; pass < (q ? 4 : 2); pass++) {
85
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
86
- if (!(op & 1)) {
87
- if (u)
88
- gen_vfp_ulto(0, shift, 1);
89
- else
90
- gen_vfp_slto(0, shift, 1);
91
- } else {
92
- if (u)
93
- gen_vfp_toul(0, shift, 1);
94
- else
95
- gen_vfp_tosl(0, shift, 1);
96
- }
97
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
98
+ TCGv_i32 tmpf = neon_load_reg(rm, pass);
99
+ fn(tmpf, tmpf, shiftv, fpst);
100
+ neon_store_reg(rd, pass, tmpf);
101
}
102
+ tcg_temp_free_ptr(fpst);
103
+ tcg_temp_free_i32(shiftv);
104
} else {
105
return 1;
106
}
53
--
107
--
54
2.7.4
108
2.20.1
55
109
56
110
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Remove some old constructs from NEON_2RM_VCVT_F16_F32 code:
2
* don't use cpu_F0s
3
* don't use tcg_gen_ld_f32
2
4
3
In 2.9 ITS will block save/restore and migration use cases. As such,
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
let's introduce a user option that allows to turn its instantiation
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
off, along with GICv3. With the "its" option turned false, migration
7
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
will be possible, obviously at the expense of MSI support (with GICv3).
8
Message-id: 20190613163917.28589-11-peter.maydell@linaro.org
9
---
10
target/arm/translate.c | 27 ++++++++++++---------------
11
1 file changed, 12 insertions(+), 15 deletions(-)
7
12
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
9
Message-id: 1487681108-14452-1-git-send-email-eric.auger@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/arm/virt.h | 1 +
14
hw/arm/virt.c | 31 +++++++++++++++++++++++++++++--
15
2 files changed, 30 insertions(+), 2 deletions(-)
16
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
15
--- a/target/arm/translate.c
20
+++ b/include/hw/arm/virt.h
16
+++ b/target/arm/translate.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
22
FWCfgState *fw_cfg;
18
return ret;
23
bool secure;
24
bool highmem;
25
+ bool its;
26
bool virt;
27
int32_t gic_version;
28
struct arm_boot_info bootinfo;
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/virt.c
32
+++ b/hw/arm/virt.c
33
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
34
static void create_gic(VirtMachineState *vms, qemu_irq *pic)
35
{
36
/* We create a standalone GIC */
37
- VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
38
DeviceState *gicdev;
39
SysBusDevice *gicbusdev;
40
const char *gictype;
41
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
42
43
fdt_add_gic_node(vms);
44
45
- if (type == 3 && !vmc->no_its) {
46
+ if (type == 3 && vms->its) {
47
create_its(vms, gicdev);
48
} else if (type == 2) {
49
create_v2m(vms, pic);
50
@@ -XXX,XX +XXX,XX @@ static void virt_set_highmem(Object *obj, bool value, Error **errp)
51
vms->highmem = value;
52
}
19
}
53
20
54
+static bool virt_get_its(Object *obj, Error **errp)
21
-#define tcg_gen_ld_f32 tcg_gen_ld_i32
55
+{
22
#define tcg_gen_st_f32 tcg_gen_st_i32
56
+ VirtMachineState *vms = VIRT_MACHINE(obj);
23
57
+
24
#define ARM_CP_RW_BIT (1 << 20)
58
+ return vms->its;
25
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
59
+}
26
q || (rm & 1)) {
60
+
27
return 1;
61
+static void virt_set_its(Object *obj, bool value, Error **errp)
28
}
62
+{
29
- tmp = tcg_temp_new_i32();
63
+ VirtMachineState *vms = VIRT_MACHINE(obj);
30
- tmp2 = tcg_temp_new_i32();
64
+
31
fpst = get_fpstatus_ptr(true);
65
+ vms->its = value;
32
ahp = get_ahp_flag();
66
+}
33
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
67
+
34
- gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
68
static char *virt_get_gic_version(Object *obj, Error **errp)
35
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
69
{
36
- gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
70
VirtMachineState *vms = VIRT_MACHINE(obj);
37
+ tmp = neon_load_reg(rm, 0);
71
@@ -XXX,XX +XXX,XX @@ type_init(machvirt_machine_init);
38
+ gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
72
static void virt_2_9_instance_init(Object *obj)
39
+ tmp2 = neon_load_reg(rm, 1);
73
{
40
+ gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
74
VirtMachineState *vms = VIRT_MACHINE(obj);
41
tcg_gen_shli_i32(tmp2, tmp2, 16);
75
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
42
tcg_gen_or_i32(tmp2, tmp2, tmp);
76
43
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
77
/* EL3 is disabled by default on virt: this makes us consistent
44
- gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
78
* between KVM and TCG for this board, and it also allows us to
45
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
79
@@ -XXX,XX +XXX,XX @@ static void virt_2_9_instance_init(Object *obj)
46
+ tcg_temp_free_i32(tmp);
80
"Set GIC version. "
47
+ tmp = neon_load_reg(rm, 2);
81
"Valid values are 2, 3 and host", NULL);
48
+ gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
82
49
+ tmp3 = neon_load_reg(rm, 3);
83
+ if (vmc->no_its) {
50
neon_store_reg(rd, 0, tmp2);
84
+ vms->its = false;
51
- tmp2 = tcg_temp_new_i32();
85
+ } else {
52
- gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
86
+ /* Default allows ITS instantiation */
53
- tcg_gen_shli_i32(tmp2, tmp2, 16);
87
+ vms->its = true;
54
- tcg_gen_or_i32(tmp2, tmp2, tmp);
88
+ object_property_add_bool(obj, "its", virt_get_its,
55
- neon_store_reg(rd, 1, tmp2);
89
+ virt_set_its, NULL);
56
+ gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
90
+ object_property_set_description(obj, "its",
57
+ tcg_gen_shli_i32(tmp3, tmp3, 16);
91
+ "Set on/off to enable/disable "
58
+ tcg_gen_or_i32(tmp3, tmp3, tmp);
92
+ "ITS instantiation",
59
+ neon_store_reg(rd, 1, tmp3);
93
+ NULL);
60
tcg_temp_free_i32(tmp);
94
+ }
61
tcg_temp_free_i32(ahp);
95
+
62
tcg_temp_free_ptr(fpst);
96
vms->memmap = a15memmap;
97
vms->irqmap = a15irqmap;
98
}
99
--
63
--
100
2.7.4
64
2.20.1
101
65
102
66
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
Remove some old constructns from NEON_2RM_VCVT_F16_F32 code:
2
* don't use CPU_F0s
3
* don't use tcg_gen_st_f32
2
4
3
In SDHCI protocol, the 'Block count enable' bit of the Transfer
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Mode register is relevant only in multi block transfers. We need
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
not check it in single block transfers.
7
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190613163917.28589-12-peter.maydell@linaro.org
9
---
10
target/arm/translate.c | 26 +++++++++++---------------
11
1 file changed, 11 insertions(+), 15 deletions(-)
6
12
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
8
Message-id: 20170214185225.7994-5-ppandit@redhat.com
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/sd/sdhci.c | 6 +-----
13
1 file changed, 1 insertion(+), 5 deletions(-)
14
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
15
--- a/target/arm/translate.c
18
+++ b/hw/sd/sdhci.c
16
+++ b/target/arm/translate.c
19
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
17
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
18
return ret;
20
}
19
}
21
20
22
/* single block SDMA transfer */
21
-#define tcg_gen_st_f32 tcg_gen_st_i32
23
-
22
-
24
static void sdhci_sdma_transfer_single_block(SDHCIState *s)
23
#define ARM_CP_RW_BIT (1 << 20)
25
{
24
26
int n;
25
/* Include the VFP decoder */
27
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
26
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
28
sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
27
tmp = neon_load_reg(rm, 0);
29
}
28
tmp2 = neon_load_reg(rm, 1);
30
}
29
tcg_gen_ext16u_i32(tmp3, tmp);
31
-
30
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
32
- if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
31
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
33
- s->blkcnt--;
32
- tcg_gen_shri_i32(tmp3, tmp, 16);
34
- }
33
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
35
+ s->blkcnt--;
34
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
36
35
- tcg_temp_free_i32(tmp);
37
sdhci_end_transfer(s);
36
+ gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
38
}
37
+ neon_store_reg(rd, 0, tmp3);
38
+ tcg_gen_shri_i32(tmp, tmp, 16);
39
+ gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
40
+ neon_store_reg(rd, 1, tmp);
41
+ tmp3 = tcg_temp_new_i32();
42
tcg_gen_ext16u_i32(tmp3, tmp2);
43
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
44
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
45
- tcg_gen_shri_i32(tmp3, tmp2, 16);
46
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
47
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
48
- tcg_temp_free_i32(tmp2);
49
- tcg_temp_free_i32(tmp3);
50
+ gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
51
+ neon_store_reg(rd, 2, tmp3);
52
+ tcg_gen_shri_i32(tmp2, tmp2, 16);
53
+ gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
54
+ neon_store_reg(rd, 3, tmp2);
55
tcg_temp_free_i32(ahp);
56
tcg_temp_free_ptr(fpst);
57
break;
39
--
58
--
40
2.7.4
59
2.20.1
41
60
42
61
diff view generated by jsdifflib
Deleted patch
1
From: Igor Mammedov <imammedo@redhat.com>
2
1
3
object_new(FOO) returns an object with ref_cnt == 1
4
and following
5
object_property_set_bool(cpuobj, true, "realized", NULL)
6
set parent of cpuobj to '/machine/unattached' which makes
7
ref_cnt == 2.
8
9
Since machvirt_init() doesn't take ownership of cpuobj
10
returned by object_new() it should explicitly drop
11
reference to cpuobj when dangling pointer is about to
12
go out of scope like it's done pc_new_cpu() to avoid
13
object leak.
14
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
16
Message-id: 1487253461-269218-1-git-send-email-imammedo@redhat.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
hw/arm/virt.c | 1 +
21
1 file changed, 1 insertion(+)
22
23
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/virt.c
26
+++ b/hw/arm/virt.c
27
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
28
}
29
30
object_property_set_bool(cpuobj, true, "realized", NULL);
31
+ object_unref(cpuobj);
32
}
33
fdt_add_timer_nodes(vms);
34
fdt_add_cpu_nodes(vms);
35
--
36
2.7.4
37
38
diff view generated by jsdifflib
1
M profile doesn't implement ARM, and the architecturally required
1
Remove the now unused TCG globals cpu_F0s, cpu_F0d, cpu_F1s, cpu_F1d.
2
behaviour for attempts to execute with the Thumb bit clear is to
2
3
generate a UsageFault with the CFSR INVSTATE bit set. We were
3
cpu_M0 is still used by the iwmmxt code, and cpu_V0 and
4
incorrectly implementing this as generating an UNDEFINSTR UsageFault;
4
cpu_V1 are used by both iwmmxt and Neon.
5
fix this.
6
5
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20190613163917.28589-13-peter.maydell@linaro.org
9
---
10
---
10
target/arm/cpu.h | 1 +
11
target/arm/translate.c | 12 ++----------
11
linux-user/main.c | 1 +
12
1 file changed, 2 insertions(+), 10 deletions(-)
12
target/arm/helper.c | 4 ++++
13
target/arm/translate.c | 8 ++++++--
14
4 files changed, 12 insertions(+), 2 deletions(-)
15
13
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@
21
#define EXCP_VFIQ 15
22
#define EXCP_SEMIHOST 16 /* semihosting call */
23
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
24
+#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
25
26
#define ARMV7M_EXCP_RESET 1
27
#define ARMV7M_EXCP_NMI 2
28
diff --git a/linux-user/main.c b/linux-user/main.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/linux-user/main.c
31
+++ b/linux-user/main.c
32
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
33
switch(trapnr) {
34
case EXCP_UDEF:
35
case EXCP_NOCP:
36
+ case EXCP_INVSTATE:
37
{
38
TaskState *ts = cs->opaque;
39
uint32_t opcode;
40
diff --git a/target/arm/helper.c b/target/arm/helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/helper.c
43
+++ b/target/arm/helper.c
44
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
45
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
46
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
47
break;
48
+ case EXCP_INVSTATE:
49
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
50
+ env->v7m.cfsr |= R_V7M_CFSR_INVSTATE_MASK;
51
+ break;
52
case EXCP_SWI:
53
/* The PC already points to the next instruction. */
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
55
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
56
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate.c
16
--- a/target/arm/translate.c
58
+++ b/target/arm/translate.c
17
+++ b/target/arm/translate.c
59
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
18
@@ -XXX,XX +XXX,XX @@ TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
60
TCGv_i32 addr;
19
TCGv_i64 cpu_exclusive_addr;
61
TCGv_i64 tmp64;
20
TCGv_i64 cpu_exclusive_val;
62
21
63
- /* M variants do not implement ARM mode. */
22
-/* FIXME: These should be removed. */
64
+ /* M variants do not implement ARM mode; this must raise the INVSTATE
23
-static TCGv_i32 cpu_F0s, cpu_F1s;
65
+ * UsageFault exception.
24
-static TCGv_i64 cpu_F0d, cpu_F1d;
66
+ */
25
-
67
if (arm_dc_feature(s, ARM_FEATURE_M)) {
26
#include "exec/gen-icount.h"
68
- goto illegal_op;
27
69
+ gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
28
static const char * const regnames[] =
70
+ default_exception_el(s));
29
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
71
+ return;
30
dc->base.max_insns = MIN(dc->base.max_insns, bound);
72
}
31
}
73
cond = insn >> 28;
32
74
if (cond == 0xf){
33
- cpu_F0s = tcg_temp_new_i32();
34
- cpu_F1s = tcg_temp_new_i32();
35
- cpu_F0d = tcg_temp_new_i64();
36
- cpu_F1d = tcg_temp_new_i64();
37
- cpu_V0 = cpu_F0d;
38
- cpu_V1 = cpu_F1d;
39
+ cpu_V0 = tcg_temp_new_i64();
40
+ cpu_V1 = tcg_temp_new_i64();
41
/* FIXME: cpu_M0 can probably be the same as cpu_V0. */
42
cpu_M0 = tcg_temp_new_i64();
43
}
75
--
44
--
76
2.7.4
45
2.20.1
77
46
78
47
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
In several places cut and paste errors meant we were using the wrong
2
type for the 'arg' struct in trans_ functions called by the
3
decodetree decoder, because we were using the _sp version of the
4
struct in the _dp function. These were harmless, because the two
5
structs were identical and so decodetree made them typedefs of the
6
same underlying structure (and we'd have had a compile error if they
7
were not harmless), but we should clean them up anyway.
2
8
3
Despite some superficial similarities of register layout, the
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
M-profile NVIC is really very different from the A-profile GIC.
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Our current attempt to reuse the GIC code means that we have
11
Message-id: 20190614104457.24703-2-peter.maydell@linaro.org
6
significant bugs in our NVIC.
12
---
13
target/arm/translate-vfp.inc.c | 28 ++++++++++++++--------------
14
1 file changed, 14 insertions(+), 14 deletions(-)
7
15
8
Implement the NVIC as an entirely separate device, to give
16
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
9
us somewhere we can get the behaviour correct.
10
11
This initial commit does not attempt to implement exception
12
priority escalation, since the GIC-based code didn't either.
13
It does fix a few bugs in passing:
14
* ICSR.RETTOBASE polarity was wrong and didn't account for
15
internal exceptions
16
* ICSR.VECTPENDING was 16 too high if the pending exception
17
was for an external interrupt
18
* UsageFault, BusFault and MemFault were not disabled on reset
19
as they are supposed to be
20
21
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
22
[PMM: reworked, various bugs and stylistic cleanups]
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
25
---
26
hw/intc/armv7m_nvic.c | 738 ++++++++++++++++++++++++++++++++++++++++----------
27
hw/intc/trace-events | 15 +
28
2 files changed, 609 insertions(+), 144 deletions(-)
29
30
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
31
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/intc/armv7m_nvic.c
18
--- a/target/arm/translate-vfp.inc.c
33
+++ b/hw/intc/armv7m_nvic.c
19
+++ b/target/arm/translate-vfp.inc.c
34
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a)
35
#include "hw/sysbus.h"
21
return true;
36
#include "qemu/timer.h"
37
#include "hw/arm/arm.h"
38
+#include "target/arm/cpu.h"
39
#include "exec/address-spaces.h"
40
-#include "gic_internal.h"
41
#include "qemu/log.h"
42
+#include "trace.h"
43
+
44
+/* IRQ number counting:
45
+ *
46
+ * the num-irq property counts the number of external IRQ lines
47
+ *
48
+ * NVICState::num_irq counts the total number of exceptions
49
+ * (external IRQs, the 15 internal exceptions including reset,
50
+ * and one for the unused exception number 0).
51
+ *
52
+ * NVIC_MAX_IRQ is the highest permitted number of external IRQ lines.
53
+ *
54
+ * NVIC_MAX_VECTORS is the highest permitted number of exceptions.
55
+ *
56
+ * Iterating through all exceptions should typically be done with
57
+ * for (i = 1; i < s->num_irq; i++) to avoid the unused slot 0.
58
+ *
59
+ * The external qemu_irq lines are the NVIC's external IRQ lines,
60
+ * so line 0 is exception 16.
61
+ *
62
+ * In the terminology of the architecture manual, "interrupts" are
63
+ * a subcategory of exception referring to the external interrupts
64
+ * (which are exception numbers NVIC_FIRST_IRQ and upward).
65
+ * For historical reasons QEMU tends to use "interrupt" and
66
+ * "exception" more or less interchangeably.
67
+ */
68
+#define NVIC_FIRST_IRQ 16
69
+#define NVIC_MAX_VECTORS 512
70
+#define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ)
71
+
72
+/* Effective running priority of the CPU when no exception is active
73
+ * (higher than the highest possible priority value)
74
+ */
75
+#define NVIC_NOEXC_PRIO 0x100
76
+
77
+typedef struct VecInfo {
78
+ /* Exception priorities can range from -3 to 255; only the unmodifiable
79
+ * priority values for RESET, NMI and HardFault can be negative.
80
+ */
81
+ int16_t prio;
82
+ uint8_t enabled;
83
+ uint8_t pending;
84
+ uint8_t active;
85
+ uint8_t level; /* exceptions <=15 never set level */
86
+} VecInfo;
87
88
typedef struct NVICState {
89
- GICState gic;
90
+ /*< private >*/
91
+ SysBusDevice parent_obj;
92
+ /*< public >*/
93
+
94
ARMCPU *cpu;
95
96
+ VecInfo vectors[NVIC_MAX_VECTORS];
97
uint32_t prigroup;
98
99
+ /* vectpending and exception_prio are both cached state that can
100
+ * be recalculated from the vectors[] array and the prigroup field.
101
+ */
102
+ unsigned int vectpending; /* highest prio pending enabled exception */
103
+ int exception_prio; /* group prio of the highest prio active exception */
104
+
105
struct {
106
uint32_t control;
107
uint32_t reload;
108
int64_t tick;
109
QEMUTimer *timer;
110
} systick;
111
+
112
MemoryRegion sysregmem;
113
- MemoryRegion gic_iomem_alias;
114
MemoryRegion container;
115
+
116
uint32_t num_irq;
117
+ qemu_irq excpout;
118
qemu_irq sysresetreq;
119
} NVICState;
120
121
#define TYPE_NVIC "armv7m_nvic"
122
-/**
123
- * NVICClass:
124
- * @parent_reset: the parent class' reset handler.
125
- *
126
- * A model of the v7M NVIC and System Controller
127
- */
128
-typedef struct NVICClass {
129
- /*< private >*/
130
- ARMGICClass parent_class;
131
- /*< public >*/
132
- DeviceRealize parent_realize;
133
- void (*parent_reset)(DeviceState *dev);
134
-} NVICClass;
135
-
136
-#define NVIC_CLASS(klass) \
137
- OBJECT_CLASS_CHECK(NVICClass, (klass), TYPE_NVIC)
138
-#define NVIC_GET_CLASS(obj) \
139
- OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
140
+
141
#define NVIC(obj) \
142
OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
143
144
@@ -XXX,XX +XXX,XX @@ static void systick_reset(NVICState *s)
145
timer_del(s->systick.timer);
146
}
22
}
147
23
148
-/* The external routines use the hardware vector numbering, ie. the first
24
-static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_sp *a)
149
- IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
25
+static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
150
+static int nvic_pending_prio(NVICState *s)
151
+{
152
+ /* return the priority of the current pending interrupt,
153
+ * or NVIC_NOEXC_PRIO if no interrupt is pending
154
+ */
155
+ return s->vectpending ? s->vectors[s->vectpending].prio : NVIC_NOEXC_PRIO;
156
+}
157
+
158
+/* Return the value of the ISCR RETTOBASE bit:
159
+ * 1 if there is exactly one active exception
160
+ * 0 if there is more than one active exception
161
+ * UNKNOWN if there are no active exceptions (we choose 1,
162
+ * which matches the choice Cortex-M3 is documented as making).
163
+ *
164
+ * NB: some versions of the documentation talk about this
165
+ * counting "active exceptions other than the one shown by IPSR";
166
+ * this is only different in the obscure corner case where guest
167
+ * code has manually deactivated an exception and is about
168
+ * to fail an exception-return integrity check. The definition
169
+ * above is the one from the v8M ARM ARM and is also in line
170
+ * with the behaviour documented for the Cortex-M3.
171
+ */
172
+static bool nvic_rettobase(NVICState *s)
173
+{
174
+ int irq, nhand = 0;
175
+
176
+ for (irq = ARMV7M_EXCP_RESET; irq < s->num_irq; irq++) {
177
+ if (s->vectors[irq].active) {
178
+ nhand++;
179
+ if (nhand == 2) {
180
+ return 0;
181
+ }
182
+ }
183
+ }
184
+
185
+ return 1;
186
+}
187
+
188
+/* Return the value of the ISCR ISRPENDING bit:
189
+ * 1 if an external interrupt is pending
190
+ * 0 if no external interrupt is pending
191
+ */
192
+static bool nvic_isrpending(NVICState *s)
193
+{
194
+ int irq;
195
+
196
+ /* We can shortcut if the highest priority pending interrupt
197
+ * happens to be external or if there is nothing pending.
198
+ */
199
+ if (s->vectpending > NVIC_FIRST_IRQ) {
200
+ return true;
201
+ }
202
+ if (s->vectpending == 0) {
203
+ return false;
204
+ }
205
+
206
+ for (irq = NVIC_FIRST_IRQ; irq < s->num_irq; irq++) {
207
+ if (s->vectors[irq].pending) {
208
+ return true;
209
+ }
210
+ }
211
+ return false;
212
+}
213
+
214
+/* Return a mask word which clears the subpriority bits from
215
+ * a priority value for an M-profile exception, leaving only
216
+ * the group priority.
217
+ */
218
+static inline uint32_t nvic_gprio_mask(NVICState *s)
219
+{
220
+ return ~0U << (s->prigroup + 1);
221
+}
222
+
223
+/* Recompute vectpending and exception_prio */
224
+static void nvic_recompute_state(NVICState *s)
225
+{
226
+ int i;
227
+ int pend_prio = NVIC_NOEXC_PRIO;
228
+ int active_prio = NVIC_NOEXC_PRIO;
229
+ int pend_irq = 0;
230
+
231
+ for (i = 1; i < s->num_irq; i++) {
232
+ VecInfo *vec = &s->vectors[i];
233
+
234
+ if (vec->enabled && vec->pending && vec->prio < pend_prio) {
235
+ pend_prio = vec->prio;
236
+ pend_irq = i;
237
+ }
238
+ if (vec->active && vec->prio < active_prio) {
239
+ active_prio = vec->prio;
240
+ }
241
+ }
242
+
243
+ s->vectpending = pend_irq;
244
+ s->exception_prio = active_prio & nvic_gprio_mask(s);
245
+
246
+ trace_nvic_recompute_state(s->vectpending, s->exception_prio);
247
+}
248
+
249
+/* Return the current execution priority of the CPU
250
+ * (equivalent to the pseudocode ExecutionPriority function).
251
+ * This is a value between -2 (NMI priority) and NVIC_NOEXC_PRIO.
252
+ */
253
+static inline int nvic_exec_prio(NVICState *s)
254
+{
255
+ CPUARMState *env = &s->cpu->env;
256
+ int running;
257
+
258
+ if (env->daif & PSTATE_F) { /* FAULTMASK */
259
+ running = -1;
260
+ } else if (env->daif & PSTATE_I) { /* PRIMASK */
261
+ running = 0;
262
+ } else if (env->v7m.basepri > 0) {
263
+ running = env->v7m.basepri & nvic_gprio_mask(s);
264
+ } else {
265
+ running = NVIC_NOEXC_PRIO; /* lower than any possible priority */
266
+ }
267
+ /* consider priority of active handler */
268
+ return MIN(running, s->exception_prio);
269
+}
270
+
271
+/* caller must call nvic_irq_update() after this */
272
+static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
273
+{
274
+ assert(irq > ARMV7M_EXCP_NMI); /* only use for configurable prios */
275
+ assert(irq < s->num_irq);
276
+
277
+ s->vectors[irq].prio = prio;
278
+
279
+ trace_nvic_set_prio(irq, prio);
280
+}
281
+
282
+/* Recompute state and assert irq line accordingly.
283
+ * Must be called after changes to:
284
+ * vec->active, vec->enabled, vec->pending or vec->prio for any vector
285
+ * prigroup
286
+ */
287
+static void nvic_irq_update(NVICState *s)
288
+{
289
+ int lvl;
290
+ int pend_prio;
291
+
292
+ nvic_recompute_state(s);
293
+ pend_prio = nvic_pending_prio(s);
294
+
295
+ /* Raise NVIC output if this IRQ would be taken, except that we
296
+ * ignore the effects of the BASEPRI, FAULTMASK and PRIMASK (which
297
+ * will be checked for in arm_v7m_cpu_exec_interrupt()); changes
298
+ * to those CPU registers don't cause us to recalculate the NVIC
299
+ * pending info.
300
+ */
301
+ lvl = (pend_prio < s->exception_prio);
302
+ trace_nvic_irq_update(s->vectpending, pend_prio, s->exception_prio, lvl);
303
+ qemu_set_irq(s->excpout, lvl);
304
+}
305
+
306
+static void armv7m_nvic_clear_pending(void *opaque, int irq)
307
+{
308
+ NVICState *s = (NVICState *)opaque;
309
+ VecInfo *vec;
310
+
311
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
312
+
313
+ vec = &s->vectors[irq];
314
+ trace_nvic_clear_pending(irq, vec->enabled, vec->prio);
315
+ if (vec->pending) {
316
+ vec->pending = 0;
317
+ nvic_irq_update(s);
318
+ }
319
+}
320
+
321
void armv7m_nvic_set_pending(void *opaque, int irq)
322
{
26
{
323
NVICState *s = (NVICState *)opaque;
27
TCGv_i32 tmp;
324
- if (irq >= 16)
28
325
- irq += 16;
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
326
- gic_set_pending_private(&s->gic, 0, irq);
30
return true;
327
+ VecInfo *vec;
328
+
329
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
330
+
331
+ vec = &s->vectors[irq];
332
+ trace_nvic_set_pending(irq, vec->enabled, vec->prio);
333
+ if (!vec->pending) {
334
+ vec->pending = 1;
335
+ nvic_irq_update(s);
336
+ }
337
}
31
}
338
32
339
/* Make pending IRQ active. */
33
-static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_sp *a)
340
int armv7m_nvic_acknowledge_irq(void *opaque)
34
+static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
341
{
35
{
342
NVICState *s = (NVICState *)opaque;
36
uint32_t offset;
343
- uint32_t irq;
37
TCGv_i32 addr;
344
-
38
@@ -XXX,XX +XXX,XX @@ static void gen_VMLA_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
345
- irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
39
tcg_temp_free_i64(tmp);
346
- if (irq == 1023)
347
- hw_error("Interrupt but no vector\n");
348
- if (irq >= 32)
349
- irq -= 16;
350
- return irq;
351
+ CPUARMState *env = &s->cpu->env;
352
+ const int pending = s->vectpending;
353
+ const int running = nvic_exec_prio(s);
354
+ int pendgroupprio;
355
+ VecInfo *vec;
356
+
357
+ assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
358
+
359
+ vec = &s->vectors[pending];
360
+
361
+ assert(vec->enabled);
362
+ assert(vec->pending);
363
+
364
+ pendgroupprio = vec->prio & nvic_gprio_mask(s);
365
+ assert(pendgroupprio < running);
366
+
367
+ trace_nvic_acknowledge_irq(pending, vec->prio);
368
+
369
+ vec->active = 1;
370
+ vec->pending = 0;
371
+
372
+ env->v7m.exception = s->vectpending;
373
+
374
+ nvic_irq_update(s);
375
+
376
+ return env->v7m.exception;
377
}
40
}
378
41
379
void armv7m_nvic_complete_irq(void *opaque, int irq)
42
-static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_sp *a)
43
+static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_dp *a)
380
{
44
{
381
NVICState *s = (NVICState *)opaque;
45
return do_vfp_3op_dp(s, gen_VMLA_dp, a->vd, a->vn, a->vm, true);
382
- if (irq >= 16)
383
- irq += 16;
384
- gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
385
+ VecInfo *vec;
386
+
387
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
388
+
389
+ vec = &s->vectors[irq];
390
+
391
+ trace_nvic_complete_irq(irq);
392
+
393
+ vec->active = 0;
394
+ if (vec->level) {
395
+ /* Re-pend the exception if it's still held high; only
396
+ * happens for extenal IRQs
397
+ */
398
+ assert(irq >= NVIC_FIRST_IRQ);
399
+ vec->pending = 1;
400
+ }
401
+
402
+ nvic_irq_update(s);
403
+}
404
+
405
+/* callback when external interrupt line is changed */
406
+static void set_irq_level(void *opaque, int n, int level)
407
+{
408
+ NVICState *s = opaque;
409
+ VecInfo *vec;
410
+
411
+ n += NVIC_FIRST_IRQ;
412
+
413
+ assert(n >= NVIC_FIRST_IRQ && n < s->num_irq);
414
+
415
+ trace_nvic_set_irq_level(n, level);
416
+
417
+ /* The pending status of an external interrupt is
418
+ * latched on rising edge and exception handler return.
419
+ *
420
+ * Pulsing the IRQ will always run the handler
421
+ * once, and the handler will re-run until the
422
+ * level is low when the handler completes.
423
+ */
424
+ vec = &s->vectors[n];
425
+ if (level != vec->level) {
426
+ vec->level = level;
427
+ if (level) {
428
+ armv7m_nvic_set_pending(s, n);
429
+ }
430
+ }
431
}
46
}
432
47
@@ -XXX,XX +XXX,XX @@ static void gen_VMLS_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
433
static uint32_t nvic_readl(NVICState *s, uint32_t offset)
48
tcg_temp_free_i64(tmp);
49
}
50
51
-static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_sp *a)
52
+static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_dp *a)
434
{
53
{
435
ARMCPU *cpu = s->cpu;
54
return do_vfp_3op_dp(s, gen_VMLS_dp, a->vd, a->vn, a->vm, true);
436
uint32_t val;
55
}
437
- int irq;
56
@@ -XXX,XX +XXX,XX @@ static void gen_VNMLS_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
438
57
tcg_temp_free_i64(tmp);
439
switch (offset) {
58
}
440
case 4: /* Interrupt Control Type. */
59
441
- return (s->num_irq / 32) - 1;
60
-static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_sp *a)
442
+ return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
61
+static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_dp *a)
443
case 0x10: /* SysTick Control and Status. */
444
val = s->systick.control;
445
s->systick.control &= ~SYSTICK_COUNTFLAG;
446
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
447
case 0xd04: /* Interrupt Control State. */
448
/* VECTACTIVE */
449
val = cpu->env.v7m.exception;
450
- if (val == 1023) {
451
- val = 0;
452
- } else if (val >= 32) {
453
- val -= 16;
454
- }
455
/* VECTPENDING */
456
- if (s->gic.current_pending[0] != 1023)
457
- val |= (s->gic.current_pending[0] << 12);
458
- /* ISRPENDING and RETTOBASE */
459
- for (irq = 32; irq < s->num_irq; irq++) {
460
- if (s->gic.irq_state[irq].pending) {
461
- val |= (1 << 22);
462
- break;
463
- }
464
- if (irq != cpu->env.v7m.exception && s->gic.irq_state[irq].active) {
465
- val |= (1 << 11);
466
- }
467
+ val |= (s->vectpending & 0xff) << 12;
468
+ /* ISRPENDING - set if any external IRQ is pending */
469
+ if (nvic_isrpending(s)) {
470
+ val |= (1 << 22);
471
+ }
472
+ /* RETTOBASE - set if only one handler is active */
473
+ if (nvic_rettobase(s)) {
474
+ val |= (1 << 11);
475
}
476
/* PENDSTSET */
477
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
478
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].pending) {
479
val |= (1 << 26);
480
+ }
481
/* PENDSVSET */
482
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
483
+ if (s->vectors[ARMV7M_EXCP_PENDSV].pending) {
484
val |= (1 << 28);
485
+ }
486
/* NMIPENDSET */
487
- if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
488
+ if (s->vectors[ARMV7M_EXCP_NMI].pending) {
489
val |= (1 << 31);
490
+ }
491
+ /* ISRPREEMPT not implemented */
492
return val;
493
case 0xd08: /* Vector Table Offset. */
494
return cpu->env.v7m.vecbase;
495
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
496
return cpu->env.v7m.ccr;
497
case 0xd24: /* System Handler Status. */
498
val = 0;
499
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
500
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1);
501
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3);
502
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7);
503
- if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8);
504
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10);
505
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11);
506
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12);
507
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13);
508
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14);
509
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15);
510
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16);
511
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17);
512
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
513
+ if (s->vectors[ARMV7M_EXCP_MEM].active) {
514
+ val |= (1 << 0);
515
+ }
516
+ if (s->vectors[ARMV7M_EXCP_BUS].active) {
517
+ val |= (1 << 1);
518
+ }
519
+ if (s->vectors[ARMV7M_EXCP_USAGE].active) {
520
+ val |= (1 << 3);
521
+ }
522
+ if (s->vectors[ARMV7M_EXCP_SVC].active) {
523
+ val |= (1 << 7);
524
+ }
525
+ if (s->vectors[ARMV7M_EXCP_DEBUG].active) {
526
+ val |= (1 << 8);
527
+ }
528
+ if (s->vectors[ARMV7M_EXCP_PENDSV].active) {
529
+ val |= (1 << 10);
530
+ }
531
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].active) {
532
+ val |= (1 << 11);
533
+ }
534
+ if (s->vectors[ARMV7M_EXCP_USAGE].pending) {
535
+ val |= (1 << 12);
536
+ }
537
+ if (s->vectors[ARMV7M_EXCP_MEM].pending) {
538
+ val |= (1 << 13);
539
+ }
540
+ if (s->vectors[ARMV7M_EXCP_BUS].pending) {
541
+ val |= (1 << 14);
542
+ }
543
+ if (s->vectors[ARMV7M_EXCP_SVC].pending) {
544
+ val |= (1 << 15);
545
+ }
546
+ if (s->vectors[ARMV7M_EXCP_MEM].enabled) {
547
+ val |= (1 << 16);
548
+ }
549
+ if (s->vectors[ARMV7M_EXCP_BUS].enabled) {
550
+ val |= (1 << 17);
551
+ }
552
+ if (s->vectors[ARMV7M_EXCP_USAGE].enabled) {
553
+ val |= (1 << 18);
554
+ }
555
return val;
556
case 0xd28: /* Configurable Fault Status. */
557
return cpu->env.v7m.cfsr;
558
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
559
if (value & (1 << 28)) {
560
armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
561
} else if (value & (1 << 27)) {
562
- s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending = 0;
563
- gic_update(&s->gic);
564
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_PENDSV);
565
}
566
if (value & (1 << 26)) {
567
armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
568
} else if (value & (1 << 25)) {
569
- s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending = 0;
570
- gic_update(&s->gic);
571
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_SYSTICK);
572
}
573
break;
574
case 0xd08: /* Vector Table Offset. */
575
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
576
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
577
}
578
s->prigroup = extract32(value, 8, 3);
579
+ nvic_irq_update(s);
580
}
581
break;
582
case 0xd10: /* System Control. */
583
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
584
case 0xd24: /* System Handler Control. */
585
/* TODO: Real hardware allows you to set/clear the active bits
586
under some circumstances. We don't implement this. */
587
- s->gic.irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
588
- s->gic.irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
589
- s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
590
+ s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
591
+ s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
592
+ s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
593
+ nvic_irq_update(s);
594
break;
595
case 0xd28: /* Configurable Fault Status. */
596
cpu->env.v7m.cfsr &= ~value; /* W1C */
597
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
598
"NVIC: Aux fault status registers unimplemented\n");
599
break;
600
case 0xf00: /* Software Triggered Interrupt Register */
601
+ {
602
/* user mode can only write to STIR if CCR.USERSETMPEND permits it */
603
- if ((value & 0x1ff) < s->num_irq &&
604
+ int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
605
+ if (excnum < s->num_irq &&
606
(arm_current_el(&cpu->env) ||
607
(cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) {
608
- gic_set_pending_private(&s->gic, 0, value & 0x1ff);
609
+ armv7m_nvic_set_pending(s, excnum);
610
}
611
break;
612
+ }
613
default:
614
qemu_log_mask(LOG_GUEST_ERROR,
615
"NVIC: Bad write offset 0x%x\n", offset);
616
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
617
{
62
{
618
NVICState *s = (NVICState *)opaque;
63
return do_vfp_3op_dp(s, gen_VNMLS_dp, a->vd, a->vn, a->vm, true);
619
uint32_t offset = addr;
620
- int i;
621
+ unsigned i, startvec, end;
622
uint32_t val;
623
624
switch (offset) {
625
+ /* reads of set and clear both return the status */
626
+ case 0x100 ... 0x13f: /* NVIC Set enable */
627
+ offset += 0x80;
628
+ /* fall through */
629
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
630
+ val = 0;
631
+ startvec = offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */
632
+
633
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
634
+ if (s->vectors[startvec + i].enabled) {
635
+ val |= (1 << i);
636
+ }
637
+ }
638
+ break;
639
+ case 0x200 ... 0x23f: /* NVIC Set pend */
640
+ offset += 0x80;
641
+ /* fall through */
642
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
643
+ val = 0;
644
+ startvec = offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */
645
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
646
+ if (s->vectors[startvec + i].pending) {
647
+ val |= (1 << i);
648
+ }
649
+ }
650
+ break;
651
+ case 0x300 ... 0x33f: /* NVIC Active */
652
+ val = 0;
653
+ startvec = offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */
654
+
655
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
656
+ if (s->vectors[startvec + i].active) {
657
+ val |= (1 << i);
658
+ }
659
+ }
660
+ break;
661
+ case 0x400 ... 0x5ef: /* NVIC Priority */
662
+ val = 0;
663
+ startvec = offset - 0x400 + NVIC_FIRST_IRQ; /* vector # */
664
+
665
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
666
+ val |= s->vectors[startvec + i].prio << (8 * i);
667
+ }
668
+ break;
669
case 0xd18 ... 0xd23: /* System Handler Priority. */
670
val = 0;
671
for (i = 0; i < size; i++) {
672
- val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
673
+ val |= s->vectors[(offset - 0xd14) + i].prio << (i * 8);
674
}
675
- return val;
676
+ break;
677
case 0xfe0 ... 0xfff: /* ID. */
678
if (offset & 3) {
679
- return 0;
680
+ val = 0;
681
+ } else {
682
+ val = nvic_id[(offset - 0xfe0) >> 2];
683
+ }
684
+ break;
685
+ default:
686
+ if (size == 4) {
687
+ val = nvic_readl(s, offset);
688
+ } else {
689
+ qemu_log_mask(LOG_GUEST_ERROR,
690
+ "NVIC: Bad read of size %d at offset 0x%x\n",
691
+ size, offset);
692
+ val = 0;
693
}
694
- return nvic_id[(offset - 0xfe0) >> 2];
695
- }
696
- if (size == 4) {
697
- return nvic_readl(s, offset);
698
}
699
- qemu_log_mask(LOG_GUEST_ERROR,
700
- "NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
701
- return 0;
702
+
703
+ trace_nvic_sysreg_read(addr, val, size);
704
+ return val;
705
}
64
}
706
65
@@ -XXX,XX +XXX,XX @@ static void gen_VNMLA_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
707
static void nvic_sysreg_write(void *opaque, hwaddr addr,
66
tcg_temp_free_i64(tmp);
708
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
67
}
68
69
-static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_sp *a)
70
+static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_dp *a)
709
{
71
{
710
NVICState *s = (NVICState *)opaque;
72
return do_vfp_3op_dp(s, gen_VNMLA_dp, a->vd, a->vn, a->vm, true);
711
uint32_t offset = addr;
73
}
712
- int i;
74
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_sp(DisasContext *s, arg_VMUL_sp *a)
713
+ unsigned i, startvec, end;
75
return do_vfp_3op_sp(s, gen_helper_vfp_muls, a->vd, a->vn, a->vm, false);
714
+ unsigned setval = 0;
76
}
715
+
77
716
+ trace_nvic_sysreg_write(addr, value, size);
78
-static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_sp *a)
717
79
+static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_dp *a)
718
switch (offset) {
719
+ case 0x100 ... 0x13f: /* NVIC Set enable */
720
+ offset += 0x80;
721
+ setval = 1;
722
+ /* fall through */
723
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
724
+ startvec = 8 * (offset - 0x180) + NVIC_FIRST_IRQ;
725
+
726
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
727
+ if (value & (1 << i)) {
728
+ s->vectors[startvec + i].enabled = setval;
729
+ }
730
+ }
731
+ nvic_irq_update(s);
732
+ return;
733
+ case 0x200 ... 0x23f: /* NVIC Set pend */
734
+ /* the special logic in armv7m_nvic_set_pending()
735
+ * is not needed since IRQs are never escalated
736
+ */
737
+ offset += 0x80;
738
+ setval = 1;
739
+ /* fall through */
740
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
741
+ startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
742
+
743
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
744
+ if (value & (1 << i)) {
745
+ s->vectors[startvec + i].pending = setval;
746
+ }
747
+ }
748
+ nvic_irq_update(s);
749
+ return;
750
+ case 0x300 ... 0x33f: /* NVIC Active */
751
+ return; /* R/O */
752
+ case 0x400 ... 0x5ef: /* NVIC Priority */
753
+ startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
754
+
755
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
756
+ set_prio(s, startvec + i, (value >> (i * 8)) & 0xff);
757
+ }
758
+ nvic_irq_update(s);
759
+ return;
760
case 0xd18 ... 0xd23: /* System Handler Priority. */
761
for (i = 0; i < size; i++) {
762
- s->gic.priority1[(offset - 0xd14) + i][0] =
763
- (value >> (i * 8)) & 0xff;
764
+ unsigned hdlidx = (offset - 0xd14) + i;
765
+ set_prio(s, hdlidx, (value >> (i * 8)) & 0xff);
766
}
767
- gic_update(&s->gic);
768
+ nvic_irq_update(s);
769
return;
770
}
771
if (size == 4) {
772
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
773
.endianness = DEVICE_NATIVE_ENDIAN,
774
};
775
776
+static int nvic_post_load(void *opaque, int version_id)
777
+{
778
+ NVICState *s = opaque;
779
+ unsigned i;
780
+
781
+ /* Check for out of range priority settings */
782
+ if (s->vectors[ARMV7M_EXCP_RESET].prio != -3 ||
783
+ s->vectors[ARMV7M_EXCP_NMI].prio != -2 ||
784
+ s->vectors[ARMV7M_EXCP_HARD].prio != -1) {
785
+ return 1;
786
+ }
787
+ for (i = ARMV7M_EXCP_MEM; i < s->num_irq; i++) {
788
+ if (s->vectors[i].prio & ~0xff) {
789
+ return 1;
790
+ }
791
+ }
792
+
793
+ nvic_recompute_state(s);
794
+
795
+ return 0;
796
+}
797
+
798
+static const VMStateDescription vmstate_VecInfo = {
799
+ .name = "armv7m_nvic_info",
800
+ .version_id = 1,
801
+ .minimum_version_id = 1,
802
+ .fields = (VMStateField[]) {
803
+ VMSTATE_INT16(prio, VecInfo),
804
+ VMSTATE_UINT8(enabled, VecInfo),
805
+ VMSTATE_UINT8(pending, VecInfo),
806
+ VMSTATE_UINT8(active, VecInfo),
807
+ VMSTATE_UINT8(level, VecInfo),
808
+ VMSTATE_END_OF_LIST()
809
+ }
810
+};
811
+
812
static const VMStateDescription vmstate_nvic = {
813
.name = "armv7m_nvic",
814
- .version_id = 2,
815
- .minimum_version_id = 2,
816
+ .version_id = 3,
817
+ .minimum_version_id = 3,
818
+ .post_load = &nvic_post_load,
819
.fields = (VMStateField[]) {
820
+ VMSTATE_STRUCT_ARRAY(vectors, NVICState, NVIC_MAX_VECTORS, 1,
821
+ vmstate_VecInfo, VecInfo),
822
VMSTATE_UINT32(systick.control, NVICState),
823
VMSTATE_UINT32(systick.reload, NVICState),
824
VMSTATE_INT64(systick.tick, NVICState),
825
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
826
}
827
};
828
829
+static Property props_nvic[] = {
830
+ /* Number of external IRQ lines (so excluding the 16 internal exceptions) */
831
+ DEFINE_PROP_UINT32("num-irq", NVICState, num_irq, 64),
832
+ DEFINE_PROP_END_OF_LIST()
833
+};
834
+
835
static void armv7m_nvic_reset(DeviceState *dev)
836
{
80
{
837
NVICState *s = NVIC(dev);
81
return do_vfp_3op_dp(s, gen_helper_vfp_muld, a->vd, a->vn, a->vm, false);
838
- NVICClass *nc = NVIC_GET_CLASS(s);
839
- nc->parent_reset(dev);
840
- /* Common GIC reset resets to disabled; the NVIC doesn't have
841
- * per-CPU interfaces so mark our non-existent CPU interface
842
- * as enabled by default, and with a priority mask which allows
843
- * all interrupts through.
844
+
845
+ s->vectors[ARMV7M_EXCP_NMI].enabled = 1;
846
+ s->vectors[ARMV7M_EXCP_HARD].enabled = 1;
847
+ /* MEM, BUS, and USAGE are enabled through
848
+ * the System Handler Control register
849
*/
850
- s->gic.cpu_ctlr[0] = GICC_CTLR_EN_GRP0;
851
- s->gic.priority_mask[0] = 0x100;
852
- /* The NVIC as a whole is always enabled. */
853
- s->gic.ctlr = 1;
854
+ s->vectors[ARMV7M_EXCP_SVC].enabled = 1;
855
+ s->vectors[ARMV7M_EXCP_DEBUG].enabled = 1;
856
+ s->vectors[ARMV7M_EXCP_PENDSV].enabled = 1;
857
+ s->vectors[ARMV7M_EXCP_SYSTICK].enabled = 1;
858
+
859
+ s->vectors[ARMV7M_EXCP_RESET].prio = -3;
860
+ s->vectors[ARMV7M_EXCP_NMI].prio = -2;
861
+ s->vectors[ARMV7M_EXCP_HARD].prio = -1;
862
+
863
+ /* Strictly speaking the reset handler should be enabled.
864
+ * However, we don't simulate soft resets through the NVIC,
865
+ * and the reset vector should never be pended.
866
+ * So we leave it disabled to catch logic errors.
867
+ */
868
+
869
+ s->exception_prio = NVIC_NOEXC_PRIO;
870
+ s->vectpending = 0;
871
+
872
systick_reset(s);
873
}
82
}
874
83
@@ -XXX,XX +XXX,XX @@ static void gen_VNMUL_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
875
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
84
gen_helper_vfp_negd(vd, vd);
85
}
86
87
-static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_sp *a)
88
+static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_dp *a)
876
{
89
{
877
NVICState *s = NVIC(dev);
90
return do_vfp_3op_dp(s, gen_VNMUL_dp, a->vd, a->vn, a->vm, false);
878
- NVICClass *nc = NVIC_GET_CLASS(s);
879
- Error *local_err = NULL;
880
881
s->cpu = ARM_CPU(qemu_get_cpu(0));
882
assert(s->cpu);
883
- /* The NVIC always has only one CPU */
884
- s->gic.num_cpu = 1;
885
- /* Tell the common code we're an NVIC */
886
- s->gic.revision = 0xffffffff;
887
- s->num_irq = s->gic.num_irq;
888
- nc->parent_realize(dev, &local_err);
889
- if (local_err) {
890
- error_propagate(errp, local_err);
891
+
892
+ if (s->num_irq > NVIC_MAX_IRQ) {
893
+ error_setg(errp, "num-irq %d exceeds NVIC maximum", s->num_irq);
894
return;
895
}
896
- gic_init_irqs_and_distributor(&s->gic);
897
- /* The NVIC and system controller register area looks like this:
898
- * 0..0xff : system control registers, including systick
899
- * 0x100..0xcff : GIC-like registers
900
- * 0xd00..0xfff : system control registers
901
- * We use overlaying to put the GIC like registers
902
- * over the top of the system control register region.
903
+
904
+ qdev_init_gpio_in(dev, set_irq_level, s->num_irq);
905
+
906
+ /* include space for internal exception vectors */
907
+ s->num_irq += NVIC_FIRST_IRQ;
908
+
909
+ /* The NVIC and System Control Space (SCS) starts at 0xe000e000
910
+ * and looks like this:
911
+ * 0x004 - ICTR
912
+ * 0x010 - 0x1c - systick
913
+ * 0x100..0x7ec - NVIC
914
+ * 0x7f0..0xcff - Reserved
915
+ * 0xd00..0xd3c - SCS registers
916
+ * 0xd40..0xeff - Reserved or Not implemented
917
+ * 0xf00 - STIR
918
+ *
919
+ * At the moment there is only one thing in the container region,
920
+ * but we leave it in place to allow us to pull systick out into
921
+ * its own device object later.
922
*/
923
memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
924
/* The system register region goes at the bottom of the priority
925
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
926
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
927
"nvic_sysregs", 0x1000);
928
memory_region_add_subregion(&s->container, 0, &s->sysregmem);
929
- /* Alias the GIC region so we can get only the section of it
930
- * we need, and layer it on top of the system register region.
931
- */
932
- memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s),
933
- "nvic-gic", &s->gic.iomem,
934
- 0x100, 0xc00);
935
- memory_region_add_subregion_overlap(&s->container, 0x100,
936
- &s->gic_iomem_alias, 1);
937
+
938
/* Map the whole thing into system memory at the location required
939
* by the v7M architecture.
940
*/
941
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
942
* any user-specified property setting, so just modify the
943
* value in the GICState struct.
944
*/
945
- GICState *s = ARM_GIC_COMMON(obj);
946
DeviceState *dev = DEVICE(obj);
947
NVICState *nvic = NVIC(obj);
948
- /* The ARM v7m may have anything from 0 to 496 external interrupt
949
- * IRQ lines. We default to 64. Other boards may differ and should
950
- * set the num-irq property appropriately.
951
- */
952
- s->num_irq = 64;
953
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
954
+
955
+ sysbus_init_irq(sbd, &nvic->excpout);
956
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
957
}
91
}
958
92
@@ -XXX,XX +XXX,XX @@ static bool trans_VADD_sp(DisasContext *s, arg_VADD_sp *a)
959
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
93
return do_vfp_3op_sp(s, gen_helper_vfp_adds, a->vd, a->vn, a->vm, false);
94
}
95
96
-static bool trans_VADD_dp(DisasContext *s, arg_VADD_sp *a)
97
+static bool trans_VADD_dp(DisasContext *s, arg_VADD_dp *a)
960
{
98
{
961
- NVICClass *nc = NVIC_CLASS(klass);
99
return do_vfp_3op_dp(s, gen_helper_vfp_addd, a->vd, a->vn, a->vm, false);
962
DeviceClass *dc = DEVICE_CLASS(klass);
963
964
- nc->parent_reset = dc->reset;
965
- nc->parent_realize = dc->realize;
966
dc->vmsd = &vmstate_nvic;
967
+ dc->props = props_nvic;
968
dc->reset = armv7m_nvic_reset;
969
dc->realize = armv7m_nvic_realize;
970
}
100
}
971
101
@@ -XXX,XX +XXX,XX @@ static bool trans_VSUB_sp(DisasContext *s, arg_VSUB_sp *a)
972
static const TypeInfo armv7m_nvic_info = {
102
return do_vfp_3op_sp(s, gen_helper_vfp_subs, a->vd, a->vn, a->vm, false);
973
.name = TYPE_NVIC,
103
}
974
- .parent = TYPE_ARM_GIC_COMMON,
104
975
+ .parent = TYPE_SYS_BUS_DEVICE,
105
-static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_sp *a)
976
.instance_init = armv7m_nvic_instance_init,
106
+static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_dp *a)
977
.instance_size = sizeof(NVICState),
107
{
978
.class_init = armv7m_nvic_class_init,
108
return do_vfp_3op_dp(s, gen_helper_vfp_subd, a->vd, a->vn, a->vm, false);
979
- .class_size = sizeof(NVICClass),
109
}
980
+ .class_size = sizeof(SysBusDeviceClass),
110
@@ -XXX,XX +XXX,XX @@ static bool trans_VDIV_sp(DisasContext *s, arg_VDIV_sp *a)
981
};
111
return do_vfp_3op_sp(s, gen_helper_vfp_divs, a->vd, a->vn, a->vm, false);
982
112
}
983
static void armv7m_nvic_register_types(void)
113
984
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
114
-static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_sp *a)
985
index XXXXXXX..XXXXXXX 100644
115
+static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
986
--- a/hw/intc/trace-events
116
{
987
+++ b/hw/intc/trace-events
117
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
988
@@ -XXX,XX +XXX,XX @@ gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size,
118
}
989
gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
990
gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor %x interrupt %d level changed to %d"
120
return true;
991
gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor %x pending SGI %d"
121
}
992
+
122
993
+# hw/intc/armv7m_nvic.c
123
-static bool trans_VFM_dp(DisasContext *s, arg_VFM_sp *a)
994
+nvic_recompute_state(int vectpending, int exception_prio) "NVIC state recomputed: vectpending %d exception_prio %d"
124
+static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
995
+nvic_set_prio(int irq, uint8_t prio) "NVIC set irq %d priority %d"
125
{
996
+nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d"
126
/*
997
+nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
127
* VFNMA : fd = muladd(-fd, fn, fm)
998
+nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
128
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a)
999
+nvic_set_pending(int irq, int en, int prio) "NVIC set pending irq %d (enabled: %d priority %d)"
129
return true;
1000
+nvic_clear_pending(int irq, int en, int prio) "NVIC clear pending irq %d (enabled: %d priority %d)"
130
}
1001
+nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
131
1002
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
132
-static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_sp *a)
1003
+nvic_complete_irq(int irq) "NVIC complete IRQ %d"
133
+static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
1004
+nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
134
{
1005
+nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
135
TCGv_ptr fpst;
1006
+nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
136
TCGv_i64 tmp;
137
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a)
138
return true;
139
}
140
141
-static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_sp *a)
142
+static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
143
{
144
TCGv_ptr fpst;
145
TCGv_i64 tmp;
1007
--
146
--
1008
2.7.4
147
2.20.1
1009
148
1010
149
diff view generated by jsdifflib
1
Having armv7m_nvic_acknowledge_irq() return the new value of
1
The architecture permits FPUs which have only single-precision
2
env->v7m.exception and its one caller assign the return value
2
support, not double-precision; Cortex-M4 and Cortex-M33 are
3
back to env->v7m.exception is pointless. Just make the return
3
both like that. Add the necessary checks on the MVFR0 FPDP
4
type void instead.
4
field so that we UNDEF any double-precision instructions on
5
CPUs like this.
6
7
Note that even if FPDP==0 the insns like VMOV-to/from-gpreg,
8
VLDM/VSTM, VLDR/VSTR which take double precision registers
9
still exist.
5
10
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190614104457.24703-3-peter.maydell@linaro.org
8
---
14
---
9
target/arm/cpu.h | 2 +-
15
target/arm/cpu.h | 6 +++
10
hw/intc/armv7m_nvic.c | 4 +---
16
target/arm/translate-vfp.inc.c | 84 ++++++++++++++++++++++++++++++++++
11
target/arm/helper.c | 2 +-
17
2 files changed, 90 insertions(+)
12
3 files changed, 3 insertions(+), 5 deletions(-)
13
18
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
21
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
24
return FIELD_EX64(id->mvfr0, MVFR0, FPSHVEC) > 0;
19
}
25
}
20
#endif
26
21
void armv7m_nvic_set_pending(void *opaque, int irq);
27
+static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id)
22
-int armv7m_nvic_acknowledge_irq(void *opaque);
28
+{
23
+void armv7m_nvic_acknowledge_irq(void *opaque);
29
+ /* Return true if CPU supports double precision floating point */
24
void armv7m_nvic_complete_irq(void *opaque, int irq);
30
+ return FIELD_EX64(id->mvfr0, MVFR0, FPDP) > 0;
25
31
+}
26
/* Interface for defining coprocessor registers.
32
+
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
33
/*
34
* We always set the FP and SIMD FP16 fields to indicate identical
35
* levels of support (assuming SIMD is implemented at all), so
36
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
28
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
38
--- a/target/arm/translate-vfp.inc.c
30
+++ b/hw/intc/armv7m_nvic.c
39
+++ b/target/arm/translate-vfp.inc.c
31
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
40
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
32
}
41
((a->vm | a->vn | a->vd) & 0x10)) {
33
42
return false;
34
/* Make pending IRQ active. */
43
}
35
-int armv7m_nvic_acknowledge_irq(void *opaque)
44
+
36
+void armv7m_nvic_acknowledge_irq(void *opaque)
45
+ if (dp && !dc_isar_feature(aa32_fpdp, s)) {
37
{
46
+ return false;
38
NVICState *s = (NVICState *)opaque;
47
+ }
39
CPUARMState *env = &s->cpu->env;
48
+
40
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
49
rd = a->vd;
41
env->v7m.exception = s->vectpending;
50
rn = a->vn;
42
51
rm = a->vm;
43
nvic_irq_update(s);
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
44
-
53
((a->vm | a->vn | a->vd) & 0x10)) {
45
- return env->v7m.exception;
54
return false;
46
}
55
}
47
56
+
48
void armv7m_nvic_complete_irq(void *opaque, int irq)
57
+ if (dp && !dc_isar_feature(aa32_fpdp, s)) {
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
58
+ return false;
50
index XXXXXXX..XXXXXXX 100644
59
+ }
51
--- a/target/arm/helper.c
60
+
52
+++ b/target/arm/helper.c
61
rd = a->vd;
53
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
62
rn = a->vn;
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
63
rm = a->vm;
55
return;
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
56
case EXCP_IRQ:
65
((a->vm | a->vd) & 0x10)) {
57
- env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
66
return false;
58
+ armv7m_nvic_acknowledge_irq(env->nvic);
67
}
59
break;
68
+
60
case EXCP_EXCEPTION_EXIT:
69
+ if (dp && !dc_isar_feature(aa32_fpdp, s)) {
61
do_v7m_exception_exit(env);
70
+ return false;
71
+ }
72
+
73
rd = a->vd;
74
rm = a->vm;
75
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
77
if (dp && !dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
78
return false;
79
}
80
+
81
+ if (dp && !dc_isar_feature(aa32_fpdp, s)) {
82
+ return false;
83
+ }
84
+
85
rd = a->vd;
86
rm = a->vm;
87
88
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
89
return false;
90
}
91
92
+ if (!dc_isar_feature(aa32_fpdp, s)) {
93
+ return false;
94
+ }
95
+
96
if (!dc_isar_feature(aa32_fpshvec, s) &&
97
(veclen != 0 || s->vec_stride != 0)) {
98
return false;
99
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
100
return false;
101
}
102
103
+ if (!dc_isar_feature(aa32_fpdp, s)) {
104
+ return false;
105
+ }
106
+
107
if (!dc_isar_feature(aa32_fpshvec, s) &&
108
(veclen != 0 || s->vec_stride != 0)) {
109
return false;
110
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
111
return false;
112
}
113
114
+ if (!dc_isar_feature(aa32_fpdp, s)) {
115
+ return false;
116
+ }
117
+
118
if (!vfp_access_check(s)) {
119
return true;
120
}
121
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
122
return false;
123
}
124
125
+ if (!dc_isar_feature(aa32_fpdp, s)) {
126
+ return false;
127
+ }
128
+
129
if (!dc_isar_feature(aa32_fpshvec, s) &&
130
(veclen != 0 || s->vec_stride != 0)) {
131
return false;
132
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
133
return false;
134
}
135
136
+ if (!dc_isar_feature(aa32_fpdp, s)) {
137
+ return false;
138
+ }
139
+
140
if (!vfp_access_check(s)) {
141
return true;
142
}
143
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
144
return false;
145
}
146
147
+ if (!dc_isar_feature(aa32_fpdp, s)) {
148
+ return false;
149
+ }
150
+
151
if (!vfp_access_check(s)) {
152
return true;
153
}
154
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
155
return false;
156
}
157
158
+ if (!dc_isar_feature(aa32_fpdp, s)) {
159
+ return false;
160
+ }
161
+
162
if (!vfp_access_check(s)) {
163
return true;
164
}
165
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
166
return false;
167
}
168
169
+ if (!dc_isar_feature(aa32_fpdp, s)) {
170
+ return false;
171
+ }
172
+
173
if (!vfp_access_check(s)) {
174
return true;
175
}
176
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
177
return false;
178
}
179
180
+ if (!dc_isar_feature(aa32_fpdp, s)) {
181
+ return false;
182
+ }
183
+
184
if (!vfp_access_check(s)) {
185
return true;
186
}
187
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
188
return false;
189
}
190
191
+ if (!dc_isar_feature(aa32_fpdp, s)) {
192
+ return false;
193
+ }
194
+
195
if (!vfp_access_check(s)) {
196
return true;
197
}
198
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
199
return false;
200
}
201
202
+ if (!dc_isar_feature(aa32_fpdp, s)) {
203
+ return false;
204
+ }
205
+
206
if (!vfp_access_check(s)) {
207
return true;
208
}
209
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
210
return false;
211
}
212
213
+ if (!dc_isar_feature(aa32_fpdp, s)) {
214
+ return false;
215
+ }
216
+
217
if (!vfp_access_check(s)) {
218
return true;
219
}
220
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
221
return false;
222
}
223
224
+ if (!dc_isar_feature(aa32_fpdp, s)) {
225
+ return false;
226
+ }
227
+
228
if (!vfp_access_check(s)) {
229
return true;
230
}
231
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
232
return false;
233
}
234
235
+ if (!dc_isar_feature(aa32_fpdp, s)) {
236
+ return false;
237
+ }
238
+
239
if (!vfp_access_check(s)) {
240
return true;
241
}
242
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
243
return false;
244
}
245
246
+ if (!dc_isar_feature(aa32_fpdp, s)) {
247
+ return false;
248
+ }
249
+
250
if (!vfp_access_check(s)) {
251
return true;
252
}
253
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
254
return false;
255
}
256
257
+ if (!dc_isar_feature(aa32_fpdp, s)) {
258
+ return false;
259
+ }
260
+
261
if (!vfp_access_check(s)) {
262
return true;
263
}
62
--
264
--
63
2.7.4
265
2.20.1
64
266
65
267
diff view generated by jsdifflib
Deleted patch
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
2
1
3
The VECTCLRACTIVE and VECTRESET bits in the AIRCR are both
4
documented as UNPREDICTABLE if you write a 1 to them when
5
the processor is not halted in Debug state (ie stopped
6
and under the control of an external JTAG debugger).
7
Since we don't implement Debug state or emulated JTAG
8
these bits are always UNPREDICTABLE for us. Instead of
9
logging them as unimplemented we can simply log writes
10
as guest errors and ignore them.
11
12
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
13
[PMM: change extracted from another patch; commit message
14
constructed from scratch]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
---
19
hw/intc/armv7m_nvic.c | 8 ++++++--
20
1 file changed, 6 insertions(+), 2 deletions(-)
21
22
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/armv7m_nvic.c
25
+++ b/hw/intc/armv7m_nvic.c
26
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
27
qemu_irq_pulse(s->sysresetreq);
28
}
29
if (value & 2) {
30
- qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
31
+ qemu_log_mask(LOG_GUEST_ERROR,
32
+ "Setting VECTCLRACTIVE when not in DEBUG mode "
33
+ "is UNPREDICTABLE\n");
34
}
35
if (value & 1) {
36
- qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
37
+ qemu_log_mask(LOG_GUEST_ERROR,
38
+ "Setting VECTRESET when not in DEBUG mode "
39
+ "is UNPREDICTABLE\n");
40
}
41
s->prigroup = extract32(value, 8, 3);
42
nvic_irq_update(s);
43
--
44
2.7.4
45
46
diff view generated by jsdifflib