1
ARM queu; includes all the NVIC rewrite patches.
1
Some more outstanding target-arm patches; nothing terribly
2
The QOMify-armv7m patchset hasn't got enough review just
2
exciting. Mostly they're mine; I'm trying to reduce the
3
yet but I may be able to sneak it in before freeze
3
number of patches I still have in flight, so I've picked
4
tomorrow if it gets review. Didn't want to hold this lot
4
out some of the reviewed patches from a couple of sets I've
5
up waiting, anyway.
5
sent out and will resend v2 versions of those sets with the
6
remaining patches with fixes for issues noted in review once
7
this is in master.
6
8
7
thanks
9
thanks
8
-- PMM
10
-- PMM
9
11
10
12
11
The following changes since commit 8f2d7c341184a95d05476ea3c45dbae2b9ddbe51:
13
The following changes since commit adaec191bfb31e12d40af8ab1b869f5b40d61ee9:
12
14
13
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-02-27-1' into staging (2017-02-27 15:33:21 +0000)
15
Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging (2018-08-20 09:48:03 +0100)
14
16
15
are available in the git repository at:
17
are available in the Git repository at:
16
18
17
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170227
19
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180820
18
20
19
for you to fetch changes up to 94d5bcf5a7f3799660b62098a5183f161aad0601:
21
for you to fetch changes up to b85fad1588e812566f897f747e38da345a7016d6:
20
22
21
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID (2017-02-27 17:23:16 +0000)
23
hw/dma/pl080: Remove hw_error() if DMA is enabled (2018-08-20 11:24:33 +0100)
22
24
23
----------------------------------------------------------------
25
----------------------------------------------------------------
24
target-arm queue:
26
target-arm queue:
25
* raspi2: implement RNG module, GPIO and new SD card controller
27
* Fix crash on conditional instruction in an IT block
26
(sufficient to boot new raspbian kernels)
28
* docs/generic-loader: mention U-Boot and Intel HEX executable formats
27
* sdhci: bugfixes for block transfers
29
* hw/intc/arm_gicv3_its: downgrade error_report to warn_report in kvm_arm_its_reset
28
* virt: fix cpu object reference leak
30
* imx_serial: Generate interrupt on receive data ready if enabled
29
* Add missing fp_access_check() to aarch64 crypto instructions
31
* Fix various minor bugs in AArch32 Hyp related coprocessor registers
30
* cputlb: Don't assume do_unassigned_access() never returns
32
* Permit accesses to ELR_Hyp from Hyp mode via MSR/MRS (banked)
31
* virt: Add a user option to disallow ITS instantiation
33
* Implement AArch32 ERET instruction
32
* i.MX timers: fix reset handling
34
* hw/arm/virt: Add virt-3.1 machine type
33
* ARMv7M NVIC: rewrite to fix broken priority handling and masking
35
* sdhci: add i.MX SD Stable Clock bit
34
* exynos: Fix proper mapping of CPUs by providing real cluster ID
36
* Remove now-obsolete MMIO request_ptr APIs
35
* exynos: Fix Linux kernel division by zero for PLLs
37
* hw/timer/m48t59: Move away from old_mmio accessors
38
* hw/watchdog/cmsdk_apb_watchdog: Implement CMSDK APB watchdog module
39
* nvic: Expose NMI line
40
* hw/dma/pl080: cleanups and new features required for use in MPS boards
36
41
37
----------------------------------------------------------------
42
----------------------------------------------------------------
38
Clement Deschamps (4):
43
Andrew Jones (1):
39
bcm2835_sdhost: add bcm2835 sdhost controller
44
hw/arm/virt: Add virt-3.1 machine type
40
hw/sd: add card-reparenting function
41
bcm2835_gpio: add bcm2835 gpio controller
42
bcm2835: add sdhost and gpio controllers
43
45
44
Eric Auger (1):
46
Hans-Erik Floryd (2):
45
hw/arm/virt: Add a user option to disallow ITS instantiation
47
imx_serial: Generate interrupt on receive data ready if enabled
48
sdhci: add i.MX SD Stable Clock bit
46
49
47
Igor Mammedov (1):
50
Jia He (1):
48
hw/arm/virt: fix cpu object reference leak
51
hw/intc/arm_gicv3_its: downgrade error_report to warn_report in kvm_arm_its_reset
49
52
50
Krzysztof Kozlowski (2):
53
Peter Maydell (19):
51
hw/arm/exynos: Fix Linux kernel division by zero for PLLs
54
target/arm: Correct typo in HAMAIR1 regdef name
52
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID
55
target/arm: Add missing .cp = 15 to HMAIR1 and HAMAIR1 regdefs
56
target/arm: Implement AArch32 HVBAR
57
target/arm: Implement AArch32 Hyp FARs
58
target/arm: Implement ESR_EL2/HSR for AArch32 and no-EL2
59
target/arm: Permit accesses to ELR_Hyp from Hyp mode via MSR/MRS (banked)
60
target/arm: Implement AArch32 ERET instruction
61
hw/ssi/xilinx_spips: Remove unneeded MMIO request_ptr code
62
memory: Remove MMIO request_ptr APIs
63
hw/misc: Remove mmio_interface device
64
hw/timer/m48t59: Move away from old_mmio accessors
65
hw/watchdog/cmsdk_apb_watchdog: Implement CMSDK APB watchdog module
66
nvic: Expose NMI line
67
hw/dma/pl080: Allow use as embedded-struct device
68
hw/dma/pl080: Support all three interrupt lines
69
hw/dma/pl080: Don't use CPU address space for DMA accesses
70
hw/dma/pl080: Provide device reset function
71
hw/dma/pl080: Correct bug in register address decode logic
72
hw/dma/pl080: Remove hw_error() if DMA is enabled
53
73
54
Kurban Mallachiev (1):
74
Roman Kapl (1):
55
ARM i.MX timers: fix reset handling
75
target/arm: Fix crash on conditional instruction in an IT block
56
76
57
Marcin Chojnacki (1):
77
Stefan Hajnoczi (1):
58
target-arm: Implement BCM2835 hardware RNG
78
docs/generic-loader: mention U-Boot and Intel HEX executable formats
59
79
60
Michael Davidsaver (5):
80
docs/generic-loader.txt | 20 +-
61
armv7m: Rewrite NVIC to not use any GIC code
81
Makefile.objs | 1 +
62
arm: gic: Remove references to NVIC
82
hw/misc/Makefile.objs | 1 -
63
armv7m: Escalate exceptions to HardFault if necessary
83
hw/watchdog/Makefile.objs | 1 +
64
armv7m: Simpler and faster exception start
84
hw/sd/sdhci-internal.h | 2 +
65
armv7m: VECTCLRACTIVE and VECTRESET are UNPREDICTABLE
85
include/exec/memory.h | 35 ----
86
include/hw/char/imx_serial.h | 1 +
87
include/hw/dma/pl080.h | 71 +++++++
88
include/hw/misc/mmio_interface.h | 49 -----
89
include/hw/watchdog/cmsdk-apb-watchdog.h | 59 ++++++
90
hw/arm/armv7m.c | 1 +
91
hw/arm/realview.c | 8 +-
92
hw/arm/versatilepb.c | 9 +-
93
hw/arm/virt.c | 23 ++-
94
hw/char/imx_serial.c | 3 +-
95
hw/dma/pl080.c | 113 ++++++-----
96
hw/intc/arm_gicv3_its_kvm.c | 2 +-
97
hw/intc/armv7m_nvic.c | 19 ++
98
hw/misc/mmio_interface.c | 135 -------------
99
hw/sd/sdhci.c | 8 +
100
hw/ssi/xilinx_spips.c | 46 -----
101
hw/timer/m48t59.c | 59 ++----
102
hw/watchdog/cmsdk-apb-watchdog.c | 326 +++++++++++++++++++++++++++++++
103
memory.c | 110 -----------
104
target/arm/helper.c | 36 +++-
105
target/arm/op_helper.c | 22 +--
106
target/arm/translate.c | 76 +++++--
107
MAINTAINERS | 3 +
108
default-configs/arm-softmmu.mak | 1 +
109
hw/intc/trace-events | 1 +
110
hw/watchdog/trace-events | 6 +
111
31 files changed, 717 insertions(+), 530 deletions(-)
112
create mode 100644 include/hw/dma/pl080.h
113
delete mode 100644 include/hw/misc/mmio_interface.h
114
create mode 100644 include/hw/watchdog/cmsdk-apb-watchdog.h
115
delete mode 100644 hw/misc/mmio_interface.c
116
create mode 100644 hw/watchdog/cmsdk-apb-watchdog.c
117
create mode 100644 hw/watchdog/trace-events
66
118
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
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Roman Kapl <rka@sysgo.com>
2
2
3
This adds the BCM2835 GPIO controller.
3
If an instruction is conditional (like CBZ) and it is executed
4
conditionally (using the ITx instruction), a jump to an undefined
5
label is generated, and QEMU crashes.
4
6
5
It currently implements:
7
CBZ in IT block is an UNPREDICTABLE behavior, but we should not
6
- The 54 GPIOs as outputs (qemu_irq)
8
crash. Honouring the condition code is allowed by the spec in this
7
- The SD controller selection via alternate function of GPIOs 48-53
9
case (constrained unpredictable, ARMv8, section K1.1.7), and matches
10
what we do for other "UNPREDICTABLE inside an IT block" instructions.
8
11
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
12
Fix the 'skip on condition' code to create a new label only if it
10
Message-id: 20170224164021.9066-4-clement.deschamps@antfield.fr
13
does not already exist. Previously multiple labels were created, but
14
only the last one of them was set.
15
16
Signed-off-by: Roman Kapl <rka@sysgo.com>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20180816120533.6587-1-rka@sysgo.com
19
[PMM: fixed ^ 1 being applied to wrong argument, fixed typo]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
22
---
14
hw/gpio/Makefile.objs | 1 +
23
target/arm/translate.c | 35 +++++++++++++++++++++--------------
15
include/hw/gpio/bcm2835_gpio.h | 39 +++++
24
1 file changed, 21 insertions(+), 14 deletions(-)
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
25
21
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
26
diff --git a/target/arm/translate.c b/target/arm/translate.c
22
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/gpio/Makefile.objs
28
--- a/target/arm/translate.c
24
+++ b/hw/gpio/Makefile.objs
29
+++ b/target/arm/translate.c
25
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
30
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
26
31
s->base.is_jmp = DISAS_UPDATE;
27
obj-$(CONFIG_OMAP) += omap_gpio.o
32
}
28
obj-$(CONFIG_IMX) += imx_gpio.o
33
29
+obj-$(CONFIG_RASPI) += bcm2835_gpio.o
34
+/* Generate a label used for skipping this instruction */
30
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
35
+static void arm_gen_condlabel(DisasContext *s)
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/gpio/bcm2835_gpio.h
35
@@ -XXX,XX +XXX,XX @@
36
+/*
37
+ * Raspberry Pi (BCM2835) GPIO Controller
38
+ *
39
+ * Copyright (c) 2017 Antfield SAS
40
+ *
41
+ * Authors:
42
+ * Clement Deschamps <clement.deschamps@antfield.fr>
43
+ * Luc Michel <luc.michel@antfield.fr>
44
+ *
45
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
46
+ * See the COPYING file in the top-level directory.
47
+ */
48
+
49
+#ifndef BCM2835_GPIO_H
50
+#define BCM2835_GPIO_H
51
+
52
+#include "hw/sd/sd.h"
53
+
54
+typedef struct BCM2835GpioState {
55
+ SysBusDevice parent_obj;
56
+
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
+{
36
+{
134
+ int i;
37
+ if (!s->condjmp) {
135
+ uint32_t value = 0;
38
+ s->condlabel = gen_new_label();
136
+ for (i = 0; i < 10; i++) {
39
+ s->condjmp = 1;
137
+ uint32_t index = 10 * reg + i;
138
+ if (index < sizeof(s->fsel)) {
139
+ value |= (s->fsel[index] & 0x7) << (3 * i);
140
+ }
141
+ }
142
+ return value;
143
+}
144
+
145
+static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value)
146
+{
147
+ int i;
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
+ }
154
+ }
155
+
156
+ /* SD controller selection (48-53) */
157
+ if (s->sd_fsel != 0
158
+ && (s->fsel[48] == 0) /* SD_CLK_R */
159
+ && (s->fsel[49] == 0) /* SD_CMD_R */
160
+ && (s->fsel[50] == 0) /* SD_DATA0_R */
161
+ && (s->fsel[51] == 0) /* SD_DATA1_R */
162
+ && (s->fsel[52] == 0) /* SD_DATA2_R */
163
+ && (s->fsel[53] == 0) /* SD_DATA3_R */
164
+ ) {
165
+ /* SDHCI controller selected */
166
+ sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
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
+ }
40
+ }
180
+}
41
+}
181
+
42
+
182
+static int gpfsel_is_out(BCM2835GpioState *s, int index)
43
+/* Skip this instruction if the ARM condition is false */
44
+static void arm_skip_unless(DisasContext *s, uint32_t cond)
183
+{
45
+{
184
+ if (index >= 0 && index < 54) {
46
+ arm_gen_condlabel(s);
185
+ return s->fsel[index] == 1;
47
+ arm_gen_test_cc(cond ^ 1, s->condlabel);
186
+ }
187
+ return 0;
188
+}
48
+}
189
+
49
+
190
+static void gpset(BCM2835GpioState *s,
50
static void disas_arm_insn(DisasContext *s, unsigned int insn)
191
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
51
{
192
+{
52
unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
193
+ uint32_t changes = val & ~*lev;
53
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
194
+ uint32_t cur = 1;
54
if (cond != 0xe) {
195
+
55
/* if not always execute, we generate a conditional jump to
196
+ int i;
56
next instruction */
197
+ for (i = 0; i < count; i++) {
57
- s->condlabel = gen_new_label();
198
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
58
- arm_gen_test_cc(cond ^ 1, s->condlabel);
199
+ qemu_set_irq(s->out[start + i], 1);
59
- s->condjmp = 1;
200
+ }
60
+ arm_skip_unless(s, cond);
201
+ cur <<= 1;
61
}
202
+ }
62
if ((insn & 0x0f900000) == 0x03000000) {
203
+
63
if ((insn & (1 << 21)) == 0) {
204
+ *lev |= val;
64
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
205
+}
65
/* Conditional branch. */
206
+
66
op = (insn >> 22) & 0xf;
207
+static void gpclr(BCM2835GpioState *s,
67
/* Generate a conditional jump to next instruction. */
208
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
68
- s->condlabel = gen_new_label();
209
+{
69
- arm_gen_test_cc(op ^ 1, s->condlabel);
210
+ uint32_t changes = val & *lev;
70
- s->condjmp = 1;
211
+ uint32_t cur = 1;
71
+ arm_skip_unless(s, op);
212
+
72
213
+ int i;
73
/* offset[11:1] = insn[10:0] */
214
+ for (i = 0; i < count; i++) {
74
offset = (insn & 0x7ff) << 1;
215
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
75
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
216
+ qemu_set_irq(s->out[start + i], 0);
76
case 1: case 3: case 9: case 11: /* czb */
217
+ }
77
rm = insn & 7;
218
+ cur <<= 1;
78
tmp = load_reg(s, rm);
219
+ }
79
- s->condlabel = gen_new_label();
220
+
80
- s->condjmp = 1;
221
+ *lev &= ~val;
81
+ arm_gen_condlabel(s);
222
+}
82
if (insn & (1 << 11))
223
+
83
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
224
+static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset,
84
else
225
+ unsigned size)
85
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
226
+{
86
break;
227
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
87
}
228
+
88
/* generate a conditional jump to next instruction */
229
+ switch (offset) {
89
- s->condlabel = gen_new_label();
230
+ case GPFSEL0:
90
- arm_gen_test_cc(cond ^ 1, s->condlabel);
231
+ case GPFSEL1:
91
- s->condjmp = 1;
232
+ case GPFSEL2:
92
+ arm_skip_unless(s, cond);
233
+ case GPFSEL3:
93
234
+ case GPFSEL4:
94
/* jump to the offset */
235
+ case GPFSEL5:
95
val = (uint32_t)s->pc + 2;
236
+ return gpfsel_get(s, offset / 4);
96
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
237
+ case GPSET0:
97
uint32_t cond = dc->condexec_cond;
238
+ case GPSET1:
98
239
+ /* Write Only */
99
if (cond != 0x0e) { /* Skip conditional when condition is AL. */
240
+ return 0;
100
- dc->condlabel = gen_new_label();
241
+ case GPCLR0:
101
- arm_gen_test_cc(cond ^ 1, dc->condlabel);
242
+ case GPCLR1:
102
- dc->condjmp = 1;
243
+ /* Write Only */
103
+ arm_skip_unless(dc, cond);
244
+ return 0;
104
}
245
+ case GPLEV0:
105
}
246
+ return s->lev0;
106
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
--
107
--
435
2.7.4
108
2.18.0
436
109
437
110
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
The Exynos4210 has cluster ID 0x9 in its MPIDR register (raw value
3
The generic loader device supports the U-Boot and Intel HEX executable
4
0x8000090x). If this cluster ID is not provided, then Linux kernel
4
formats in addition to the document raw and ELF formats. Reword the
5
cannot map DeviceTree nodes to MPIDR values resulting in kernel
5
documentation to include these formats and explain how various options
6
warning and lack of any secondary CPUs:
6
depend on the executable format.
7
7
8
DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
...
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
smp: Bringing up secondary CPUs ...
10
Message-id: 20180816145554.9814-1-stefanha@redhat.com
11
smp: Brought up 1 node, 1 CPU
12
SMP: Total of 1 processors activated (24.00 BogoMIPS).
13
14
Provide a cluster ID so Linux will see proper MPIDR and will try to
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>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
13
---
22
hw/arm/exynos4210.c | 12 ++++++++++++
14
docs/generic-loader.txt | 20 ++++++++++----------
23
1 file changed, 12 insertions(+)
15
1 file changed, 10 insertions(+), 10 deletions(-)
24
16
25
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
17
diff --git a/docs/generic-loader.txt b/docs/generic-loader.txt
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/exynos4210.c
19
--- a/docs/generic-loader.txt
28
+++ b/hw/arm/exynos4210.c
20
+++ b/docs/generic-loader.txt
29
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
21
@@ -XXX,XX +XXX,XX @@ An example of setting CPU 0's PC to 0x8000 is:
30
info->smp_loader_start);
22
31
}
23
Loading Files
32
24
-------------
33
+static uint64_t exynos4210_calc_affinity(int cpu)
25
-The loader device also allows files to be loaded into memory. It can load raw
34
+{
26
-files and ELF executable files. Raw files are loaded verbatim. ELF executable
35
+ uint64_t mp_affinity;
27
-files are loaded by an ELF loader. The syntax is shown below:
36
+
28
+The loader device also allows files to be loaded into memory. It can load ELF,
37
+ /* Exynos4210 has 0x9 as cluster ID */
29
+U-Boot, and Intel HEX executable formats as well as raw images. The syntax is
38
+ mp_affinity = (0x9 << ARM_AFF1_SHIFT) | cpu;
30
+shown below:
39
+
31
40
+ return mp_affinity;
32
-device loader,file=<file>[,addr=<addr>][,cpu-num=<cpu-num>][,force-raw=<raw>]
41
+}
33
42
+
34
<file> - A file to be loaded into memory
43
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
35
- <addr> - The addr in memory that the file should be loaded. This is
44
unsigned long ram_size)
36
- ignored if you are using an ELF (unless force-raw is true).
45
{
37
- This is required if you aren't loading an ELF.
46
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
38
+ <addr> - The memory address where the file should be loaded. This is
47
}
39
+ required for raw images and ignored for non-raw files.
48
40
<cpu-num> - This specifies the CPU that should be used. This is an
49
s->cpu[n] = ARM_CPU(cpuobj);
41
optional argument and will cause the CPU's PC to be set to
50
+ object_property_set_int(cpuobj, exynos4210_calc_affinity(n),
42
- where the image is stored or in the case of an ELF file to
51
+ "mp-affinity", &error_abort);
43
- the value in the header. This option should only be used
52
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
44
- for the boot image.
53
"reset-cbar", &error_abort);
45
+ the memory address where the raw file is loaded or the entry
54
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
46
+ point specified in the executable format header. This option
47
+ should only be used for the boot image.
48
This will also cause the image to be written to the specified
49
CPU's address space. If not specified, the default is CPU 0.
50
<force-raw> - Setting force-raw=on forces the file to be treated as a raw
51
- image. This can be used to load ELF files as if they were raw.
52
+ image. This can be used to load supported executable formats
53
+ as if they were raw.
54
55
All values are parsed using the standard QemuOps parsing. This allows the user
56
to specify any values in any format supported. By default the values
55
--
57
--
56
2.7.4
58
2.18.0
57
59
58
60
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Jia He <hejianet@gmail.com>
2
2
3
This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform.
3
In scripts/arch-run.bash of kvm-unit-tests, it will check the qemu
4
output log with:
5
if [ -z "$(echo "$errors" | grep -vi warning)" ]; then
4
6
5
For supporting the SD controller selection (alternate function of GPIOs
7
Thus without the warning prefix, all of the test fail.
6
48-53), the bcm2835_gpio now exposes an sdbus.
7
It also has a link to both the sdbus of sdhci and sdhost controllers,
8
and the card is reparented from one bus to another when the alternate
9
function of GPIOs 48-53 is modified.
10
8
11
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
9
Since it is not unrecoverable error in kvm_arm_its_reset for
12
Message-id: 20170224164021.9066-5-clement.deschamps@antfield.fr
10
current implementation, downgrading the report from error to
11
warn makes sense.
12
13
Signed-off-by: Jia He <jia.he@hxt-semitech.com>
14
Message-id: 1531969910-32843-1-git-send-email-jia.he@hxt-semitech.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
17
---
16
include/hw/arm/bcm2835_peripherals.h | 4 ++++
18
hw/intc/arm_gicv3_its_kvm.c | 2 +-
17
hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++++--
19
1 file changed, 1 insertion(+), 1 deletion(-)
18
2 files changed, 45 insertions(+), 2 deletions(-)
19
20
20
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
21
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
21
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2835_peripherals.h
23
--- a/hw/intc/arm_gicv3_its_kvm.c
23
+++ b/include/hw/arm/bcm2835_peripherals.h
24
+++ b/hw/intc/arm_gicv3_its_kvm.c
24
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_reset(DeviceState *dev)
25
#include "hw/misc/bcm2835_rng.h"
26
#include "hw/misc/bcm2835_mbox.h"
27
#include "hw/sd/sdhci.h"
28
+#include "hw/sd/bcm2835_sdhost.h"
29
+#include "hw/gpio/bcm2835_gpio.h"
30
31
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
32
#define BCM2835_PERIPHERALS(obj) \
33
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
34
BCM2835RngState rng;
35
BCM2835MboxState mboxes;
36
SDHCIState sdhci;
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
+
55
/* DMA Channels */
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
+
63
+ /* GPIO */
64
+ object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO);
65
+ object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL);
66
+ qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default());
67
+
68
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
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;
26
return;
87
}
27
}
88
28
89
+ memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET,
29
- error_report("ITS KVM: full reset is not supported by the host kernel");
90
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0));
30
+ warn_report("ITS KVM: full reset is not supported by the host kernel");
91
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0,
31
92
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
32
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
93
+ INTERRUPT_SDIO));
33
GITS_CTLR)) {
94
+
95
/* DMA Channels */
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
+ }
109
+
110
+ memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
111
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
112
+
113
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus",
114
+ &err);
115
+ if (err) {
116
+ error_propagate(errp, err);
117
+ return;
118
+ }
119
}
120
121
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
122
--
34
--
123
2.7.4
35
2.18.0
124
36
125
37
diff view generated by jsdifflib
1
From: Nick Reilly <nreilly@blackberry.com>
1
From: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
2
2
3
The aarch64 crypto instructions for AES and SHA are missing the
3
Generate an interrupt if USR2_RDR and UCR4_DREN are both set.
4
check for if the FPU is enabled.
5
4
6
Signed-off-by: Nick Reilly <nreilly@blackberry.com>
5
Signed-off-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
6
Message-id: 1534341354-11956-1-git-send-email-hans-erik.floryd@rt-labs.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/translate-a64.c | 12 ++++++++++++
10
include/hw/char/imx_serial.h | 1 +
11
1 file changed, 12 insertions(+)
11
hw/char/imx_serial.c | 3 ++-
12
2 files changed, 3 insertions(+), 1 deletion(-)
12
13
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
16
--- a/include/hw/char/imx_serial.h
16
+++ b/target/arm/translate-a64.c
17
+++ b/include/hw/char/imx_serial.h
17
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@
18
return;
19
#define UCR2_RXEN (1<<1) /* Receiver enable */
19
}
20
#define UCR2_SRST (1<<0) /* Reset complete */
20
21
21
+ if (!fp_access_check(s)) {
22
+#define UCR4_DREN BIT(0) /* Receive Data Ready interrupt enable */
22
+ return;
23
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
23
+ }
24
24
+
25
#define UTS1_TXEMPTY (1<<6)
25
/* Note that we convert the Vx register indexes into the
26
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
26
* index within the vfp.regs[] array, so we can share the
27
index XXXXXXX..XXXXXXX 100644
27
* helper with the AArch32 instructions.
28
--- a/hw/char/imx_serial.c
28
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
29
+++ b/hw/char/imx_serial.c
29
return;
30
@@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s)
30
}
31
mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
31
32
/*
32
+ if (!fp_access_check(s)) {
33
* TCEN and TXDC are both bit 3
33
+ return;
34
+ * RDR and DREN are both bit 0
34
+ }
35
*/
35
+
36
- mask |= s->ucr4 & UCR4_TCEN;
36
tcg_rd_regno = tcg_const_i32(rd << 1);
37
+ mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
37
tcg_rn_regno = tcg_const_i32(rn << 1);
38
38
tcg_rm_regno = tcg_const_i32(rm << 1);
39
usr2 = s->usr2 & mask;
39
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
40
return;
41
}
42
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
40
50
--
41
--
51
2.7.4
42
2.18.0
52
43
53
44
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
We implement the HAMAIR1 register as RAZ/WI; we had a typo in the
2
regdef, though, and were incorrectly naming it HMAIR1 (which is
3
a different register which we also implement as RAZ/WI).
2
4
3
The v7M exception architecture requires that if a synchronous
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
exception cannot be taken immediately (because it is disabled
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
or at too low a priority) then it should be escalated to
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
HardFault (and the HardFault exception is then taken).
8
Message-id: 20180814124254.5229-2-peter.maydell@linaro.org
7
Implement this escalation logic.
9
---
10
target/arm/helper.c | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
8
12
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>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
---
14
hw/intc/armv7m_nvic.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
15
target/arm/helper.c | 2 --
16
2 files changed, 53 insertions(+), 2 deletions(-)
17
18
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/armv7m_nvic.c
21
+++ b/hw/intc/armv7m_nvic.c
22
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
23
24
vec = &s->vectors[irq];
25
trace_nvic_set_pending(irq, vec->enabled, vec->prio);
26
+
27
+
28
+ if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
29
+ /* If a synchronous exception is pending then it may be
30
+ * escalated to HardFault if:
31
+ * * it is equal or lower priority to current execution
32
+ * * it is disabled
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
+
52
+ if (vec->prio >= running) {
53
+ trace_nvic_escalate_prio(irq, vec->prio, running);
54
+ escalate = true;
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
+ }
71
+
72
+ /* We can do the escalation, so we take HardFault instead */
73
+ irq = ARMV7M_EXCP_HARD;
74
+ vec = &s->vectors[irq];
75
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
76
+ }
77
+ }
78
+
79
if (!vec->pending) {
80
vec->pending = 1;
81
nvic_irq_update(s);
82
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
83
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/helper.c
15
--- a/target/arm/helper.c
85
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.c
86
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
17
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
87
18
.opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0,
88
/* For exceptions we just mark as pending on the NVIC, and let that
19
.access = PL2_RW, .type = ARM_CP_CONST,
89
handle it. */
20
.resetvalue = 0 },
90
- /* TODO: Need to escalate if the current priority is higher than the
21
- { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
91
- one we're raising. */
22
+ { .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
92
switch (cs->exception_index) {
23
.opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
93
case EXCP_UDEF:
24
.access = PL2_RW, .type = ARM_CP_CONST,
94
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
25
.resetvalue = 0 },
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
27
.access = PL2_RW, .type = ARM_CP_CONST,
28
.resetvalue = 0 },
29
/* HAMAIR1 is mapped to AMAIR_EL2[63:32] */
30
- { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
31
+ { .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
32
.opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
33
.access = PL2_RW, .type = ARM_CP_CONST,
34
.resetvalue = 0 },
95
--
35
--
96
2.7.4
36
2.18.0
97
37
98
38
diff view generated by jsdifflib
1
Implement the exception return consistency checks
1
ARMCPRegInfo structs will default to .cp = 15 if they
2
described in the v7M pseudocode ExceptionReturn().
2
are ARM_CP_STATE_BOTH, but not if they are ARM_CP_STATE_AA32
3
3
(because a coprocessor number of 0 is valid for AArch32).
4
Inspired by a patch from Michael Davidsaver's series, but
4
We forgot to explicitly set .cp = 15 for the HMAIR1 and
5
this is a reimplementation from scratch based on the
5
HAMAIR1 regdefs, which meant they would UNDEF when the guest
6
ARM ARM pseudocode.
6
tried to access them under cp15.
7
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
11
Message-id: 20180814124254.5229-3-peter.maydell@linaro.org
10
---
12
---
11
target/arm/cpu.h | 12 +++++-
13
target/arm/helper.c | 8 ++++----
12
hw/intc/armv7m_nvic.c | 12 +++++-
14
1 file changed, 4 insertions(+), 4 deletions(-)
13
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++++++-----
14
3 files changed, 123 insertions(+), 13 deletions(-)
15
15
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 @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
21
#endif
22
void armv7m_nvic_set_pending(void *opaque, int irq);
23
void armv7m_nvic_acknowledge_irq(void *opaque);
24
-void armv7m_nvic_complete_irq(void *opaque, int irq);
25
+/**
26
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
27
+ * @opaque: the NVIC
28
+ * @irq: the exception number to complete
29
+ *
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
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque)
44
nvic_irq_update(s);
45
}
46
47
-void armv7m_nvic_complete_irq(void *opaque, int irq)
48
+int armv7m_nvic_complete_irq(void *opaque, int irq)
49
{
50
NVICState *s = (NVICState *)opaque;
51
VecInfo *vec;
52
+ int ret;
53
54
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
55
56
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
57
58
trace_nvic_complete_irq(irq);
59
60
+ if (!vec->active) {
61
+ /* Tell the caller this was an illegal exception return */
62
+ return -1;
63
+ }
64
+
65
+ ret = nvic_rettobase(s);
66
+
67
vec->active = 0;
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
+
75
+ return ret;
76
}
77
78
/* callback when external interrupt line is changed */
79
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
80
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/helper.c
18
--- a/target/arm/helper.c
82
+++ b/target/arm/helper.c
19
+++ b/target/arm/helper.c
83
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
20
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
84
v7m_push(env, env->regs[0]);
21
.access = PL2_RW, .type = ARM_CP_CONST,
85
}
22
.resetvalue = 0 },
86
23
{ .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
87
-static void do_v7m_exception_exit(CPUARMState *env)
24
- .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
88
+static void do_v7m_exception_exit(ARMCPU *cpu)
25
+ .cp = 15, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
89
{
26
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
90
+ CPUARMState *env = &cpu->env;
27
{ .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH,
91
uint32_t type;
28
.opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0,
92
uint32_t xpsr;
29
.access = PL2_RW, .type = ARM_CP_CONST,
93
-
30
.resetvalue = 0 },
94
+ bool ufault = false;
31
{ .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
95
+ bool return_to_sp_process = false;
32
- .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
96
+ bool return_to_handler = false;
33
+ .cp = 15, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
97
+ bool rettobase = false;
34
.access = PL2_RW, .type = ARM_CP_CONST,
98
+
35
.resetvalue = 0 },
99
+ /* We can only get here from an EXCP_EXCEPTION_EXIT, and
36
{ .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH,
100
+ * arm_v7m_do_unassigned_access() enforces the architectural rule
37
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
101
+ * that jumps to magic addresses don't have magic behaviour unless
38
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[2]),
102
+ * we're in Handler mode (compare pseudocode BXWritePC()).
39
.resetvalue = 0 },
103
+ */
40
{ .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
104
+ assert(env->v7m.exception != 0);
41
- .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
105
+
42
+ .cp = 15, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
106
+ /* In the spec pseudocode ExceptionReturn() is called directly
43
.access = PL2_RW, .type = ARM_CP_ALIAS,
107
+ * from BXWritePC() and gets the full target PC value including
44
.fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el[2]) },
108
+ * bit zero. In QEMU's implementation we treat it as a normal
45
{ .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH,
109
+ * jump-to-register (which is then caught later on), and so split
46
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
110
+ * the target value up between env->regs[15] and env->thumb in
47
.resetvalue = 0 },
111
+ * gen_bx(). Reconstitute it.
48
/* HAMAIR1 is mapped to AMAIR_EL2[63:32] */
112
+ */
49
{ .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
113
type = env->regs[15];
50
- .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
114
+ if (env->thumb) {
51
+ .cp = 15, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
115
+ type |= 1;
52
.access = PL2_RW, .type = ARM_CP_CONST,
116
+ }
53
.resetvalue = 0 },
117
+
54
{ .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH,
118
+ qemu_log_mask(CPU_LOG_INT, "Exception return: magic PC %" PRIx32
119
+ " previous exception %d\n",
120
+ type, env->v7m.exception);
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
--
55
--
228
2.7.4
56
2.18.0
229
57
230
58
diff view generated by jsdifflib
1
Extract the code from the tail end of arm_v7m_do_interrupt() which
1
Implement the AArch32 HVBAR register; we can do this just by
2
enters the exception handler into a pair of utility functions
2
making the existing VBAR_EL2 regdefs be STATE_BOTH.
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
3
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Message-id: 20180814124254.5229-5-peter.maydell@linaro.org
16
---
8
---
17
target/arm/helper.c | 118 ++++++++++++++++++++++++++++++----------------------
9
target/arm/helper.c | 4 ++--
18
1 file changed, 68 insertions(+), 50 deletions(-)
10
1 file changed, 2 insertions(+), 2 deletions(-)
19
11
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
14
--- a/target/arm/helper.c
23
+++ b/target/arm/helper.c
15
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
16
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
25
}
17
26
}
18
/* Used to describe the behaviour of EL2 regs when EL2 does not exist. */
27
19
static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
28
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
20
- { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64,
29
+{
21
+ { .name = "VBAR_EL2", .state = ARM_CP_STATE_BOTH,
30
+ CPUState *cs = CPU(cpu);
22
.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
31
+ CPUARMState *env = &cpu->env;
23
.access = PL2_RW,
32
+ MemTxResult result;
24
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
33
+ hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
25
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
34
+ uint32_t addr;
26
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0,
35
+
27
.access = PL2_RW,
36
+ addr = address_space_ldl(cs->as, vec,
28
.fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) },
37
+ MEMTXATTRS_UNSPECIFIED, &result);
29
- { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64,
38
+ if (result != MEMTX_OK) {
30
+ { .name = "VBAR_EL2", .state = ARM_CP_STATE_BOTH,
39
+ /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
31
.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
40
+ * which would then be immediately followed by our failing to load
32
.access = PL2_RW, .writefn = vbar_write,
41
+ * the entry vector for that HardFault, which is a Lockup case.
33
.fieldoffset = offsetof(CPUARMState, cp15.vbar_el[2]),
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
-{
104
- CPUState *cs = CPU(cpu);
105
- CPUARMState *env = &cpu->env;
106
- MemTxResult result;
107
- hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
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
-}
124
-
125
void arm_v7m_cpu_do_interrupt(CPUState *cs)
126
{
127
ARMCPU *cpu = ARM_CPU(cs);
128
CPUARMState *env = &cpu->env;
129
- uint32_t xpsr = xpsr_read(env);
130
uint32_t lr;
131
- uint32_t addr;
132
133
arm_log_exception(cs->exception_index);
134
135
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
136
return; /* Never happens. Keep compiler happy. */
137
}
138
139
- armv7m_nvic_acknowledge_irq(env->nvic);
140
-
141
+ v7m_push_stack(cpu);
142
+ v7m_exception_taken(cpu, lr);
143
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
144
-
145
- /* Align stack pointer if the guest wants that */
146
- if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
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
--
34
--
170
2.7.4
35
2.18.0
171
36
172
37
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
The AArch32 virtualization extensions support these fault address
2
registers:
3
* HDFAR: aliased with AArch64 FAR_EL2[31:0] and AArch32 DFAR(S)
4
* HIFAR: aliased with AArch64 FAR_EL2[63:32] and AArch32 IFAR(S)
2
5
3
All the places in armv7m_cpu_do_interrupt() which pend an
6
Implement the accessors for these. This fixes in passing a bug
4
exception in the NVIC are doing so for synchronous
7
where we weren't implementing the "RES0 from EL3 if EL2 not
5
exceptions. We know that we will always take some
8
implemented" behaviour for AArch64 FAR_EL2.
6
exception in this case, so we can just acknowledge it
7
immediately, rather than returning and then immediately
8
being called again because the NVIC has raised its outbound
9
IRQ line.
10
9
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
13
Message-id: 20180814124254.5229-7-peter.maydell@linaro.org
17
---
14
---
18
target/arm/helper.c | 15 +++++++++------
15
target/arm/helper.c | 14 +++++++++++++-
19
1 file changed, 9 insertions(+), 6 deletions(-)
16
1 file changed, 13 insertions(+), 1 deletion(-)
20
17
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
20
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
21
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
22
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
26
case EXCP_UDEF:
23
{ .name = "HSTR_EL2", .state = ARM_CP_STATE_BOTH,
27
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
24
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
28
env->v7m.cfsr |= R_V7M_CFSR_UNDEFINSTR_MASK;
25
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
29
- return;
26
+ { .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
30
+ break;
27
+ .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0,
31
case EXCP_NOCP:
28
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
32
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
29
+ { .name = "HIFAR", .state = ARM_CP_STATE_AA32,
33
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
30
+ .type = ARM_CP_CONST,
34
- return;
31
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
35
+ break;
32
+ .access = PL2_RW, .resetvalue = 0 },
36
case EXCP_SWI:
33
REGINFO_SENTINEL
37
/* The PC already points to the next instruction. */
34
};
38
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
35
39
- return;
36
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
40
+ break;
37
{ .name = "ESR_EL2", .state = ARM_CP_STATE_AA64,
41
case EXCP_PREFETCH_ABORT:
38
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
42
case EXCP_DATA_ABORT:
39
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) },
43
/* TODO: if we implemented the MPU registers, this is where we
40
- { .name = "FAR_EL2", .state = ARM_CP_STATE_AA64,
44
* should set the MMFAR, etc from exception.fsr and exception.vaddress.
41
+ { .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
45
*/
42
.opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0,
46
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
43
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[2]) },
47
- return;
44
+ { .name = "HIFAR", .state = ARM_CP_STATE_AA32,
48
+ break;
45
+ .type = ARM_CP_ALIAS,
49
case EXCP_BKPT:
46
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
50
if (semihosting_enabled()) {
47
+ .access = PL2_RW,
51
int nr;
48
+ .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[2]) },
52
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
49
{ .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64,
53
}
50
.type = ARM_CP_ALIAS,
54
}
51
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0,
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
}
66
67
+ armv7m_nvic_acknowledge_irq(env->nvic);
68
+
69
+ qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
70
+
71
/* Align stack pointer if the guest wants that */
72
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
73
env->regs[13] -= 4;
74
--
52
--
75
2.7.4
53
2.18.0
76
54
77
55
diff view generated by jsdifflib
1
Having armv7m_nvic_acknowledge_irq() return the new value of
1
The AArch32 HSR is the equivalent of AArch64 ESR_EL2;
2
env->v7m.exception and its one caller assign the return value
2
we can implement it by marking our existing ESR_EL2 regdef
3
back to env->v7m.exception is pointless. Just make the return
3
as STATE_BOTH. It also needs to be "RES0 from EL3 if
4
type void instead.
4
EL2 not implemented", so add the missing stanza to
5
el3_no_el2_cp_reginfo.
5
6
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
10
Message-id: 20180814124254.5229-8-peter.maydell@linaro.org
8
---
11
---
9
target/arm/cpu.h | 2 +-
12
target/arm/helper.c | 6 +++++-
10
hw/intc/armv7m_nvic.c | 4 +---
13
1 file changed, 5 insertions(+), 1 deletion(-)
11
target/arm/helper.c | 2 +-
12
3 files changed, 3 insertions(+), 5 deletions(-)
13
14
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
19
}
20
#endif
21
void armv7m_nvic_set_pending(void *opaque, int irq);
22
-int armv7m_nvic_acknowledge_irq(void *opaque);
23
+void armv7m_nvic_acknowledge_irq(void *opaque);
24
void armv7m_nvic_complete_irq(void *opaque, int irq);
25
26
/* Interface for defining coprocessor registers.
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
30
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
32
}
33
34
/* Make pending IRQ active. */
35
-int armv7m_nvic_acknowledge_irq(void *opaque)
36
+void armv7m_nvic_acknowledge_irq(void *opaque)
37
{
38
NVICState *s = (NVICState *)opaque;
39
CPUARMState *env = &s->cpu->env;
40
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
41
env->v7m.exception = s->vectpending;
42
43
nvic_irq_update(s);
44
-
45
- return env->v7m.exception;
46
}
47
48
void armv7m_nvic_complete_irq(void *opaque, int irq)
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
52
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
19
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
20
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
55
return;
21
.access = PL2_RW,
56
case EXCP_IRQ:
22
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
57
- env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
23
+ { .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
58
+ armv7m_nvic_acknowledge_irq(env->nvic);
24
+ .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
59
break;
25
+ .access = PL2_RW,
60
case EXCP_EXCEPTION_EXIT:
26
+ .type = ARM_CP_CONST, .resetvalue = 0 },
61
do_v7m_exception_exit(env);
27
{ .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH,
28
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2,
29
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
30
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
31
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
32
.access = PL2_RW,
33
.fieldoffset = offsetof(CPUARMState, elr_el[2]) },
34
- { .name = "ESR_EL2", .state = ARM_CP_STATE_AA64,
35
+ { .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
36
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
37
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) },
38
{ .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
62
--
39
--
63
2.7.4
40
2.18.0
64
41
65
42
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
The MSR (banked) and MRS (banked) instructions allow accesses to ELR_Hyp
2
from either Monitor or Hyp mode. Our translate time check
3
was overly strict and only permitted access from Monitor mode.
2
4
3
In the SDHCI protocol, the transfer mode register value
5
The runtime check we do in msr_mrs_banked_exc_checks() had the
4
is used during multi block transfer to check if block count
6
correct code in it, but never got there because of the earlier
5
register is enabled and should be updated. Transfer mode
7
"currmode == tgtmode" check. Special case ELR_Hyp.
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
8
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>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
Message-id: 20180814124254.5229-9-peter.maydell@linaro.org
16
---
13
---
17
hw/sd/sdhci.c | 10 +++++-----
14
target/arm/op_helper.c | 22 +++++++++++-----------
18
1 file changed, 5 insertions(+), 5 deletions(-)
15
target/arm/translate.c | 10 +++++++---
16
2 files changed, 18 insertions(+), 14 deletions(-)
19
17
20
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
18
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
21
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/sd/sdhci.c
20
--- a/target/arm/op_helper.c
23
+++ b/hw/sd/sdhci.c
21
+++ b/target/arm/op_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
22
@@ -XXX,XX +XXX,XX @@ static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
25
uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12);
23
*/
26
uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk);
24
int curmode = env->uncached_cpsr & CPSR_M;
27
25
28
+ if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) {
26
+ if (regno == 17) {
29
+ qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n");
27
+ /* ELR_Hyp: a special case because access from tgtmode is OK */
28
+ if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
29
+ goto undef;
30
+ }
30
+ return;
31
+ return;
31
+ }
32
+ }
32
+
33
+
33
/* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for
34
if (curmode == tgtmode) {
34
* possible stop at page boundary if initial address is not page aligned,
35
goto undef;
35
* allow them to work properly */
36
}
36
@@ -XXX,XX +XXX,XX @@ static void sdhci_data_transfer(void *opaque)
37
@@ -XXX,XX +XXX,XX @@ static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
37
if (s->trnmod & SDHC_TRNS_DMA) {
38
}
38
switch (SDHC_DMA_TYPE(s->hostctl)) {
39
39
case SDHC_CTRL_SDMA:
40
if (tgtmode == ARM_CPU_MODE_HYP) {
40
- if ((s->trnmod & SDHC_TRNS_MULTI) &&
41
- switch (regno) {
41
- (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) {
42
- case 17: /* ELR_Hyp */
42
- break;
43
- if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
44
- goto undef;
43
- }
45
- }
44
-
46
- break;
45
if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
47
- default:
46
sdhci_sdma_transfer_single_block(s);
48
- if (curmode != ARM_CPU_MODE_MON) {
47
} else {
49
- goto undef;
50
- }
51
- break;
52
+ /* SPSR_Hyp, r13_hyp: accessible from Monitor mode only */
53
+ if (curmode != ARM_CPU_MODE_MON) {
54
+ goto undef;
55
}
56
}
57
58
diff --git a/target/arm/translate.c b/target/arm/translate.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate.c
61
+++ b/target/arm/translate.c
62
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
63
}
64
break;
65
case ARM_CPU_MODE_HYP:
66
- /* Note that we can forbid accesses from EL2 here because they
67
- * must be from Hyp mode itself
68
+ /*
69
+ * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
70
+ * (and so we can forbid accesses from EL2 or below). elr_hyp
71
+ * can be accessed also from Hyp mode, so forbid accesses from
72
+ * EL0 or EL1.
73
*/
74
- if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 3) {
75
+ if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
76
+ (s->current_el < 3 && *regno != 17)) {
77
goto undef;
78
}
79
break;
48
--
80
--
49
2.7.4
81
2.18.0
50
82
51
83
diff view generated by jsdifflib
1
M profile doesn't implement ARM, and the architecturally required
1
ARMv7VE introduced the ERET instruction, which is necessary to
2
behaviour for attempts to execute with the Thumb bit clear is to
2
return from an exception taken to Hyp mode. Implement this.
3
generate a UsageFault with the CFSR INVSTATE bit set. We were
3
In A32 encoding it is a completely new encoding; in T32 it
4
incorrectly implementing this as generating an UNDEFINSTR UsageFault;
4
is an adjustment of the behaviour of the existing
5
fix this.
5
"SUBS PC, LR, #<imm8>" instruction.
6
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
10
Message-id: 20180814124254.5229-10-peter.maydell@linaro.org
9
---
11
---
10
target/arm/cpu.h | 1 +
12
target/arm/translate.c | 31 +++++++++++++++++++++++++++++--
11
linux-user/main.c | 1 +
13
1 file changed, 29 insertions(+), 2 deletions(-)
12
target/arm/helper.c | 4 ++++
13
target/arm/translate.c | 8 ++++++--
14
4 files changed, 12 insertions(+), 2 deletions(-)
15
14
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
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
56
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate.c
17
--- a/target/arm/translate.c
58
+++ b/target/arm/translate.c
18
+++ b/target/arm/translate.c
59
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
19
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
60
TCGv_i32 addr;
20
tcg_temp_free_i32(tmp2);
61
TCGv_i64 tmp64;
21
store_reg(s, rd, tmp);
62
22
break;
63
- /* M variants do not implement ARM mode. */
23
+ case 0x6: /* ERET */
64
+ /* M variants do not implement ARM mode; this must raise the INVSTATE
24
+ if (op1 != 3) {
65
+ * UsageFault exception.
25
+ goto illegal_op;
66
+ */
26
+ }
67
if (arm_dc_feature(s, ARM_FEATURE_M)) {
27
+ if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
68
- goto illegal_op;
28
+ goto illegal_op;
69
+ gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
29
+ }
70
+ default_exception_el(s));
30
+ if ((insn & 0x000fff0f) != 0x0000000e) {
71
+ return;
31
+ /* UNPREDICTABLE; we choose to UNDEF */
72
}
32
+ goto illegal_op;
73
cond = insn >> 28;
33
+ }
74
if (cond == 0xf){
34
+
35
+ if (s->current_el == 2) {
36
+ tmp = load_cpu_field(elr_el[2]);
37
+ } else {
38
+ tmp = load_reg(s, 14);
39
+ }
40
+ gen_exception_return(s, tmp);
41
+ break;
42
case 7:
43
{
44
int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
45
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
46
if (rn != 14 || rd != 15) {
47
goto illegal_op;
48
}
49
- tmp = load_reg(s, rn);
50
- tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
51
+ if (s->current_el == 2) {
52
+ /* ERET from Hyp uses ELR_Hyp, not LR */
53
+ if (insn & 0xff) {
54
+ goto illegal_op;
55
+ }
56
+ tmp = load_cpu_field(elr_el[2]);
57
+ } else {
58
+ tmp = load_reg(s, rn);
59
+ tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
60
+ }
61
gen_exception_return(s, tmp);
62
break;
63
case 6: /* MRS */
75
--
64
--
76
2.7.4
65
2.18.0
77
66
78
67
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Andrew Jones <drjones@redhat.com>
2
2
3
In 2.9 ITS will block save/restore and migration use cases. As such,
3
Signed-off-by: Andrew Jones <drjones@redhat.com>
4
let's introduce a user option that allows to turn its instantiation
4
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
5
off, along with GICv3. With the "its" option turned false, migration
6
will be possible, obviously at the expense of MSI support (with GICv3).
7
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 1487681108-14452-1-git-send-email-eric.auger@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
7
---
13
include/hw/arm/virt.h | 1 +
8
hw/arm/virt.c | 23 +++++++++++++++++------
14
hw/arm/virt.c | 31 +++++++++++++++++++++++++++++--
9
1 file changed, 17 insertions(+), 6 deletions(-)
15
2 files changed, 30 insertions(+), 2 deletions(-)
16
10
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
20
+++ b/include/hw/arm/virt.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
FWCfgState *fw_cfg;
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
11
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
30
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/virt.c
13
--- a/hw/arm/virt.c
32
+++ b/hw/arm/virt.c
14
+++ b/hw/arm/virt.c
33
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
15
@@ -XXX,XX +XXX,XX @@ static void machvirt_machine_init(void)
34
static void create_gic(VirtMachineState *vms, qemu_irq *pic)
16
}
17
type_init(machvirt_machine_init);
18
19
-#define VIRT_COMPAT_2_12 \
20
- HW_COMPAT_2_12
21
-
22
-static void virt_3_0_instance_init(Object *obj)
23
+static void virt_3_1_instance_init(Object *obj)
35
{
24
{
36
/* We create a standalone GIC */
25
VirtMachineState *vms = VIRT_MACHINE(obj);
37
- VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
26
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
38
DeviceState *gicdev;
27
@@ -XXX,XX +XXX,XX @@ static void virt_3_0_instance_init(Object *obj)
39
SysBusDevice *gicbusdev;
28
vms->irqmap = a15irqmap;
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
}
29
}
53
30
54
+static bool virt_get_its(Object *obj, Error **errp)
31
-static void virt_machine_3_0_options(MachineClass *mc)
32
+static void virt_machine_3_1_options(MachineClass *mc)
33
{
34
}
35
-DEFINE_VIRT_MACHINE_AS_LATEST(3, 0)
36
+DEFINE_VIRT_MACHINE_AS_LATEST(3, 1)
37
+
38
+static void virt_3_0_instance_init(Object *obj)
55
+{
39
+{
56
+ VirtMachineState *vms = VIRT_MACHINE(obj);
40
+ virt_3_1_instance_init(obj);
57
+
58
+ return vms->its;
59
+}
41
+}
60
+
42
+
61
+static void virt_set_its(Object *obj, bool value, Error **errp)
43
+static void virt_machine_3_0_options(MachineClass *mc)
62
+{
44
+{
63
+ VirtMachineState *vms = VIRT_MACHINE(obj);
45
+ virt_machine_3_1_options(mc);
46
+}
47
+DEFINE_VIRT_MACHINE(3, 0)
64
+
48
+
65
+ vms->its = value;
49
+#define VIRT_COMPAT_2_12 \
66
+}
50
+ HW_COMPAT_2_12
67
+
51
68
static char *virt_get_gic_version(Object *obj, Error **errp)
52
static void virt_2_12_instance_init(Object *obj)
69
{
53
{
70
VirtMachineState *vms = VIRT_MACHINE(obj);
71
@@ -XXX,XX +XXX,XX @@ type_init(machvirt_machine_init);
72
static void virt_2_9_instance_init(Object *obj)
73
{
74
VirtMachineState *vms = VIRT_MACHINE(obj);
75
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
76
77
/* EL3 is disabled by default on virt: this makes us consistent
78
* between KVM and TCG for this board, and it also allows us to
79
@@ -XXX,XX +XXX,XX @@ static void virt_2_9_instance_init(Object *obj)
80
"Set GIC version. "
81
"Valid values are 2, 3 and host", NULL);
82
83
+ if (vmc->no_its) {
84
+ vms->its = false;
85
+ } else {
86
+ /* Default allows ITS instantiation */
87
+ vms->its = true;
88
+ object_property_add_bool(obj, "its", virt_get_its,
89
+ virt_set_its, NULL);
90
+ object_property_set_description(obj, "its",
91
+ "Set on/off to enable/disable "
92
+ "ITS instantiation",
93
+ NULL);
94
+ }
95
+
96
vms->memmap = a15memmap;
97
vms->irqmap = a15irqmap;
98
}
99
--
54
--
100
2.7.4
55
2.18.0
101
56
102
57
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
2
2
3
In SDHCI protocol, the 'Block count enable' bit of the Transfer
3
Add the ESDHC PRSSTAT_SDSTB bit, using the value of SDHC_CLOCK_INT_STABLE.
4
Mode register is relevant only in multi block transfers. We need
4
Freescale recommends checking this bit when changing clock frequency.
5
not check it in single block transfers.
6
5
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
6
Signed-off-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
8
Message-id: 20170214185225.7994-5-ppandit@redhat.com
7
Message-id: 1534507843-4251-1-git-send-email-hans-erik.floryd@rt-labs.com
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
[PMM: fixed indentation]
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
hw/sd/sdhci.c | 6 +-----
12
hw/sd/sdhci-internal.h | 2 ++
13
1 file changed, 1 insertion(+), 5 deletions(-)
13
hw/sd/sdhci.c | 8 ++++++++
14
2 files changed, 10 insertions(+)
14
15
16
diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/sd/sdhci-internal.h
19
+++ b/hw/sd/sdhci-internal.h
20
@@ -XXX,XX +XXX,XX @@ extern const VMStateDescription sdhci_vmstate;
21
#define ESDHC_CTRL_4BITBUS (0x1 << 1)
22
#define ESDHC_CTRL_8BITBUS (0x2 << 1)
23
24
+#define ESDHC_PRNSTS_SDSTB (1 << 3)
25
+
26
#endif
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
27
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
29
--- a/hw/sd/sdhci.c
18
+++ b/hw/sd/sdhci.c
30
+++ b/hw/sd/sdhci.c
19
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
31
@@ -XXX,XX +XXX,XX @@ static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
20
}
32
21
33
break;
22
/* single block SDMA transfer */
34
23
-
35
+ case SDHC_PRNSTS:
24
static void sdhci_sdma_transfer_single_block(SDHCIState *s)
36
+ /* Add SDSTB (SD Clock Stable) bit to PRNSTS */
25
{
37
+ ret = sdhci_read(opaque, offset, size) & ~ESDHC_PRNSTS_SDSTB;
26
int n;
38
+ if (s->clkcon & SDHC_CLOCK_INT_STABLE) {
27
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
39
+ ret |= ESDHC_PRNSTS_SDSTB;
28
sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
40
+ }
29
}
41
+ break;
30
}
42
+
31
-
43
case ESDHC_DLL_CTRL:
32
- if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
44
case ESDHC_TUNE_CTRL_STATUS:
33
- s->blkcnt--;
45
case ESDHC_UNDOCUMENTED_REG27:
34
- }
35
+ s->blkcnt--;
36
37
sdhci_end_transfer(s);
38
}
39
--
46
--
40
2.7.4
47
2.18.0
41
48
42
49
diff view generated by jsdifflib
1
Rename the nvic_state struct to NVICState, to match
1
We now support direct execution from MMIO regions in the
2
our naming conventions.
2
core memory subsystem. This means that we don't need to
3
have device-specific support for it, and we can remove
4
the request_ptr handling from the Xilinx SPIPS device.
5
(It was broken anyway due to race conditions, and disabled
6
by default.)
7
8
This device is the only in-tree user of this API.
3
9
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
14
Message-id: 20180817114619.22354-2-peter.maydell@linaro.org
7
---
15
---
8
hw/intc/armv7m_nvic.c | 44 ++++++++++++++++++++++----------------------
16
hw/ssi/xilinx_spips.c | 46 -------------------------------------------
9
1 file changed, 22 insertions(+), 22 deletions(-)
17
1 file changed, 46 deletions(-)
10
18
11
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
12
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/armv7m_nvic.c
21
--- a/hw/ssi/xilinx_spips.c
14
+++ b/hw/intc/armv7m_nvic.c
22
+++ b/hw/ssi/xilinx_spips.c
15
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps spips_ops = {
16
#include "gic_internal.h"
24
17
#include "qemu/log.h"
25
static void xilinx_qspips_invalidate_mmio_ptr(XilinxQSPIPS *q)
18
19
-typedef struct {
20
+typedef struct NVICState {
21
GICState gic;
22
ARMCPU *cpu;
23
struct {
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
25
MemoryRegion container;
26
uint32_t num_irq;
27
qemu_irq sysresetreq;
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
{
26
{
49
if (s->systick.control & SYSTICK_CLKSOURCE)
27
- XilinxSPIPS *s = &q->parent_obj;
50
return system_clock_scale;
28
-
51
@@ -XXX,XX +XXX,XX @@ static inline int64_t systick_scale(nvic_state *s)
29
- if ((q->mmio_execution_enabled) && (q->lqspi_cached_addr != ~0ULL)) {
52
return 1000;
30
- /* Invalidate the current mapped mmio */
31
- memory_region_invalidate_mmio_ptr(&s->mmlqspi, q->lqspi_cached_addr,
32
- LQSPI_CACHE_SIZE);
33
- }
34
-
35
q->lqspi_cached_addr = ~0ULL;
53
}
36
}
54
37
55
-static void systick_reload(nvic_state *s, int reset)
38
@@ -XXX,XX +XXX,XX @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
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
}
39
}
71
}
40
}
72
41
73
-static void systick_reset(nvic_state *s)
42
-static void *lqspi_request_mmio_ptr(void *opaque, hwaddr addr, unsigned *size,
74
+static void systick_reset(NVICState *s)
43
- unsigned *offset)
44
-{
45
- XilinxQSPIPS *q = opaque;
46
- hwaddr offset_within_the_region;
47
-
48
- if (!q->mmio_execution_enabled) {
49
- return NULL;
50
- }
51
-
52
- offset_within_the_region = addr & ~(LQSPI_CACHE_SIZE - 1);
53
- lqspi_load_cache(opaque, offset_within_the_region);
54
- *size = LQSPI_CACHE_SIZE;
55
- *offset = offset_within_the_region;
56
- return q->lqspi_buf;
57
-}
58
-
59
static uint64_t
60
lqspi_read(void *opaque, hwaddr addr, unsigned int size)
75
{
61
{
76
s->systick.control = 0;
62
@@ -XXX,XX +XXX,XX @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
77
s->systick.reload = 0;
63
78
@@ -XXX,XX +XXX,XX @@ static void systick_reset(nvic_state *s)
64
static const MemoryRegionOps lqspi_ops = {
79
IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
65
.read = lqspi_read,
80
void armv7m_nvic_set_pending(void *opaque, int irq)
66
- .request_ptr = lqspi_request_mmio_ptr,
81
{
67
.endianness = DEVICE_NATIVE_ENDIAN,
82
- nvic_state *s = (nvic_state *)opaque;
68
.valid = {
83
+ NVICState *s = (NVICState *)opaque;
69
.min_access_size = 1,
84
if (irq >= 16)
70
@@ -XXX,XX +XXX,XX @@ static void xilinx_qspips_realize(DeviceState *dev, Error **errp)
85
irq += 16;
71
sysbus_init_mmio(sbd, &s->mmlqspi);
86
gic_set_pending_private(&s->gic, 0, irq);
72
87
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
73
q->lqspi_cached_addr = ~0ULL;
88
/* Make pending IRQ active. */
74
-
89
int armv7m_nvic_acknowledge_irq(void *opaque)
75
- /* mmio_execution breaks migration better aborting than having strange
90
{
76
- * bugs.
91
- nvic_state *s = (nvic_state *)opaque;
77
- */
92
+ NVICState *s = (NVICState *)opaque;
78
- if (q->mmio_execution_enabled) {
93
uint32_t irq;
79
- error_setg(&q->migration_blocker,
94
80
- "enabling mmio_execution breaks migration");
95
irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
81
- migrate_add_blocker(q->migration_blocker, &error_fatal);
96
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
82
- }
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
}
83
}
106
84
107
-static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
85
static void xlnx_zynqmp_qspips_realize(DeviceState *dev, Error **errp)
108
+static uint32_t nvic_readl(NVICState *s, uint32_t offset)
86
@@ -XXX,XX +XXX,XX @@ static Property xilinx_zynqmp_qspips_properties[] = {
109
{
87
DEFINE_PROP_END_OF_LIST(),
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
}
114
}
115
116
-static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
117
+static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
118
{
119
ARMCPU *cpu = s->cpu;
120
uint32_t oldval;
121
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
122
static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
123
unsigned size)
124
{
125
- nvic_state *s = (nvic_state *)opaque;
126
+ NVICState *s = (NVICState *)opaque;
127
uint32_t offset = addr;
128
int i;
129
uint32_t val;
130
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
131
static void nvic_sysreg_write(void *opaque, hwaddr addr,
132
uint64_t value, unsigned size)
133
{
134
- nvic_state *s = (nvic_state *)opaque;
135
+ NVICState *s = (NVICState *)opaque;
136
uint32_t offset = addr;
137
int i;
138
139
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
140
.version_id = 1,
141
.minimum_version_id = 1,
142
.fields = (VMStateField[]) {
143
- VMSTATE_UINT32(systick.control, nvic_state),
144
- VMSTATE_UINT32(systick.reload, nvic_state),
145
- VMSTATE_INT64(systick.tick, nvic_state),
146
- VMSTATE_TIMER_PTR(systick.timer, nvic_state),
147
+ VMSTATE_UINT32(systick.control, NVICState),
148
+ VMSTATE_UINT32(systick.reload, NVICState),
149
+ VMSTATE_INT64(systick.tick, NVICState),
150
+ VMSTATE_TIMER_PTR(systick.timer, NVICState),
151
VMSTATE_END_OF_LIST()
152
}
153
};
88
};
154
89
155
static void armv7m_nvic_reset(DeviceState *dev)
90
-static Property xilinx_qspips_properties[] = {
156
{
91
- /* We had to turn this off for 2.10 as it is not compatible with migration.
157
- nvic_state *s = NVIC(dev);
92
- * It can be enabled but will prevent the device to be migrated.
158
+ NVICState *s = NVIC(dev);
93
- * This will go aways when a fix will be released.
159
NVICClass *nc = NVIC_GET_CLASS(s);
94
- */
160
nc->parent_reset(dev);
95
- DEFINE_PROP_BOOL("x-mmio-exec", XilinxQSPIPS, mmio_execution_enabled,
161
/* Common GIC reset resets to disabled; the NVIC doesn't have
96
- false),
162
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
97
- DEFINE_PROP_END_OF_LIST(),
163
98
-};
164
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
99
-
165
{
100
static Property xilinx_spips_properties[] = {
166
- nvic_state *s = NVIC(dev);
101
DEFINE_PROP_UINT8("num-busses", XilinxSPIPS, num_busses, 1),
167
+ NVICState *s = NVIC(dev);
102
DEFINE_PROP_UINT8("num-ss-bits", XilinxSPIPS, num_cs, 4),
168
NVICClass *nc = NVIC_GET_CLASS(s);
103
@@ -XXX,XX +XXX,XX @@ static void xilinx_qspips_class_init(ObjectClass *klass, void * data)
169
Error *local_err = NULL;
104
XilinxSPIPSClass *xsc = XILINX_SPIPS_CLASS(klass);
170
105
171
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
106
dc->realize = xilinx_qspips_realize;
172
*/
107
- dc->props = xilinx_qspips_properties;
173
GICState *s = ARM_GIC_COMMON(obj);
108
xsc->reg_ops = &qspips_ops;
174
DeviceState *dev = DEVICE(obj);
109
xsc->rx_fifo_size = RXFF_A_Q;
175
- nvic_state *nvic = NVIC(obj);
110
xsc->tx_fifo_size = TXFF_A_Q;
176
+ NVICState *nvic = NVIC(obj);
177
/* The ARM v7m may have anything from 0 to 496 external interrupt
178
* IRQ lines. We default to 64. Other boards may differ and should
179
* set the num-irq property appropriately.
180
@@ -XXX,XX +XXX,XX @@ static const TypeInfo armv7m_nvic_info = {
181
.name = TYPE_NVIC,
182
.parent = TYPE_ARM_GIC_COMMON,
183
.instance_init = armv7m_nvic_instance_init,
184
- .instance_size = sizeof(nvic_state),
185
+ .instance_size = sizeof(NVICState),
186
.class_init = armv7m_nvic_class_init,
187
.class_size = sizeof(NVICClass),
188
};
189
--
111
--
190
2.7.4
112
2.18.0
191
113
192
114
diff view generated by jsdifflib
1
The M profile condition for when we can take a pending exception or
1
Remove the obsolete MMIO request_ptr APIs; they have no
2
interrupt is not the same as that for A/R profile. The code
2
users now.
3
originally copied from the A/R profile version of the
4
cpu_exec_interrupt function only worked by chance for the
5
very simple case of exceptions being masked by PRIMASK.
6
Replace it with a call to a function in the NVIC code that
7
correctly compares the priority of the pending exception
8
against the current execution priority of the CPU.
9
10
[Michael Davidsaver's patchset had a patch to do something
11
similar but the implementation ended up being a rewrite.]
12
3
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
8
Message-id: 20180817114619.22354-3-peter.maydell@linaro.org
15
---
9
---
16
target/arm/cpu.h | 8 ++++++++
10
include/exec/memory.h | 35 --------------
17
hw/intc/armv7m_nvic.c | 7 +++++++
11
memory.c | 110 ------------------------------------------
18
target/arm/cpu.c | 16 ++++++++--------
12
2 files changed, 145 deletions(-)
19
3 files changed, 23 insertions(+), 8 deletions(-)
20
13
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/include/exec/memory.h b/include/exec/memory.h
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
16
--- a/include/exec/memory.h
24
+++ b/target/arm/cpu.h
17
+++ b/include/exec/memory.h
25
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
18
@@ -XXX,XX +XXX,XX @@ struct MemoryRegionOps {
26
uint32_t cur_el, bool secure);
19
uint64_t data,
27
20
unsigned size,
28
/* Interface between CPU and Interrupt controller. */
21
MemTxAttrs attrs);
29
+#ifndef CONFIG_USER_ONLY
22
- /* Instruction execution pre-callback:
30
+bool armv7m_nvic_can_take_pending_exception(void *opaque);
23
- * @addr is the address of the access relative to the @mr.
31
+#else
24
- * @size is the size of the area returned by the callback.
32
+static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
25
- * @offset is the location of the pointer inside @mr.
33
+{
26
- *
34
+ return true;
27
- * Returns a pointer to a location which contains guest code.
35
+}
28
- */
36
+#endif
29
- void *(*request_ptr)(void *opaque, hwaddr addr, unsigned *size,
37
void armv7m_nvic_set_pending(void *opaque, int irq);
30
- unsigned *offset);
38
int armv7m_nvic_acknowledge_irq(void *opaque);
31
39
void armv7m_nvic_complete_irq(void *opaque, int irq);
32
enum device_endian endianness;
40
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
33
/* Guest-visible constraints: */
34
@@ -XXX,XX +XXX,XX @@ void memory_global_dirty_log_stop(void);
35
void mtree_info(fprintf_function mon_printf, void *f, bool flatview,
36
bool dispatch_tree, bool owner);
37
38
-/**
39
- * memory_region_request_mmio_ptr: request a pointer to an mmio
40
- * MemoryRegion. If it is possible map a RAM MemoryRegion with this pointer.
41
- * When the device wants to invalidate the pointer it will call
42
- * memory_region_invalidate_mmio_ptr.
43
- *
44
- * @mr: #MemoryRegion to check
45
- * @addr: address within that region
46
- *
47
- * Returns true on success, false otherwise.
48
- */
49
-bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr);
50
-
51
-/**
52
- * memory_region_invalidate_mmio_ptr: invalidate the pointer to an mmio
53
- * previously requested.
54
- * In the end that means that if something wants to execute from this area it
55
- * will need to request the pointer again.
56
- *
57
- * @mr: #MemoryRegion associated to the pointer.
58
- * @offset: offset within the memory region
59
- * @size: size of that area.
60
- */
61
-void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
62
- unsigned size);
63
-
64
/**
65
* memory_region_dispatch_read: perform a read directly to the specified
66
* MemoryRegion.
67
diff --git a/memory.c b/memory.c
41
index XXXXXXX..XXXXXXX 100644
68
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/armv7m_nvic.c
69
--- a/memory.c
43
+++ b/hw/intc/armv7m_nvic.c
70
+++ b/memory.c
44
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
71
@@ -XXX,XX +XXX,XX @@
45
return MIN(running, s->exception_prio);
72
#include "exec/ram_addr.h"
73
#include "sysemu/kvm.h"
74
#include "sysemu/sysemu.h"
75
-#include "hw/misc/mmio_interface.h"
76
#include "hw/qdev-properties.h"
77
#include "migration/vmstate.h"
78
79
@@ -XXX,XX +XXX,XX @@ void memory_listener_unregister(MemoryListener *listener)
80
listener->address_space = NULL;
46
}
81
}
47
82
48
+bool armv7m_nvic_can_take_pending_exception(void *opaque)
83
-bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr)
49
+{
84
-{
50
+ NVICState *s = opaque;
85
- void *host;
51
+
86
- unsigned size = 0;
52
+ return nvic_exec_prio(s) > nvic_pending_prio(s);
87
- unsigned offset = 0;
53
+}
88
- Object *new_interface;
54
+
89
-
55
/* caller must call nvic_irq_update() after this */
90
- if (!mr || !mr->ops->request_ptr) {
56
static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
91
- return false;
92
- }
93
-
94
- /*
95
- * Avoid an update if the request_ptr call
96
- * memory_region_invalidate_mmio_ptr which seems to be likely when we use
97
- * a cache.
98
- */
99
- memory_region_transaction_begin();
100
-
101
- host = mr->ops->request_ptr(mr->opaque, addr - mr->addr, &size, &offset);
102
-
103
- if (!host || !size) {
104
- memory_region_transaction_commit();
105
- return false;
106
- }
107
-
108
- new_interface = object_new("mmio_interface");
109
- qdev_prop_set_uint64(DEVICE(new_interface), "start", offset);
110
- qdev_prop_set_uint64(DEVICE(new_interface), "end", offset + size - 1);
111
- qdev_prop_set_bit(DEVICE(new_interface), "ro", true);
112
- qdev_prop_set_ptr(DEVICE(new_interface), "host_ptr", host);
113
- qdev_prop_set_ptr(DEVICE(new_interface), "subregion", mr);
114
- object_property_set_bool(OBJECT(new_interface), true, "realized", NULL);
115
-
116
- memory_region_transaction_commit();
117
- return true;
118
-}
119
-
120
-typedef struct MMIOPtrInvalidate {
121
- MemoryRegion *mr;
122
- hwaddr offset;
123
- unsigned size;
124
- int busy;
125
- int allocated;
126
-} MMIOPtrInvalidate;
127
-
128
-#define MAX_MMIO_INVALIDATE 10
129
-static MMIOPtrInvalidate mmio_ptr_invalidate_list[MAX_MMIO_INVALIDATE];
130
-
131
-static void memory_region_do_invalidate_mmio_ptr(CPUState *cpu,
132
- run_on_cpu_data data)
133
-{
134
- MMIOPtrInvalidate *invalidate_data = (MMIOPtrInvalidate *)data.host_ptr;
135
- MemoryRegion *mr = invalidate_data->mr;
136
- hwaddr offset = invalidate_data->offset;
137
- unsigned size = invalidate_data->size;
138
- MemoryRegionSection section = memory_region_find(mr, offset, size);
139
-
140
- qemu_mutex_lock_iothread();
141
-
142
- /* Reset dirty so this doesn't happen later. */
143
- cpu_physical_memory_test_and_clear_dirty(offset, size, 1);
144
-
145
- if (section.mr != mr) {
146
- /* memory_region_find add a ref on section.mr */
147
- memory_region_unref(section.mr);
148
- if (MMIO_INTERFACE(section.mr->owner)) {
149
- /* We found the interface just drop it. */
150
- object_property_set_bool(section.mr->owner, false, "realized",
151
- NULL);
152
- object_unref(section.mr->owner);
153
- object_unparent(section.mr->owner);
154
- }
155
- }
156
-
157
- qemu_mutex_unlock_iothread();
158
-
159
- if (invalidate_data->allocated) {
160
- g_free(invalidate_data);
161
- } else {
162
- invalidate_data->busy = 0;
163
- }
164
-}
165
-
166
-void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
167
- unsigned size)
168
-{
169
- size_t i;
170
- MMIOPtrInvalidate *invalidate_data = NULL;
171
-
172
- for (i = 0; i < MAX_MMIO_INVALIDATE; i++) {
173
- if (atomic_cmpxchg(&(mmio_ptr_invalidate_list[i].busy), 0, 1) == 0) {
174
- invalidate_data = &mmio_ptr_invalidate_list[i];
175
- break;
176
- }
177
- }
178
-
179
- if (!invalidate_data) {
180
- invalidate_data = g_malloc0(sizeof(MMIOPtrInvalidate));
181
- invalidate_data->allocated = 1;
182
- }
183
-
184
- invalidate_data->mr = mr;
185
- invalidate_data->offset = offset;
186
- invalidate_data->size = size;
187
-
188
- async_safe_run_on_cpu(first_cpu, memory_region_do_invalidate_mmio_ptr,
189
- RUN_ON_CPU_HOST_PTR(invalidate_data));
190
-}
191
-
192
void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
57
{
193
{
58
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
194
memory_region_ref(root);
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/cpu.c
61
+++ b/target/arm/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
63
CPUARMState *env = &cpu->env;
64
bool ret = false;
65
66
-
67
- if (interrupt_request & CPU_INTERRUPT_FIQ
68
- && !(env->daif & PSTATE_F)) {
69
- cs->exception_index = EXCP_FIQ;
70
- cc->do_interrupt(cs);
71
- ret = true;
72
- }
73
/* ARMv7-M interrupt return works by loading a magic value
74
* into the PC. On real hardware the load causes the
75
* return to occur. The qemu implementation performs the
76
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
77
* the stack if an interrupt occurred at the wrong time.
78
* We avoid this by disabling interrupts when
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
--
195
--
95
2.7.4
196
2.18.0
96
197
97
198
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
The mmio_interface device was a purely internal artifact
2
2
of the implementation of the memory subsystem's request_ptr
3
Without any clock controller, the Linux kernel was hitting division by
3
APIs. Now that we have removed those APIs, we can remove
4
zero during boot or with clk_summary:
4
the mmio_interface device too.
5
[ 0.000000] [<c031054c>] (unwind_backtrace) from [<c030ba6c>] (show_stack+0x10/0x14)
5
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
17
Provide stub for clock controller returning reset values for PLLs.
18
19
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
20
Message-id: 20170226200142.31169-1-krzk@kernel.org
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
10
Message-id: 20180817114619.22354-4-peter.maydell@linaro.org
23
---
11
---
24
hw/misc/Makefile.objs | 2 +-
12
hw/misc/Makefile.objs | 1 -
25
hw/arm/exynos4210.c | 6 ++
13
include/hw/misc/mmio_interface.h | 49 -----------
26
hw/misc/exynos4210_clk.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++
14
hw/misc/mmio_interface.c | 135 -------------------------------
27
3 files changed, 171 insertions(+), 1 deletion(-)
15
3 files changed, 185 deletions(-)
28
create mode 100644 hw/misc/exynos4210_clk.c
16
delete mode 100644 include/hw/misc/mmio_interface.h
17
delete mode 100644 hw/misc/mmio_interface.c
29
18
30
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
31
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/Makefile.objs
21
--- a/hw/misc/Makefile.objs
33
+++ b/hw/misc/Makefile.objs
22
+++ b/hw/misc/Makefile.objs
34
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_PVPANIC) += pvpanic.o
35
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
24
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
36
obj-$(CONFIG_NSERIES) += cbus.o
25
obj-$(CONFIG_AUX) += auxbus.o
37
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
26
obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
38
-obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
27
-obj-y += mmio_interface.o
39
+obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o
28
obj-$(CONFIG_MSF2) += msf2-sysreg.o
40
obj-$(CONFIG_IMX) += imx_ccm.o
29
diff --git a/include/hw/misc/mmio_interface.h b/include/hw/misc/mmio_interface.h
41
obj-$(CONFIG_IMX) += imx31_ccm.o
30
deleted file mode 100644
42
obj-$(CONFIG_IMX) += imx25_ccm.o
31
index XXXXXXX..XXXXXXX
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
32
--- a/include/hw/misc/mmio_interface.h
44
index XXXXXXX..XXXXXXX 100644
33
+++ /dev/null
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@
48
#include "qemu/osdep.h"
35
-/*
49
#include "qapi/error.h"
36
- * mmio_interface.h
50
#include "qemu-common.h"
37
- *
51
+#include "qemu/log.h"
38
- * Copyright (C) 2017 : GreenSocs
52
#include "cpu.h"
39
- * http://www.greensocs.com/ , email: info@greensocs.com
53
#include "hw/boards.h"
40
- *
54
#include "sysemu/sysemu.h"
41
- * Developed by :
42
- * Frederic Konrad <fred.konrad@greensocs.com>
43
- *
44
- * This program is free software; you can redistribute it and/or modify
45
- * it under the terms of the GNU General Public License as published by
46
- * the Free Software Foundation, either version 2 of the License, or
47
- * (at your option)any later version.
48
- *
49
- * This program is distributed in the hope that it will be useful,
50
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
51
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52
- * GNU General Public License for more details.
53
- *
54
- * You should have received a copy of the GNU General Public License along
55
- * with this program; if not, see <http://www.gnu.org/licenses/>.
56
- *
57
- */
58
-
59
-#ifndef MMIO_INTERFACE_H
60
-#define MMIO_INTERFACE_H
61
-
62
-#include "exec/memory.h"
63
-
64
-#define TYPE_MMIO_INTERFACE "mmio_interface"
65
-#define MMIO_INTERFACE(obj) OBJECT_CHECK(MMIOInterface, (obj), \
66
- TYPE_MMIO_INTERFACE)
67
-
68
-typedef struct MMIOInterface {
69
- DeviceState parent_obj;
70
-
71
- MemoryRegion *subregion;
72
- MemoryRegion ram_mem;
73
- uint64_t start;
74
- uint64_t end;
75
- bool ro;
76
- uint64_t id;
77
- void *host_ptr;
78
-} MMIOInterface;
79
-
80
-void mmio_interface_map(MMIOInterface *s);
81
-void mmio_interface_unmap(MMIOInterface *s);
82
-
83
-#endif /* MMIO_INTERFACE_H */
84
diff --git a/hw/misc/mmio_interface.c b/hw/misc/mmio_interface.c
85
deleted file mode 100644
86
index XXXXXXX..XXXXXXX
87
--- a/hw/misc/mmio_interface.c
88
+++ /dev/null
55
@@ -XXX,XX +XXX,XX @@
89
@@ -XXX,XX +XXX,XX @@
56
/* PMU SFR base address */
90
-/*
57
#define EXYNOS4210_PMU_BASE_ADDR 0x10020000
91
- * mmio_interface.c
58
92
- *
59
+/* Clock controller SFR base address */
93
- * Copyright (C) 2017 : GreenSocs
60
+#define EXYNOS4210_CLK_BASE_ADDR 0x10030000
94
- * http://www.greensocs.com/ , email: info@greensocs.com
61
+
95
- *
62
/* Display controllers (FIMD) */
96
- * Developed by :
63
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
97
- * Frederic Konrad <fred.konrad@greensocs.com>
64
98
- *
65
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
99
- * This program is free software; you can redistribute it and/or modify
66
*/
100
- * it under the terms of the GNU General Public License as published by
67
sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
101
- * the Free Software Foundation, either version 2 of the License, or
68
102
- * (at your option)any later version.
69
+ sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
103
- *
70
+
104
- * This program is distributed in the hope that it will be useful,
71
/* PWM */
105
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
72
sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
106
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73
s->irq_table[exynos4210_get_irq(22, 0)],
107
- * GNU General Public License for more details.
74
diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c
108
- *
75
new file mode 100644
109
- * You should have received a copy of the GNU General Public License along
76
index XXXXXXX..XXXXXXX
110
- * with this program; if not, see <http://www.gnu.org/licenses/>.
77
--- /dev/null
111
- *
78
+++ b/hw/misc/exynos4210_clk.c
112
- */
79
@@ -XXX,XX +XXX,XX @@
113
-
80
+/*
114
-#include "qemu/osdep.h"
81
+ * Exynos4210 Clock Controller Emulation
115
-#include "qemu/log.h"
82
+ *
116
-#include "trace.h"
83
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
117
-#include "hw/qdev-properties.h"
84
+ *
118
-#include "hw/misc/mmio_interface.h"
85
+ * This program is free software; you can redistribute it and/or modify it
119
-#include "qapi/error.h"
86
+ * under the terms of the GNU General Public License as published by the
120
-
87
+ * Free Software Foundation; either version 2 of the License, or
121
-#ifndef DEBUG_MMIO_INTERFACE
88
+ * (at your option) any later version.
122
-#define DEBUG_MMIO_INTERFACE 0
89
+ *
123
-#endif
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
124
-
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
125
-static uint64_t mmio_interface_counter;
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
126
-
93
+ * for more details.
127
-#define DPRINTF(fmt, ...) do { \
94
+ *
128
- if (DEBUG_MMIO_INTERFACE) { \
95
+ * You should have received a copy of the GNU General Public License along
129
- qemu_log("mmio_interface: 0x%" PRIX64 ": " fmt, s->id, ## __VA_ARGS__);\
96
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
130
- } \
97
+ */
131
-} while (0)
98
+
132
-
99
+#include "qemu/osdep.h"
133
-static void mmio_interface_init(Object *obj)
100
+#include "hw/sysbus.h"
134
-{
101
+#include "qemu/log.h"
135
- MMIOInterface *s = MMIO_INTERFACE(obj);
102
+
136
-
103
+#define TYPE_EXYNOS4210_CLK "exynos4210.clk"
137
- if (DEBUG_MMIO_INTERFACE) {
104
+#define EXYNOS4210_CLK(obj) \
138
- s->id = mmio_interface_counter++;
105
+ OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK)
139
- }
106
+
140
-
107
+#define CLK_PLL_LOCKED BIT(29)
141
- DPRINTF("interface created\n");
108
+
142
- s->host_ptr = 0;
109
+#define EXYNOS4210_CLK_REGS_MEM_SIZE 0x15104
143
- s->subregion = 0;
110
+
144
-}
111
+typedef struct Exynos4210Reg {
145
-
112
+ const char *name; /* for debug only */
146
-static void mmio_interface_realize(DeviceState *dev, Error **errp)
113
+ uint32_t offset;
147
-{
114
+ uint32_t reset_value;
148
- MMIOInterface *s = MMIO_INTERFACE(dev);
115
+} Exynos4210Reg;
149
-
116
+
150
- DPRINTF("realize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
117
+/* Clock controller register base: 0x10030000 */
151
- " %p\n", s->start, s->end, s->host_ptr);
118
+static const Exynos4210Reg exynos4210_clk_regs[] = {
152
-
119
+ {"EPLL_LOCK", 0xc010, 0x00000fff},
153
- if (!s->host_ptr) {
120
+ {"VPLL_LOCK", 0xc020, 0x00000fff},
154
- error_setg(errp, "host_ptr property must be set");
121
+ {"EPLL_CON0", 0xc110, 0x00300301 | CLK_PLL_LOCKED},
155
- return;
122
+ {"EPLL_CON1", 0xc114, 0x00000000},
156
- }
123
+ {"VPLL_CON0", 0xc120, 0x00240201 | CLK_PLL_LOCKED},
157
-
124
+ {"VPLL_CON1", 0xc124, 0x66010464},
158
- if (!s->subregion) {
125
+ {"APLL_LOCK", 0x14000, 0x00000fff},
159
- error_setg(errp, "subregion property must be set");
126
+ {"MPLL_LOCK", 0x14004, 0x00000fff},
160
- return;
127
+ {"APLL_CON0", 0x14100, 0x00c80601 | CLK_PLL_LOCKED},
161
- }
128
+ {"APLL_CON1", 0x14104, 0x0000001c},
162
-
129
+ {"MPLL_CON0", 0x14108, 0x00c80601 | CLK_PLL_LOCKED},
163
- memory_region_init_ram_ptr(&s->ram_mem, OBJECT(s), "ram",
130
+ {"MPLL_CON1", 0x1410c, 0x0000001c},
164
- s->end - s->start + 1, s->host_ptr);
131
+};
165
- memory_region_set_readonly(&s->ram_mem, s->ro);
132
+
166
- memory_region_add_subregion(s->subregion, s->start, &s->ram_mem);
133
+#define EXYNOS4210_REGS_NUM ARRAY_SIZE(exynos4210_clk_regs)
167
-}
134
+
168
-
135
+typedef struct Exynos4210ClkState {
169
-static void mmio_interface_unrealize(DeviceState *dev, Error **errp)
136
+ SysBusDevice parent_obj;
170
-{
137
+
171
- MMIOInterface *s = MMIO_INTERFACE(dev);
138
+ MemoryRegion iomem;
172
-
139
+ uint32_t reg[EXYNOS4210_REGS_NUM];
173
- DPRINTF("unrealize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
140
+} Exynos4210ClkState;
174
- " %p\n", s->start, s->end, s->host_ptr);
141
+
175
- memory_region_del_subregion(s->subregion, &s->ram_mem);
142
+static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset,
176
-}
143
+ unsigned size)
177
-
144
+{
178
-static void mmio_interface_finalize(Object *obj)
145
+ const Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
179
-{
146
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
180
- MMIOInterface *s = MMIO_INTERFACE(obj);
147
+ unsigned int i;
181
-
148
+
182
- DPRINTF("finalize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
149
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
183
- " %p\n", s->start, s->end, s->host_ptr);
150
+ if (regs->offset == offset) {
184
- object_unparent(OBJECT(&s->ram_mem));
151
+ return s->reg[i];
185
-}
152
+ }
186
-
153
+ regs++;
187
-static Property mmio_interface_properties[] = {
154
+ }
188
- DEFINE_PROP_UINT64("start", MMIOInterface, start, 0),
155
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read offset 0x%04x\n",
189
- DEFINE_PROP_UINT64("end", MMIOInterface, end, 0),
156
+ __func__, (uint32_t)offset);
190
- DEFINE_PROP_PTR("host_ptr", MMIOInterface, host_ptr),
157
+ return 0;
191
- DEFINE_PROP_BOOL("ro", MMIOInterface, ro, false),
158
+}
192
- DEFINE_PROP_MEMORY_REGION("subregion", MMIOInterface, subregion),
159
+
193
- DEFINE_PROP_END_OF_LIST(),
160
+static void exynos4210_clk_write(void *opaque, hwaddr offset,
194
-};
161
+ uint64_t val, unsigned size)
195
-
162
+{
196
-static void mmio_interface_class_init(ObjectClass *oc, void *data)
163
+ Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
197
-{
164
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
198
- DeviceClass *dc = DEVICE_CLASS(oc);
165
+ unsigned int i;
199
-
166
+
200
- dc->realize = mmio_interface_realize;
167
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
201
- dc->unrealize = mmio_interface_unrealize;
168
+ if (regs->offset == offset) {
202
- dc->props = mmio_interface_properties;
169
+ s->reg[i] = val;
203
- /* Reason: pointer property "host_ptr", and this device
170
+ return;
204
- * is an implementation detail of the memory subsystem,
171
+ }
205
- * not intended to be created directly by the user.
172
+ regs++;
206
- */
173
+ }
207
- dc->user_creatable = false;
174
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write offset 0x%04x\n",
208
-}
175
+ __func__, (uint32_t)offset);
209
-
176
+}
210
-static const TypeInfo mmio_interface_info = {
177
+
211
- .name = TYPE_MMIO_INTERFACE,
178
+static const MemoryRegionOps exynos4210_clk_ops = {
212
- .parent = TYPE_DEVICE,
179
+ .read = exynos4210_clk_read,
213
- .instance_size = sizeof(MMIOInterface),
180
+ .write = exynos4210_clk_write,
214
- .instance_init = mmio_interface_init,
181
+ .endianness = DEVICE_NATIVE_ENDIAN,
215
- .instance_finalize = mmio_interface_finalize,
182
+ .valid = {
216
- .class_init = mmio_interface_class_init,
183
+ .min_access_size = 4,
217
-};
184
+ .max_access_size = 4,
218
-
185
+ .unaligned = false
219
-static void mmio_interface_register_types(void)
186
+ }
220
-{
187
+};
221
- type_register_static(&mmio_interface_info);
188
+
222
-}
189
+static void exynos4210_clk_reset(DeviceState *dev)
223
-
190
+{
224
-type_init(mmio_interface_register_types)
191
+ Exynos4210ClkState *s = EXYNOS4210_CLK(dev);
192
+ unsigned int i;
193
+
194
+ /* Set default values for registers */
195
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
196
+ s->reg[i] = exynos4210_clk_regs[i].reset_value;
197
+ }
198
+}
199
+
200
+static void exynos4210_clk_init(Object *obj)
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
--
225
--
245
2.7.4
226
2.18.0
246
227
247
228
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
Move the m48t59 device away from using old_mmio MemoryRegionOps
2
accessors.
2
3
3
Now that the NVIC is its own separate implementation, we can
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
clean up the GIC code by removing REV_NVIC and conditionals
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
which use it.
6
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
7
Message-id: 20180802180602.22047-1-peter.maydell@linaro.org
8
---
9
hw/timer/m48t59.c | 59 +++++++++--------------------------------------
10
1 file changed, 11 insertions(+), 48 deletions(-)
6
11
7
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
12
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.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
13
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/gic_internal.h
14
--- a/hw/timer/m48t59.c
19
+++ b/hw/intc/gic_internal.h
15
+++ b/hw/timer/m48t59.c
20
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size)
21
17
return retval;
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
}
18
}
55
19
56
-static void gic_set_irq_nvic(GICState *s, int irq, int level,
20
-static void nvram_writeb (void *opaque, hwaddr addr, uint32_t value)
57
- int cm, int target)
58
-{
21
-{
59
- if (level) {
22
- M48t59State *NVRAM = opaque;
60
- GIC_SET_LEVEL(irq, cm);
23
-
61
- GIC_SET_PENDING(irq, target);
24
- m48t59_write(NVRAM, addr, value & 0xff);
62
- } else {
63
- GIC_CLEAR_LEVEL(irq, cm);
64
- }
65
-}
25
-}
66
-
26
-
67
static void gic_set_irq_generic(GICState *s, int irq, int level,
27
-static void nvram_writew (void *opaque, hwaddr addr, uint32_t value)
68
int cm, int target)
28
-{
29
- M48t59State *NVRAM = opaque;
30
-
31
- m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
32
- m48t59_write(NVRAM, addr + 1, value & 0xff);
33
-}
34
-
35
-static void nvram_writel (void *opaque, hwaddr addr, uint32_t value)
36
-{
37
- M48t59State *NVRAM = opaque;
38
-
39
- m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
40
- m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
41
- m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
42
- m48t59_write(NVRAM, addr + 3, value & 0xff);
43
-}
44
-
45
-static uint32_t nvram_readb (void *opaque, hwaddr addr)
46
+static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned size)
69
{
47
{
70
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq(void *opaque, int irq, int level)
48
M48t59State *NVRAM = opaque;
71
49
72
if (s->revision == REV_11MPCORE) {
50
return m48t59_read(NVRAM, addr);
73
gic_set_irq_11mpcore(s, irq, level, cm, target);
74
- } else if (s->revision == REV_NVIC) {
75
- gic_set_irq_nvic(s, irq, level, cm, target);
76
} else {
77
gic_set_irq_generic(s, irq, level, cm, target);
78
}
79
@@ -XXX,XX +XXX,XX @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
80
return 1023;
81
}
82
83
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
84
+ if (s->revision == REV_11MPCORE) {
85
/* Clear pending flags for both level and edge triggered interrupts.
86
* Level triggered IRQs will be reasserted once they become inactive.
87
*/
88
@@ -XXX,XX +XXX,XX @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
89
DPRINTF("Set %d pending mask %x\n", irq, cm);
90
GIC_SET_PENDING(irq, cm);
91
}
92
- } else if (s->revision == REV_NVIC) {
93
- if (GIC_TEST_LEVEL(irq, cm)) {
94
- DPRINTF("Set nvic %d pending mask %x\n", irq, cm);
95
- GIC_SET_PENDING(irq, cm);
96
- }
97
}
98
99
group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
100
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
101
} else if (offset < 0xf10) {
102
goto bad_reg;
103
} else if (offset < 0xf30) {
104
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
105
+ if (s->revision == REV_11MPCORE) {
106
goto bad_reg;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
110
case 2:
111
res = gic_id_gicv2[(offset - 0xfd0) >> 2];
112
break;
113
- case REV_NVIC:
114
- /* Shouldn't be able to get here */
115
- abort();
116
default:
117
res = 0;
118
}
119
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
120
continue; /* Ignore Non-secure access of Group0 IRQ */
121
}
122
123
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
124
+ if (s->revision == REV_11MPCORE) {
125
if (value & (1 << (i * 2))) {
126
GIC_SET_MODEL(irq + i);
127
} else {
128
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
129
goto bad_reg;
130
} else if (offset < 0xf20) {
131
/* GICD_CPENDSGIRn */
132
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
133
+ if (s->revision == REV_11MPCORE) {
134
goto bad_reg;
135
}
136
irq = (offset - 0xf10);
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
}
51
}
182
52
183
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
53
-static uint32_t nvram_readw (void *opaque, hwaddr addr)
184
@@ -XXX,XX +XXX,XX @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
54
+static void nvram_write(void *opaque, hwaddr addr, uint64_t value,
185
}
55
+ unsigned size)
186
56
{
187
if (s->security_extn &&
57
M48t59State *NVRAM = opaque;
188
- (s->revision == REV_11MPCORE || s->revision == REV_NVIC)) {
58
- uint32_t retval;
189
+ (s->revision == REV_11MPCORE)) {
59
190
error_setg(errp, "this GIC revision does not implement "
60
- retval = m48t59_read(NVRAM, addr) << 8;
191
"the security extensions");
61
- retval |= m48t59_read(NVRAM, addr + 1);
192
return;
62
- return retval;
193
@@ -XXX,XX +XXX,XX @@ static Property arm_gic_common_properties[] = {
63
-}
194
DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
64
-
195
/* Revision can be 1 or 2 for GIC architecture specification
65
-static uint32_t nvram_readl (void *opaque, hwaddr addr)
196
* versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC.
66
-{
197
- * (Internally, 0xffffffff also indicates "not a GIC but an NVIC".)
67
- M48t59State *NVRAM = opaque;
198
*/
68
- uint32_t retval;
199
DEFINE_PROP_UINT32("revision", GICState, revision, 1),
69
-
200
/* True if the GIC should implement the security extensions */
70
- retval = m48t59_read(NVRAM, addr) << 24;
71
- retval |= m48t59_read(NVRAM, addr + 1) << 16;
72
- retval |= m48t59_read(NVRAM, addr + 2) << 8;
73
- retval |= m48t59_read(NVRAM, addr + 3);
74
- return retval;
75
+ return m48t59_write(NVRAM, addr, value);
76
}
77
78
static const MemoryRegionOps nvram_ops = {
79
- .old_mmio = {
80
- .read = { nvram_readb, nvram_readw, nvram_readl, },
81
- .write = { nvram_writeb, nvram_writew, nvram_writel, },
82
- },
83
- .endianness = DEVICE_NATIVE_ENDIAN,
84
+ .read = nvram_read,
85
+ .write = nvram_write,
86
+ .impl.min_access_size = 1,
87
+ .impl.max_access_size = 1,
88
+ .valid.min_access_size = 1,
89
+ .valid.max_access_size = 4,
90
+ .endianness = DEVICE_BIG_ENDIAN,
91
};
92
93
static const VMStateDescription vmstate_m48t59 = {
201
--
94
--
202
2.7.4
95
2.18.0
203
96
204
97
diff view generated by jsdifflib
1
From: Marcin Chojnacki <marcinch7@gmail.com>
1
The Arm Cortex-M System Design Kit includes a simple watchdog module
2
based on a 32-bit down-counter. Implement this.
2
3
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>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
5
---
23
hw/misc/Makefile.objs | 1 +
6
Makefile.objs | 1 +
24
include/hw/arm/bcm2835_peripherals.h | 2 +
7
hw/watchdog/Makefile.objs | 1 +
25
include/hw/misc/bcm2835_rng.h | 27 ++++++++
8
include/hw/watchdog/cmsdk-apb-watchdog.h | 59 ++++
26
hw/arm/bcm2835_peripherals.c | 15 +++++
9
hw/watchdog/cmsdk-apb-watchdog.c | 326 +++++++++++++++++++++++
27
hw/misc/bcm2835_rng.c | 124 +++++++++++++++++++++++++++++++++++
10
MAINTAINERS | 2 +
28
5 files changed, 169 insertions(+)
11
default-configs/arm-softmmu.mak | 1 +
29
create mode 100644 include/hw/misc/bcm2835_rng.h
12
hw/watchdog/trace-events | 6 +
30
create mode 100644 hw/misc/bcm2835_rng.c
13
7 files changed, 396 insertions(+)
14
create mode 100644 include/hw/watchdog/cmsdk-apb-watchdog.h
15
create mode 100644 hw/watchdog/cmsdk-apb-watchdog.c
16
create mode 100644 hw/watchdog/trace-events
31
17
32
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
18
diff --git a/Makefile.objs b/Makefile.objs
33
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/misc/Makefile.objs
20
--- a/Makefile.objs
35
+++ b/hw/misc/Makefile.objs
21
+++ b/Makefile.objs
36
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_sdrc.o
22
@@ -XXX,XX +XXX,XX @@ trace-events-subdirs += hw/tpm
37
obj-$(CONFIG_OMAP) += omap_tap.o
23
trace-events-subdirs += hw/usb
38
obj-$(CONFIG_RASPI) += bcm2835_mbox.o
24
trace-events-subdirs += hw/vfio
39
obj-$(CONFIG_RASPI) += bcm2835_property.o
25
trace-events-subdirs += hw/virtio
40
+obj-$(CONFIG_RASPI) += bcm2835_rng.o
26
+trace-events-subdirs += hw/watchdog
41
obj-$(CONFIG_SLAVIO) += slavio_misc.o
27
trace-events-subdirs += hw/xen
42
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
28
trace-events-subdirs += io
43
obj-$(CONFIG_ZYNQ) += zynq-xadc.o
29
trace-events-subdirs += linux-user
44
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
30
diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
45
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/bcm2835_peripherals.h
32
--- a/hw/watchdog/Makefile.objs
47
+++ b/include/hw/arm/bcm2835_peripherals.h
33
+++ b/hw/watchdog/Makefile.objs
48
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@
49
#include "hw/dma/bcm2835_dma.h"
35
common-obj-y += watchdog.o
50
#include "hw/intc/bcm2835_ic.h"
36
+common-obj-$(CONFIG_CMSDK_APB_WATCHDOG) += cmsdk-apb-watchdog.o
51
#include "hw/misc/bcm2835_property.h"
37
common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
52
+#include "hw/misc/bcm2835_rng.h"
38
common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
53
#include "hw/misc/bcm2835_mbox.h"
39
common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
54
#include "hw/sd/sdhci.h"
40
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.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
41
new file mode 100644
66
index XXXXXXX..XXXXXXX
42
index XXXXXXX..XXXXXXX
67
--- /dev/null
43
--- /dev/null
68
+++ b/include/hw/misc/bcm2835_rng.h
44
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
69
@@ -XXX,XX +XXX,XX @@
45
@@ -XXX,XX +XXX,XX @@
70
+/*
46
+/*
71
+ * BCM2835 Random Number Generator emulation
47
+ * ARM CMSDK APB watchdog emulation
72
+ *
48
+ *
73
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
49
+ * Copyright (c) 2018 Linaro Limited
74
+ *
50
+ * Written by Peter Maydell
75
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
51
+ *
76
+ * See the COPYING file in the top-level directory.
52
+ * This program is free software; you can redistribute it and/or modify
53
+ * it under the terms of the GNU General Public License version 2 or
54
+ * (at your option) any later version.
77
+ */
55
+ */
78
+
56
+
79
+#ifndef BCM2835_RNG_H
57
+/*
80
+#define BCM2835_RNG_H
58
+ * This is a model of the "APB watchdog" which is part of the Cortex-M
59
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
60
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
61
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
62
+ *
63
+ * QEMU interface:
64
+ * + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
65
+ * + sysbus MMIO region 0: the register bank
66
+ * + sysbus IRQ 0: watchdog interrupt
67
+ *
68
+ * In real hardware the watchdog's reset output is just a GPIO line
69
+ * which can then be masked by the board or treated as a simple interrupt.
70
+ * (For instance the IoTKit does this with the non-secure watchdog, so that
71
+ * secure code can control whether non-secure code can perform a system
72
+ * reset via its watchdog.) In QEMU, we just wire up the watchdog reset
73
+ * to watchdog_perform_action(), at least for the moment.
74
+ */
75
+
76
+#ifndef CMSDK_APB_WATCHDOG_H
77
+#define CMSDK_APB_WATCHDOG_H
81
+
78
+
82
+#include "hw/sysbus.h"
79
+#include "hw/sysbus.h"
83
+
80
+#include "hw/ptimer.h"
84
+#define TYPE_BCM2835_RNG "bcm2835-rng"
81
+
85
+#define BCM2835_RNG(obj) \
82
+#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
86
+ OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG)
83
+#define CMSDK_APB_WATCHDOG(obj) OBJECT_CHECK(CMSDKAPBWatchdog, (obj), \
87
+
84
+ TYPE_CMSDK_APB_WATCHDOG)
88
+typedef struct {
85
+
89
+ SysBusDevice busdev;
86
+typedef struct CMSDKAPBWatchdog {
87
+ /*< private >*/
88
+ SysBusDevice parent_obj;
89
+
90
+ /*< public >*/
90
+ MemoryRegion iomem;
91
+ MemoryRegion iomem;
91
+
92
+ qemu_irq wdogint;
92
+ uint32_t rng_ctrl;
93
+ uint32_t wdogclk_frq;
93
+ uint32_t rng_status;
94
+ struct ptimer_state *timer;
94
+} BCM2835RngState;
95
+
96
+ uint32_t control;
97
+ uint32_t intstatus;
98
+ uint32_t lock;
99
+ uint32_t itcr;
100
+ uint32_t itop;
101
+ uint32_t resetstatus;
102
+} CMSDKAPBWatchdog;
95
+
103
+
96
+#endif
104
+#endif
97
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
105
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.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
106
new file mode 100644
132
index XXXXXXX..XXXXXXX
107
index XXXXXXX..XXXXXXX
133
--- /dev/null
108
--- /dev/null
134
+++ b/hw/misc/bcm2835_rng.c
109
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
135
@@ -XXX,XX +XXX,XX @@
110
@@ -XXX,XX +XXX,XX @@
136
+/*
111
+/*
137
+ * BCM2835 Random Number Generator emulation
112
+ * ARM CMSDK APB watchdog emulation
138
+ *
113
+ *
139
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
114
+ * Copyright (c) 2018 Linaro Limited
140
+ *
115
+ * Written by Peter Maydell
141
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
116
+ *
142
+ * See the COPYING file in the top-level directory.
117
+ * This program is free software; you can redistribute it and/or modify
118
+ * it under the terms of the GNU General Public License version 2 or
119
+ * (at your option) any later version.
120
+ */
121
+
122
+/*
123
+ * This is a model of the "APB watchdog" which is part of the Cortex-M
124
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
125
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
126
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
143
+ */
127
+ */
144
+
128
+
145
+#include "qemu/osdep.h"
129
+#include "qemu/osdep.h"
146
+#include "qemu/log.h"
130
+#include "qemu/log.h"
147
+#include "hw/misc/bcm2835_rng.h"
131
+#include "trace.h"
148
+
132
+#include "qapi/error.h"
149
+static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
133
+#include "qemu/main-loop.h"
150
+ unsigned size)
134
+#include "sysemu/watchdog.h"
151
+{
135
+#include "hw/sysbus.h"
152
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
136
+#include "hw/registerfields.h"
153
+ uint32_t res = 0;
137
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
154
+
138
+
155
+ assert(size == 4);
139
+REG32(WDOGLOAD, 0x0)
140
+REG32(WDOGVALUE, 0x4)
141
+REG32(WDOGCONTROL, 0x8)
142
+ FIELD(WDOGCONTROL, INTEN, 0, 1)
143
+ FIELD(WDOGCONTROL, RESEN, 1, 1)
144
+#define R_WDOGCONTROL_VALID_MASK (R_WDOGCONTROL_INTEN_MASK | \
145
+ R_WDOGCONTROL_RESEN_MASK)
146
+REG32(WDOGINTCLR, 0xc)
147
+REG32(WDOGRIS, 0x10)
148
+ FIELD(WDOGRIS, INT, 0, 1)
149
+REG32(WDOGMIS, 0x14)
150
+REG32(WDOGLOCK, 0xc00)
151
+#define WDOG_UNLOCK_VALUE 0x1ACCE551
152
+REG32(WDOGITCR, 0xf00)
153
+ FIELD(WDOGITCR, ENABLE, 0, 1)
154
+#define R_WDOGITCR_VALID_MASK R_WDOGITCR_ENABLE_MASK
155
+REG32(WDOGITOP, 0xf04)
156
+ FIELD(WDOGITOP, WDOGRES, 0, 1)
157
+ FIELD(WDOGITOP, WDOGINT, 1, 1)
158
+#define R_WDOGITOP_VALID_MASK (R_WDOGITOP_WDOGRES_MASK | \
159
+ R_WDOGITOP_WDOGINT_MASK)
160
+REG32(PID4, 0xfd0)
161
+REG32(PID5, 0xfd4)
162
+REG32(PID6, 0xfd8)
163
+REG32(PID7, 0xfdc)
164
+REG32(PID0, 0xfe0)
165
+REG32(PID1, 0xfe4)
166
+REG32(PID2, 0xfe8)
167
+REG32(PID3, 0xfec)
168
+REG32(CID0, 0xff0)
169
+REG32(CID1, 0xff4)
170
+REG32(CID2, 0xff8)
171
+REG32(CID3, 0xffc)
172
+
173
+/* PID/CID values */
174
+static const int watchdog_id[] = {
175
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
176
+ 0x24, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
177
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
178
+};
179
+
180
+static bool cmsdk_apb_watchdog_intstatus(CMSDKAPBWatchdog *s)
181
+{
182
+ /* Return masked interrupt status */
183
+ return s->intstatus && (s->control & R_WDOGCONTROL_INTEN_MASK);
184
+}
185
+
186
+static bool cmsdk_apb_watchdog_resetstatus(CMSDKAPBWatchdog *s)
187
+{
188
+ /* Return masked reset status */
189
+ return s->resetstatus && (s->control & R_WDOGCONTROL_RESEN_MASK);
190
+}
191
+
192
+static void cmsdk_apb_watchdog_update(CMSDKAPBWatchdog *s)
193
+{
194
+ bool wdogint;
195
+ bool wdogres;
196
+
197
+ if (s->itcr) {
198
+ wdogint = s->itop & R_WDOGITOP_WDOGINT_MASK;
199
+ wdogres = s->itop & R_WDOGITOP_WDOGRES_MASK;
200
+ } else {
201
+ wdogint = cmsdk_apb_watchdog_intstatus(s);
202
+ wdogres = cmsdk_apb_watchdog_resetstatus(s);
203
+ }
204
+
205
+ qemu_set_irq(s->wdogint, wdogint);
206
+ if (wdogres) {
207
+ watchdog_perform_action();
208
+ }
209
+}
210
+
211
+static uint64_t cmsdk_apb_watchdog_read(void *opaque, hwaddr offset,
212
+ unsigned size)
213
+{
214
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
215
+ uint64_t r;
156
+
216
+
157
+ switch (offset) {
217
+ switch (offset) {
158
+ case 0x0: /* rng_ctrl */
218
+ case A_WDOGLOAD:
159
+ res = s->rng_ctrl;
219
+ r = ptimer_get_limit(s->timer);
160
+ break;
220
+ break;
161
+ case 0x4: /* rng_status */
221
+ case A_WDOGVALUE:
162
+ res = s->rng_status | (1 << 24);
222
+ r = ptimer_get_count(s->timer);
163
+ break;
223
+ break;
164
+ case 0x8: /* rng_data */
224
+ case A_WDOGCONTROL:
165
+ res = rand();
225
+ r = s->control;
166
+ break;
226
+ break;
167
+
227
+ case A_WDOGRIS:
228
+ r = s->intstatus;
229
+ break;
230
+ case A_WDOGMIS:
231
+ r = cmsdk_apb_watchdog_intstatus(s);
232
+ break;
233
+ case A_WDOGLOCK:
234
+ r = s->lock;
235
+ break;
236
+ case A_WDOGITCR:
237
+ r = s->itcr;
238
+ break;
239
+ case A_PID4 ... A_CID3:
240
+ r = watchdog_id[(offset - A_PID4) / 4];
241
+ break;
242
+ case A_WDOGINTCLR:
243
+ case A_WDOGITOP:
244
+ qemu_log_mask(LOG_GUEST_ERROR,
245
+ "CMSDK APB watchdog read: read of WO offset %x\n",
246
+ (int)offset);
247
+ r = 0;
248
+ break;
168
+ default:
249
+ default:
169
+ qemu_log_mask(LOG_GUEST_ERROR,
250
+ qemu_log_mask(LOG_GUEST_ERROR,
170
+ "bcm2835_rng_read: Bad offset %x\n",
251
+ "CMSDK APB watchdog read: bad offset %x\n", (int)offset);
252
+ r = 0;
253
+ break;
254
+ }
255
+ trace_cmsdk_apb_watchdog_read(offset, r, size);
256
+ return r;
257
+}
258
+
259
+static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
260
+ uint64_t value, unsigned size)
261
+{
262
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
263
+
264
+ trace_cmsdk_apb_watchdog_write(offset, value, size);
265
+
266
+ if (s->lock && offset != A_WDOGLOCK) {
267
+ /* Write access is disabled via WDOGLOCK */
268
+ qemu_log_mask(LOG_GUEST_ERROR,
269
+ "CMSDK APB watchdog write: write to locked watchdog\n");
270
+ return;
271
+ }
272
+
273
+ switch (offset) {
274
+ case A_WDOGLOAD:
275
+ /*
276
+ * Reset the load value and the current count, and make sure
277
+ * we're counting.
278
+ */
279
+ ptimer_set_limit(s->timer, value, 1);
280
+ ptimer_run(s->timer, 0);
281
+ break;
282
+ case A_WDOGCONTROL:
283
+ s->control = value & R_WDOGCONTROL_VALID_MASK;
284
+ cmsdk_apb_watchdog_update(s);
285
+ break;
286
+ case A_WDOGINTCLR:
287
+ s->intstatus = 0;
288
+ ptimer_set_count(s->timer, ptimer_get_limit(s->timer));
289
+ cmsdk_apb_watchdog_update(s);
290
+ break;
291
+ case A_WDOGLOCK:
292
+ s->lock = (value != WDOG_UNLOCK_VALUE);
293
+ break;
294
+ case A_WDOGITCR:
295
+ s->itcr = value & R_WDOGITCR_VALID_MASK;
296
+ cmsdk_apb_watchdog_update(s);
297
+ break;
298
+ case A_WDOGITOP:
299
+ s->itop = value & R_WDOGITOP_VALID_MASK;
300
+ cmsdk_apb_watchdog_update(s);
301
+ break;
302
+ case A_WDOGVALUE:
303
+ case A_WDOGRIS:
304
+ case A_WDOGMIS:
305
+ case A_PID4 ... A_CID3:
306
+ qemu_log_mask(LOG_GUEST_ERROR,
307
+ "CMSDK APB watchdog write: write to RO offset 0x%x\n",
171
+ (int)offset);
308
+ (int)offset);
172
+ res = 0;
309
+ break;
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:
310
+ default:
197
+ qemu_log_mask(LOG_GUEST_ERROR,
311
+ qemu_log_mask(LOG_GUEST_ERROR,
198
+ "bcm2835_rng_write: Bad offset %x\n",
312
+ "CMSDK APB watchdog write: bad offset 0x%x\n",
199
+ (int)offset);
313
+ (int)offset);
200
+ break;
314
+ break;
201
+ }
315
+ }
202
+}
316
+}
203
+
317
+
204
+static const MemoryRegionOps bcm2835_rng_ops = {
318
+static const MemoryRegionOps cmsdk_apb_watchdog_ops = {
205
+ .read = bcm2835_rng_read,
319
+ .read = cmsdk_apb_watchdog_read,
206
+ .write = bcm2835_rng_write,
320
+ .write = cmsdk_apb_watchdog_write,
207
+ .endianness = DEVICE_NATIVE_ENDIAN,
321
+ .endianness = DEVICE_LITTLE_ENDIAN,
322
+ /* byte/halfword accesses are just zero-padded on reads and writes */
323
+ .impl.min_access_size = 4,
324
+ .impl.max_access_size = 4,
325
+ .valid.min_access_size = 1,
326
+ .valid.max_access_size = 4,
208
+};
327
+};
209
+
328
+
210
+static const VMStateDescription vmstate_bcm2835_rng = {
329
+static void cmsdk_apb_watchdog_tick(void *opaque)
211
+ .name = TYPE_BCM2835_RNG,
330
+{
331
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
332
+
333
+ if (!s->intstatus) {
334
+ /* Count expired for the first time: raise interrupt */
335
+ s->intstatus = R_WDOGRIS_INT_MASK;
336
+ } else {
337
+ /* Count expired for the second time: raise reset and stop clock */
338
+ s->resetstatus = 1;
339
+ ptimer_stop(s->timer);
340
+ }
341
+ cmsdk_apb_watchdog_update(s);
342
+}
343
+
344
+static void cmsdk_apb_watchdog_reset(DeviceState *dev)
345
+{
346
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
347
+
348
+ trace_cmsdk_apb_watchdog_reset();
349
+ s->control = 0;
350
+ s->intstatus = 0;
351
+ s->lock = 0;
352
+ s->itcr = 0;
353
+ s->itop = 0;
354
+ s->resetstatus = 0;
355
+ /* Set the limit and the count */
356
+ ptimer_set_limit(s->timer, 0xffffffff, 1);
357
+ ptimer_run(s->timer, 0);
358
+}
359
+
360
+static void cmsdk_apb_watchdog_init(Object *obj)
361
+{
362
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
363
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(obj);
364
+
365
+ memory_region_init_io(&s->iomem, obj, &cmsdk_apb_watchdog_ops,
366
+ s, "cmsdk-apb-watchdog", 0x1000);
367
+ sysbus_init_mmio(sbd, &s->iomem);
368
+ sysbus_init_irq(sbd, &s->wdogint);
369
+}
370
+
371
+static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
372
+{
373
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
374
+ QEMUBH *bh;
375
+
376
+ if (s->wdogclk_frq == 0) {
377
+ error_setg(errp,
378
+ "CMSDK APB watchdog: wdogclk-frq property must be set");
379
+ return;
380
+ }
381
+
382
+ bh = qemu_bh_new(cmsdk_apb_watchdog_tick, s);
383
+ s->timer = ptimer_init(bh,
384
+ PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
385
+ PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
386
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
387
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
388
+
389
+ ptimer_set_freq(s->timer, s->wdogclk_frq);
390
+}
391
+
392
+static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
393
+ .name = "cmsdk-apb-watchdog",
212
+ .version_id = 1,
394
+ .version_id = 1,
213
+ .minimum_version_id = 1,
395
+ .minimum_version_id = 1,
214
+ .fields = (VMStateField[]) {
396
+ .fields = (VMStateField[]) {
215
+ VMSTATE_UINT32(rng_ctrl, BCM2835RngState),
397
+ VMSTATE_PTIMER(timer, CMSDKAPBWatchdog),
216
+ VMSTATE_UINT32(rng_status, BCM2835RngState),
398
+ VMSTATE_UINT32(control, CMSDKAPBWatchdog),
399
+ VMSTATE_UINT32(intstatus, CMSDKAPBWatchdog),
400
+ VMSTATE_UINT32(lock, CMSDKAPBWatchdog),
401
+ VMSTATE_UINT32(itcr, CMSDKAPBWatchdog),
402
+ VMSTATE_UINT32(itop, CMSDKAPBWatchdog),
403
+ VMSTATE_UINT32(resetstatus, CMSDKAPBWatchdog),
217
+ VMSTATE_END_OF_LIST()
404
+ VMSTATE_END_OF_LIST()
218
+ }
405
+ }
219
+};
406
+};
220
+
407
+
221
+static void bcm2835_rng_init(Object *obj)
408
+static Property cmsdk_apb_watchdog_properties[] = {
222
+{
409
+ DEFINE_PROP_UINT32("wdogclk-frq", CMSDKAPBWatchdog, wdogclk_frq, 0),
223
+ BCM2835RngState *s = BCM2835_RNG(obj);
410
+ DEFINE_PROP_END_OF_LIST(),
224
+
411
+};
225
+ memory_region_init_io(&s->iomem, obj, &bcm2835_rng_ops, s,
412
+
226
+ TYPE_BCM2835_RNG, 0x10);
413
+static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
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
+{
414
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
415
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
416
+
242
+ dc->reset = bcm2835_rng_reset;
417
+ dc->realize = cmsdk_apb_watchdog_realize;
243
+ dc->vmsd = &vmstate_bcm2835_rng;
418
+ dc->vmsd = &cmsdk_apb_watchdog_vmstate;
244
+}
419
+ dc->reset = cmsdk_apb_watchdog_reset;
245
+
420
+ dc->props = cmsdk_apb_watchdog_properties;
246
+static TypeInfo bcm2835_rng_info = {
421
+}
247
+ .name = TYPE_BCM2835_RNG,
422
+
248
+ .parent = TYPE_SYS_BUS_DEVICE,
423
+static const TypeInfo cmsdk_apb_watchdog_info = {
249
+ .instance_size = sizeof(BCM2835RngState),
424
+ .name = TYPE_CMSDK_APB_WATCHDOG,
250
+ .class_init = bcm2835_rng_class_init,
425
+ .parent = TYPE_SYS_BUS_DEVICE,
251
+ .instance_init = bcm2835_rng_init,
426
+ .instance_size = sizeof(CMSDKAPBWatchdog),
427
+ .instance_init = cmsdk_apb_watchdog_init,
428
+ .class_init = cmsdk_apb_watchdog_class_init,
252
+};
429
+};
253
+
430
+
254
+static void bcm2835_rng_register_types(void)
431
+static void cmsdk_apb_watchdog_register_types(void)
255
+{
432
+{
256
+ type_register_static(&bcm2835_rng_info);
433
+ type_register_static(&cmsdk_apb_watchdog_info);
257
+}
434
+}
258
+
435
+
259
+type_init(bcm2835_rng_register_types)
436
+type_init(cmsdk_apb_watchdog_register_types);
437
diff --git a/MAINTAINERS b/MAINTAINERS
438
index XXXXXXX..XXXXXXX 100644
439
--- a/MAINTAINERS
440
+++ b/MAINTAINERS
441
@@ -XXX,XX +XXX,XX @@ F: hw/timer/cmsdk-apb-timer.c
442
F: include/hw/timer/cmsdk-apb-timer.h
443
F: hw/char/cmsdk-apb-uart.c
444
F: include/hw/char/cmsdk-apb-uart.h
445
+F: hw/watchdog/cmsdk-apb-watchdog.c
446
+F: include/hw/watchdog/cmsdk-apb-watchdog.h
447
F: hw/misc/tz-ppc.c
448
F: include/hw/misc/tz-ppc.h
449
F: hw/misc/tz-mpc.c
450
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
451
index XXXXXXX..XXXXXXX 100644
452
--- a/default-configs/arm-softmmu.mak
453
+++ b/default-configs/arm-softmmu.mak
454
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
455
456
CONFIG_CMSDK_APB_TIMER=y
457
CONFIG_CMSDK_APB_UART=y
458
+CONFIG_CMSDK_APB_WATCHDOG=y
459
460
CONFIG_MPS2_FPGAIO=y
461
CONFIG_MPS2_SCC=y
462
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
463
new file mode 100644
464
index XXXXXXX..XXXXXXX
465
--- /dev/null
466
+++ b/hw/watchdog/trace-events
467
@@ -XXX,XX +XXX,XX @@
468
+# See docs/devel/tracing.txt for syntax documentation.
469
+
470
+# hw/char/cmsdk_apb_watchdog.c
471
+cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
472
+cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
473
+cmsdk_apb_watchdog_reset(void) "CMSDK APB watchdog: reset"
260
--
474
--
261
2.7.4
475
2.18.0
262
476
263
477
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
On real v7M hardware, the NMI line is an externally visible signal
2
that an SoC or board can toggle to assert an NMI. Expose it in
3
our QEMU NVIC and armv7m container objects so that a board model
4
can wire it up if it needs to.
2
5
3
Despite some superficial similarities of register layout, the
6
In particular, the MPS2 watchdog is wired to NMI.
4
M-profile NVIC is really very different from the A-profile GIC.
5
Our current attempt to reuse the GIC code means that we have
6
significant bugs in our NVIC.
7
7
8
Implement the NVIC as an entirely separate device, to give
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
us somewhere we can get the behaviour correct.
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
---
11
hw/arm/armv7m.c | 1 +
12
hw/intc/armv7m_nvic.c | 19 +++++++++++++++++++
13
hw/intc/trace-events | 1 +
14
3 files changed, 21 insertions(+)
10
15
11
This initial commit does not attempt to implement exception
16
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
12
priority escalation, since the GIC-based code didn't either.
17
index XXXXXXX..XXXXXXX 100644
13
It does fix a few bugs in passing:
18
--- a/hw/arm/armv7m.c
14
* ICSR.RETTOBASE polarity was wrong and didn't account for
19
+++ b/hw/arm/armv7m.c
15
internal exceptions
20
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
16
* ICSR.VECTPENDING was 16 too high if the pending exception
21
*/
17
was for an external interrupt
22
qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
18
* UsageFault, BusFault and MemFault were not disabled on reset
23
qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
19
as they are supposed to be
24
+ qdev_pass_gpios(DEVICE(&s->nvic), dev, "NMI");
20
25
21
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
26
/* Wire the NVIC up to the CPU */
22
[PMM: reworked, various bugs and stylistic cleanups]
27
sbd = SYS_BUS_DEVICE(&s->nvic);
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
28
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
31
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/intc/armv7m_nvic.c
30
--- a/hw/intc/armv7m_nvic.c
33
+++ b/hw/intc/armv7m_nvic.c
31
+++ b/hw/intc/armv7m_nvic.c
34
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@ static void set_irq_level(void *opaque, int n, int level)
35
#include "hw/sysbus.h"
33
}
36
#include "qemu/timer.h"
34
}
37
#include "hw/arm/arm.h"
35
38
+#include "target/arm/cpu.h"
36
+/* callback when external NMI line is changed */
39
#include "exec/address-spaces.h"
37
+static void nvic_nmi_trigger(void *opaque, int n, int level)
40
-#include "gic_internal.h"
38
+{
41
#include "qemu/log.h"
39
+ NVICState *s = opaque;
42
+#include "trace.h"
43
+
40
+
44
+/* IRQ number counting:
41
+ trace_nvic_set_nmi_level(level);
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
+
42
+
72
+/* Effective running priority of the CPU when no exception is active
43
+ /*
73
+ * (higher than the highest possible priority value)
44
+ * The architecture doesn't specify whether NMI should share
74
+ */
45
+ * the normal-interrupt behaviour of being resampled on
75
+#define NVIC_NOEXC_PRIO 0x100
46
+ * exception handler return. We choose not to, so just
76
+
47
+ * set NMI pending here and don't track the current level.
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
+ */
48
+ */
81
+ int16_t prio;
49
+ if (level) {
82
+ uint8_t enabled;
50
+ armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI, false);
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
}
147
148
-/* The external routines use the hardware vector numbering, ie. the first
149
- IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
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
+ }
51
+ }
319
+}
52
+}
320
+
53
+
321
void armv7m_nvic_set_pending(void *opaque, int irq)
54
static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
322
{
323
NVICState *s = (NVICState *)opaque;
324
- if (irq >= 16)
325
- irq += 16;
326
- gic_set_pending_private(&s->gic, 0, irq);
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
}
338
339
/* Make pending IRQ active. */
340
int armv7m_nvic_acknowledge_irq(void *opaque)
341
{
342
NVICState *s = (NVICState *)opaque;
343
- uint32_t irq;
344
-
345
- irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
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
}
378
379
void armv7m_nvic_complete_irq(void *opaque, int irq)
380
{
381
NVICState *s = (NVICState *)opaque;
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
}
432
433
static uint32_t nvic_readl(NVICState *s, uint32_t offset)
434
{
55
{
435
ARMCPU *cpu = s->cpu;
56
ARMCPU *cpu = s->cpu;
436
uint32_t val;
57
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
437
- int irq;
58
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
438
59
qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger",
439
switch (offset) {
60
M_REG_NUM_BANKS);
440
case 4: /* Interrupt Control Type. */
61
+ qdev_init_gpio_in_named(dev, nvic_nmi_trigger, "NMI", 1);
441
- return (s->num_irq / 32) - 1;
442
+ return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
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
{
618
NVICState *s = (NVICState *)opaque;
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
}
62
}
706
63
707
static void nvic_sysreg_write(void *opaque, hwaddr addr,
708
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
709
{
710
NVICState *s = (NVICState *)opaque;
711
uint32_t offset = addr;
712
- int i;
713
+ unsigned i, startvec, end;
714
+ unsigned setval = 0;
715
+
716
+ trace_nvic_sysreg_write(addr, value, size);
717
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
{
837
NVICState *s = NVIC(dev);
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
}
874
875
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
876
{
877
NVICState *s = NVIC(dev);
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
}
958
959
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
64
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
960
{
961
- NVICClass *nc = NVIC_CLASS(klass);
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
}
971
972
static const TypeInfo armv7m_nvic_info = {
973
.name = TYPE_NVIC,
974
- .parent = TYPE_ARM_GIC_COMMON,
975
+ .parent = TYPE_SYS_BUS_DEVICE,
976
.instance_init = armv7m_nvic_instance_init,
977
.instance_size = sizeof(NVICState),
978
.class_init = armv7m_nvic_class_init,
979
- .class_size = sizeof(NVICClass),
980
+ .class_size = sizeof(SysBusDeviceClass),
981
};
982
983
static void armv7m_nvic_register_types(void)
984
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
65
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
985
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
986
--- a/hw/intc/trace-events
67
--- a/hw/intc/trace-events
987
+++ b/hw/intc/trace-events
68
+++ b/hw/intc/trace-events
988
@@ -XXX,XX +XXX,XX @@ gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size,
69
@@ -XXX,XX +XXX,XX @@ nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (pr
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"
70
nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
990
gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor %x interrupt %d level changed to %d"
71
nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
991
gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor %x pending SGI %d"
72
nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
992
+
73
+nvic_set_nmi_level(int level) "NVIC external NMI level set to %d"
993
+# hw/intc/armv7m_nvic.c
74
nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
994
+nvic_recompute_state(int vectpending, int exception_prio) "NVIC state recomputed: vectpending %d exception_prio %d"
75
nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
995
+nvic_set_prio(int irq, uint8_t prio) "NVIC set irq %d priority %d"
76
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"
997
+nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
998
+nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
999
+nvic_set_pending(int irq, int en, int prio) "NVIC set pending irq %d (enabled: %d priority %d)"
1000
+nvic_clear_pending(int irq, int en, int prio) "NVIC clear pending irq %d (enabled: %d priority %d)"
1001
+nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
1002
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
1003
+nvic_complete_irq(int irq) "NVIC complete IRQ %d"
1004
+nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
1005
+nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1006
+nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1007
--
77
--
1008
2.7.4
78
2.18.0
1009
79
1010
80
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
Create a new include file for the pl081's device struct,
2
type macros, etc, so that it can be instantiated using
3
the "embedded struct" coding style.
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é <f4bug@amsat.org>
7
---
8
include/hw/dma/pl080.h | 62 ++++++++++++++++++++++++++++++++++++++++++
9
hw/dma/pl080.c | 34 ++---------------------
10
MAINTAINERS | 1 +
11
3 files changed, 65 insertions(+), 32 deletions(-)
12
create mode 100644 include/hw/dma/pl080.h
4
13
5
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
14
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
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
19
--- a/hw/sd/Makefile.objs
20
+++ b/hw/sd/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SDHCI) += sdhci.o
22
obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
23
obj-$(CONFIG_OMAP) += omap_mmc.o
24
obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
25
+obj-$(CONFIG_RASPI) += bcm2835_sdhost.o
26
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
27
new file mode 100644
15
new file mode 100644
28
index XXXXXXX..XXXXXXX
16
index XXXXXXX..XXXXXXX
29
--- /dev/null
17
--- /dev/null
30
+++ b/include/hw/sd/bcm2835_sdhost.h
18
+++ b/include/hw/dma/pl080.h
31
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
32
+/*
20
+/*
33
+ * Raspberry Pi (BCM2835) SD Host Controller
21
+ * ARM PrimeCell PL080/PL081 DMA controller
34
+ *
22
+ *
35
+ * Copyright (c) 2017 Antfield SAS
23
+ * Copyright (c) 2006 CodeSourcery.
24
+ * Copyright (c) 2018 Linaro Limited
25
+ * Written by Paul Brook, Peter Maydell
36
+ *
26
+ *
37
+ * Authors:
27
+ * This program is free software; you can redistribute it and/or modify
38
+ * Clement Deschamps <clement.deschamps@antfield.fr>
28
+ * it under the terms of the GNU General Public License version 2 or
39
+ * Luc Michel <luc.michel@antfield.fr>
29
+ * (at your option) any later version.
40
+ *
41
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
42
+ * See the COPYING file in the top-level directory.
43
+ */
30
+ */
44
+
31
+
45
+#ifndef BCM2835_SDHOST_H
32
+/* This is a model of the Arm PrimeCell PL080/PL081 DMA controller:
46
+#define BCM2835_SDHOST_H
33
+ * The PL080 TRM is:
34
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0196g/DDI0196.pdf
35
+ * and the PL081 TRM is:
36
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0218e/DDI0218.pdf
37
+ *
38
+ * QEMU interface:
39
+ * + sysbus IRQ: DMACINTR combined interrupt line
40
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
41
+ */
42
+
43
+#ifndef HW_DMA_PL080_H
44
+#define HW_DMA_PL080_H
47
+
45
+
48
+#include "hw/sysbus.h"
46
+#include "hw/sysbus.h"
49
+#include "hw/sd/sd.h"
50
+
47
+
51
+#define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
48
+#define PL080_MAX_CHANNELS 8
52
+#define BCM2835_SDHOST(obj) \
53
+ OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST)
54
+
55
+#define BCM2835_SDHOST_FIFO_LEN 16
56
+
49
+
57
+typedef struct {
50
+typedef struct {
58
+ SysBusDevice busdev;
51
+ uint32_t src;
59
+ SDBus sdbus;
52
+ uint32_t dest;
53
+ uint32_t lli;
54
+ uint32_t ctrl;
55
+ uint32_t conf;
56
+} pl080_channel;
57
+
58
+#define TYPE_PL080 "pl080"
59
+#define TYPE_PL081 "pl081"
60
+#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080)
61
+
62
+typedef struct PL080State {
63
+ SysBusDevice parent_obj;
64
+
60
+ MemoryRegion iomem;
65
+ MemoryRegion iomem;
61
+
66
+ uint8_t tc_int;
62
+ uint32_t cmd;
67
+ uint8_t tc_mask;
63
+ uint32_t cmdarg;
68
+ uint8_t err_int;
64
+ uint32_t status;
69
+ uint8_t err_mask;
65
+ uint32_t rsp[4];
70
+ uint32_t conf;
66
+ uint32_t config;
71
+ uint32_t sync;
67
+ uint32_t edm;
72
+ uint32_t req_single;
68
+ uint32_t vdd;
73
+ uint32_t req_burst;
69
+ uint32_t hbct;
74
+ pl080_channel chan[PL080_MAX_CHANNELS];
70
+ uint32_t hblc;
75
+ int nchannels;
71
+ int32_t fifo_pos;
76
+ /* Flag to avoid recursive DMA invocations. */
72
+ int32_t fifo_len;
77
+ int running;
73
+ uint32_t fifo[BCM2835_SDHOST_FIFO_LEN];
74
+ uint32_t datacnt;
75
+
76
+ qemu_irq irq;
78
+ qemu_irq irq;
77
+} BCM2835SDHostState;
79
+} PL080State;
78
+
80
+
79
+#endif
81
+#endif
80
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
82
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
81
new file mode 100644
83
index XXXXXXX..XXXXXXX 100644
82
index XXXXXXX..XXXXXXX
84
--- a/hw/dma/pl080.c
83
--- /dev/null
85
+++ b/hw/dma/pl080.c
84
+++ b/hw/sd/bcm2835_sdhost.c
85
@@ -XXX,XX +XXX,XX @@
86
@@ -XXX,XX +XXX,XX @@
86
+/*
87
#include "hw/sysbus.h"
87
+ * Raspberry Pi (BCM2835) SD Host Controller
88
#include "exec/address-spaces.h"
88
+ *
89
#include "qemu/log.h"
89
+ * Copyright (c) 2017 Antfield SAS
90
+#include "hw/dma/pl080.h"
90
+ *
91
91
+ * Authors:
92
-#define PL080_MAX_CHANNELS 8
92
+ * Clement Deschamps <clement.deschamps@antfield.fr>
93
#define PL080_CONF_E 0x1
93
+ * Luc Michel <luc.michel@antfield.fr>
94
#define PL080_CONF_M1 0x2
94
+ *
95
#define PL080_CONF_M2 0x4
95
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
96
@@ -XXX,XX +XXX,XX @@
96
+ * See the COPYING file in the top-level directory.
97
#define PL080_CCTRL_D 0x02000000
97
+ */
98
#define PL080_CCTRL_S 0x01000000
98
+
99
99
+#include "qemu/osdep.h"
100
-typedef struct {
100
+#include "qemu/log.h"
101
- uint32_t src;
101
+#include "sysemu/blockdev.h"
102
- uint32_t dest;
102
+#include "hw/sd/bcm2835_sdhost.h"
103
- uint32_t lli;
103
+
104
- uint32_t ctrl;
104
+#define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus"
105
- uint32_t conf;
105
+#define BCM2835_SDHOST_BUS(obj) \
106
-} pl080_channel;
106
+ OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS)
107
-
107
+
108
-#define TYPE_PL080 "pl080"
108
+#define SDCMD 0x00 /* Command to SD card - 16 R/W */
109
-#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080)
109
+#define SDARG 0x04 /* Argument to SD card - 32 R/W */
110
-
110
+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
111
-typedef struct PL080State {
111
+#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
112
- SysBusDevice parent_obj;
112
+#define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */
113
-
113
+#define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */
114
- MemoryRegion iomem;
114
+#define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */
115
- uint8_t tc_int;
115
+#define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */
116
- uint8_t tc_mask;
116
+#define SDHSTS 0x20 /* SD host status - 11 R */
117
- uint8_t err_int;
117
+#define SDVDD 0x30 /* SD card power control - 1 R/W */
118
- uint8_t err_mask;
118
+#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
119
- uint32_t conf;
119
+#define SDHCFG 0x38 /* Host configuration - 2 R/W */
120
- uint32_t sync;
120
+#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
121
- uint32_t req_single;
121
+#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
122
- uint32_t req_burst;
122
+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
123
- pl080_channel chan[PL080_MAX_CHANNELS];
123
+
124
- int nchannels;
124
+#define SDCMD_NEW_FLAG 0x8000
125
- /* Flag to avoid recursive DMA invocations. */
125
+#define SDCMD_FAIL_FLAG 0x4000
126
- int running;
126
+#define SDCMD_BUSYWAIT 0x800
127
- qemu_irq irq;
127
+#define SDCMD_NO_RESPONSE 0x400
128
-} PL080State;
128
+#define SDCMD_LONG_RESPONSE 0x200
129
-
129
+#define SDCMD_WRITE_CMD 0x80
130
static const VMStateDescription vmstate_pl080_channel = {
130
+#define SDCMD_READ_CMD 0x40
131
.name = "pl080_channel",
131
+#define SDCMD_CMD_MASK 0x3f
132
.version_id = 1,
132
+
133
@@ -XXX,XX +XXX,XX @@ static const TypeInfo pl080_info = {
133
+#define SDCDIV_MAX_CDIV 0x7ff
134
};
134
+
135
135
+#define SDHSTS_BUSY_IRPT 0x400
136
static const TypeInfo pl081_info = {
136
+#define SDHSTS_BLOCK_IRPT 0x200
137
- .name = "pl081",
137
+#define SDHSTS_SDIO_IRPT 0x100
138
+ .name = TYPE_PL081,
138
+#define SDHSTS_REW_TIME_OUT 0x80
139
.parent = TYPE_PL080,
139
+#define SDHSTS_CMD_TIME_OUT 0x40
140
.instance_init = pl081_init,
140
+#define SDHSTS_CRC16_ERROR 0x20
141
};
141
+#define SDHSTS_CRC7_ERROR 0x10
142
diff --git a/MAINTAINERS b/MAINTAINERS
142
+#define SDHSTS_FIFO_ERROR 0x08
143
index XXXXXXX..XXXXXXX 100644
143
+/* Reserved */
144
--- a/MAINTAINERS
144
+/* Reserved */
145
+++ b/MAINTAINERS
145
+#define SDHSTS_DATA_FLAG 0x01
146
@@ -XXX,XX +XXX,XX @@ F: hw/char/pl011.c
146
+
147
F: include/hw/char/pl011.h
147
+#define SDHCFG_BUSY_IRPT_EN (1 << 10)
148
F: hw/display/pl110*
148
+#define SDHCFG_BLOCK_IRPT_EN (1 << 8)
149
F: hw/dma/pl080.c
149
+#define SDHCFG_SDIO_IRPT_EN (1 << 5)
150
+F: include/hw/dma/pl080.h
150
+#define SDHCFG_DATA_IRPT_EN (1 << 4)
151
F: hw/dma/pl330.c
151
+#define SDHCFG_SLOW_CARD (1 << 3)
152
F: hw/gpio/pl061.c
152
+#define SDHCFG_WIDE_EXT_BUS (1 << 2)
153
F: hw/input/pl050.c
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
--
154
--
516
2.7.4
155
2.18.0
517
156
518
157
diff view generated by jsdifflib
1
From: Kurban Mallachiev <mallachiev@ispras.ru>
1
The PL080 and PL081 have three outgoing interrupt lines:
2
* DMACINTERR signals DMA errors
3
* DMACINTTC is the DMA count interrupt
4
* DMACINTR is a combined interrupt, the logical OR of the other two
2
5
3
The i.MX timer device can be reset by writing to the SWR bit
6
We currently only implement DMACINTR, because that's all the
4
of the CR register. This has to behave differently from hard
7
realview and versatile boards needed, but the instances of the
5
(power-on) reset because it does not reset all of the bits
8
PL081 in the MPS2 firmware images use all three interrupt lines.
6
in the CR register.
9
Implement the missing DMACINTERR and DMACINTTC.
7
10
8
We were incorrectly implementing soft reset and hard reset
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
the same way, and in addition had a logic error which meant
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
that we were clearing the bits that soft-reset is supposed
13
---
11
to preserve and not touching the bits that soft-reset clears.
14
include/hw/dma/pl080.h | 6 +++++-
12
This was not correct behaviour for either kind of reset.
15
hw/dma/pl080.c | 13 ++++++++-----
16
2 files changed, 13 insertions(+), 6 deletions(-)
13
17
14
Separate out the soft reset and hard reset code paths, and
18
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
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
19
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/timer/imx_gpt.c
20
--- a/include/hw/dma/pl080.h
30
+++ b/hw/timer/imx_gpt.c
21
+++ b/include/hw/dma/pl080.h
31
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
22
@@ -XXX,XX +XXX,XX @@
32
return reg_value;
23
* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0218e/DDI0218.pdf
24
*
25
* QEMU interface:
26
- * + sysbus IRQ: DMACINTR combined interrupt line
27
+ * + sysbus IRQ 0: DMACINTR combined interrupt line
28
+ * + sysbus IRQ 1: DMACINTERR error interrupt request
29
+ * + sysbus IRQ 2: DMACINTTC count interrupt request
30
* + sysbus MMIO region 0: MemoryRegion for the device's registers
31
*/
32
33
@@ -XXX,XX +XXX,XX @@ typedef struct PL080State {
34
/* Flag to avoid recursive DMA invocations. */
35
int running;
36
qemu_irq irq;
37
+ qemu_irq interr;
38
+ qemu_irq inttc;
39
} PL080State;
40
41
#endif
42
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/dma/pl080.c
45
+++ b/hw/dma/pl080.c
46
@@ -XXX,XX +XXX,XX @@ static const unsigned char pl081_id[] =
47
48
static void pl080_update(PL080State *s)
49
{
50
- if ((s->tc_int & s->tc_mask)
51
- || (s->err_int & s->err_mask))
52
- qemu_irq_raise(s->irq);
53
- else
54
- qemu_irq_lower(s->irq);
55
+ bool tclevel = (s->tc_int & s->tc_mask);
56
+ bool errlevel = (s->err_int & s->err_mask);
57
+
58
+ qemu_set_irq(s->interr, errlevel);
59
+ qemu_set_irq(s->inttc, tclevel);
60
+ qemu_set_irq(s->irq, errlevel || tclevel);
33
}
61
}
34
62
35
-static void imx_gpt_reset(DeviceState *dev)
63
static void pl080_run(PL080State *s)
36
-{
64
@@ -XXX,XX +XXX,XX @@ static void pl080_init(Object *obj)
37
- IMXGPTState *s = IMX_GPT(dev);
65
memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
38
66
sysbus_init_mmio(sbd, &s->iomem);
39
+static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
67
sysbus_init_irq(sbd, &s->irq);
40
+{
68
+ sysbus_init_irq(sbd, &s->interr);
41
/* stop timer */
69
+ sysbus_init_irq(sbd, &s->inttc);
42
ptimer_stop(s->timer);
70
s->nchannels = 8;
43
44
- /*
45
- * Soft reset doesn't touch some bits; hard reset clears them
46
+ /* Soft reset and hard reset differ only in their handling of the CR
47
+ * register -- soft reset preserves the values of some bits there.
48
*/
49
- s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
50
- GPT_CR_WAITEN|GPT_CR_DBGEN);
51
+ if (is_soft_reset) {
52
+ /* Clear all CR bits except those that are preserved by soft reset. */
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
}
71
}
65
72
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
--
73
--
91
2.7.4
74
2.18.0
92
75
93
76
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
Currently our PL080/PL081 model uses a combination of the CPU's
2
address space (via cpu_physical_memory_{read,write}()) and the
3
system address space for performing DMA accesses.
2
4
3
Provide a new function sdbus_reparent_card() in sd core for reparenting
5
For the PL081s in the MPS FPGA images, their DMA accesses
4
a card from a SDBus to another one.
6
must go via Master Security Controllers. Switch the
7
PL080/PL081 model to take a MemoryRegion property which
8
defines its downstream for making DMA accesses.
5
9
6
This function is required by the raspi platform, where the two SD
10
Since the PL08x are only used in two board models, we
7
controllers can be dynamically switched.
11
make provision of the 'downstream' link mandatory and convert
12
both users at once, rather than having it be optional with
13
a default to the system address space.
8
14
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>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
---
17
---
15
include/hw/sd/sd.h | 11 +++++++++++
18
include/hw/dma/pl080.h | 5 +++++
16
hw/sd/core.c | 30 ++++++++++++++++++++++++++++++
19
hw/arm/realview.c | 8 +++++++-
17
2 files changed, 41 insertions(+)
20
hw/arm/versatilepb.c | 9 ++++++++-
21
hw/dma/pl080.c | 35 +++++++++++++++++++++++++++++------
22
4 files changed, 49 insertions(+), 8 deletions(-)
18
23
19
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
24
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
20
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/sd/sd.h
26
--- a/include/hw/dma/pl080.h
22
+++ b/include/hw/sd/sd.h
27
+++ b/include/hw/dma/pl080.h
23
@@ -XXX,XX +XXX,XX @@ uint8_t sdbus_read_data(SDBus *sd);
28
@@ -XXX,XX +XXX,XX @@
24
bool sdbus_data_ready(SDBus *sd);
29
* + sysbus IRQ 1: DMACINTERR error interrupt request
25
bool sdbus_get_inserted(SDBus *sd);
30
* + sysbus IRQ 2: DMACINTTC count interrupt request
26
bool sdbus_get_readonly(SDBus *sd);
31
* + sysbus MMIO region 0: MemoryRegion for the device's registers
27
+/**
32
+ * + QOM property "downstream": MemoryRegion defining where DMA
28
+ * sdbus_reparent_card: Reparent an SD card from one controller to another
33
+ * bus master transactions are made
29
+ * @from: controller bus to remove card from
34
*/
30
+ * @to: controller bus to move card to
35
31
+ *
36
#ifndef HW_DMA_PL080_H
32
+ * Reparent an SD card, effectively unplugging it from one controller
37
@@ -XXX,XX +XXX,XX @@ typedef struct PL080State {
33
+ * and inserting it into another. This is useful for SoCs like the
38
qemu_irq irq;
34
+ * bcm2835 which have two SD controllers and connect a single SD card
39
qemu_irq interr;
35
+ * to them, selected by the guest reprogramming GPIO line routing.
40
qemu_irq inttc;
36
+ */
41
+
37
+void sdbus_reparent_card(SDBus *from, SDBus *to);
42
+ MemoryRegion *downstream;
38
43
+ AddressSpace downstream_as;
39
/* Functions to be used by SD devices to report back to qdevified controllers */
44
} PL080State;
40
void sdbus_set_inserted(SDBus *sd, bool inserted);
45
41
diff --git a/hw/sd/core.c b/hw/sd/core.c
46
#endif
47
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
42
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/sd/core.c
49
--- a/hw/arm/realview.c
44
+++ b/hw/sd/core.c
50
+++ b/hw/arm/realview.c
45
@@ -XXX,XX +XXX,XX @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly)
51
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
46
}
52
pl011_create(0x1000c000, pic[15], serial_hd(3));
53
54
/* DMA controller is optional, apparently. */
55
- sysbus_create_simple("pl081", 0x10030000, pic[24]);
56
+ dev = qdev_create(NULL, "pl081");
57
+ object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream",
58
+ &error_fatal);
59
+ qdev_init_nofail(dev);
60
+ busdev = SYS_BUS_DEVICE(dev);
61
+ sysbus_mmio_map(busdev, 0, 0x10030000);
62
+ sysbus_connect_irq(busdev, 0, pic[24]);
63
64
sysbus_create_simple("sp804", 0x10011000, pic[4]);
65
sysbus_create_simple("sp804", 0x10012000, pic[5]);
66
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/versatilepb.c
69
+++ b/hw/arm/versatilepb.c
70
@@ -XXX,XX +XXX,XX @@ static void versatile_init(MachineState *machine, int board_id)
71
pl011_create(0x101f3000, pic[14], serial_hd(2));
72
pl011_create(0x10009000, sic[6], serial_hd(3));
73
74
- sysbus_create_simple("pl080", 0x10130000, pic[17]);
75
+ dev = qdev_create(NULL, "pl080");
76
+ object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream",
77
+ &error_fatal);
78
+ qdev_init_nofail(dev);
79
+ busdev = SYS_BUS_DEVICE(dev);
80
+ sysbus_mmio_map(busdev, 0, 0x10130000);
81
+ sysbus_connect_irq(busdev, 0, pic[17]);
82
+
83
sysbus_create_simple("sp804", 0x101e2000, pic[4]);
84
sysbus_create_simple("sp804", 0x101e3000, pic[5]);
85
86
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/dma/pl080.c
89
+++ b/hw/dma/pl080.c
90
@@ -XXX,XX +XXX,XX @@
91
#include "exec/address-spaces.h"
92
#include "qemu/log.h"
93
#include "hw/dma/pl080.h"
94
+#include "qapi/error.h"
95
96
#define PL080_CONF_E 0x1
97
#define PL080_CONF_M1 0x2
98
@@ -XXX,XX +XXX,XX @@ again:
99
swidth = 1 << ((ch->ctrl >> 18) & 7);
100
dwidth = 1 << ((ch->ctrl >> 21) & 7);
101
for (n = 0; n < dwidth; n+= swidth) {
102
- cpu_physical_memory_read(ch->src, buff + n, swidth);
103
+ address_space_read(&s->downstream_as, ch->src,
104
+ MEMTXATTRS_UNSPECIFIED, buff + n, swidth);
105
if (ch->ctrl & PL080_CCTRL_SI)
106
ch->src += swidth;
107
}
108
xsize = (dwidth < swidth) ? swidth : dwidth;
109
/* ??? This may pad the value incorrectly for dwidth < 32. */
110
for (n = 0; n < xsize; n += dwidth) {
111
- cpu_physical_memory_write(ch->dest + n, buff + n, dwidth);
112
+ address_space_write(&s->downstream_as, ch->dest + n,
113
+ MEMTXATTRS_UNSPECIFIED, buff + n, dwidth);
114
if (ch->ctrl & PL080_CCTRL_DI)
115
ch->dest += swidth;
116
}
117
@@ -XXX,XX +XXX,XX @@ again:
118
if (size == 0) {
119
/* Transfer complete. */
120
if (ch->lli) {
121
- ch->src = address_space_ldl_le(&address_space_memory,
122
+ ch->src = address_space_ldl_le(&s->downstream_as,
123
ch->lli,
124
MEMTXATTRS_UNSPECIFIED,
125
NULL);
126
- ch->dest = address_space_ldl_le(&address_space_memory,
127
+ ch->dest = address_space_ldl_le(&s->downstream_as,
128
ch->lli + 4,
129
MEMTXATTRS_UNSPECIFIED,
130
NULL);
131
- ch->ctrl = address_space_ldl_le(&address_space_memory,
132
+ ch->ctrl = address_space_ldl_le(&s->downstream_as,
133
ch->lli + 12,
134
MEMTXATTRS_UNSPECIFIED,
135
NULL);
136
- ch->lli = address_space_ldl_le(&address_space_memory,
137
+ ch->lli = address_space_ldl_le(&s->downstream_as,
138
ch->lli + 8,
139
MEMTXATTRS_UNSPECIFIED,
140
NULL);
141
@@ -XXX,XX +XXX,XX @@ static void pl080_init(Object *obj)
142
s->nchannels = 8;
47
}
143
}
48
144
49
+void sdbus_reparent_card(SDBus *from, SDBus *to)
145
+static void pl080_realize(DeviceState *dev, Error **errp)
50
+{
146
+{
51
+ BusChild *kid = QTAILQ_FIRST(&from->qbus.children);
147
+ PL080State *s = PL080(dev);
52
+ SDState *card;
53
+ SDCardClass *sc;
54
+ bool readonly;
55
+
148
+
56
+ /* We directly reparent the card object rather than implementing this
149
+ if (!s->downstream) {
57
+ * as a hotpluggable connection because we don't want to expose SD cards
150
+ error_setg(errp, "PL080 'downstream' link not set");
58
+ * to users as being hotpluggable, and we can get away with it in this
59
+ * limited use case. This could perhaps be implemented more cleanly in
60
+ * future by adding support to the hotplug infrastructure for "device
61
+ * can be hotplugged only via code, not by user".
62
+ */
63
+
64
+ if (!kid) {
65
+ return;
151
+ return;
66
+ }
152
+ }
67
+
153
+
68
+ card = SD_CARD(kid->child);
154
+ address_space_init(&s->downstream_as, s->downstream, "pl080-downstream");
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
+}
155
+}
78
+
156
+
79
static const TypeInfo sd_bus_info = {
157
static void pl081_init(Object *obj)
80
.name = TYPE_SD_BUS,
158
{
81
.parent = TYPE_BUS,
159
PL080State *s = PL080(obj);
160
@@ -XXX,XX +XXX,XX @@ static void pl081_init(Object *obj)
161
s->nchannels = 2;
162
}
163
164
+static Property pl080_properties[] = {
165
+ DEFINE_PROP_LINK("downstream", PL080State, downstream,
166
+ TYPE_MEMORY_REGION, MemoryRegion *),
167
+ DEFINE_PROP_END_OF_LIST(),
168
+};
169
+
170
static void pl080_class_init(ObjectClass *oc, void *data)
171
{
172
DeviceClass *dc = DEVICE_CLASS(oc);
173
174
dc->vmsd = &vmstate_pl080;
175
+ dc->realize = pl080_realize;
176
+ dc->props = pl080_properties;
177
}
178
179
static const TypeInfo pl080_info = {
82
--
180
--
83
2.7.4
181
2.18.0
84
182
85
183
diff view generated by jsdifflib
1
Switch to using qcrypto_random_bytes() rather than rand() as
1
The PL080/PL081 model is missing a reset function; implement it.
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: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
---
5
---
17
hw/misc/bcm2835_rng.c | 27 ++++++++++++++++++++++++++-
6
hw/dma/pl080.c | 25 +++++++++++++++++++++++++
18
1 file changed, 26 insertions(+), 1 deletion(-)
7
1 file changed, 25 insertions(+)
19
8
20
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
9
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
21
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/bcm2835_rng.c
11
--- a/hw/dma/pl080.c
23
+++ b/hw/misc/bcm2835_rng.c
12
+++ b/hw/dma/pl080.c
24
@@ -XXX,XX +XXX,XX @@
13
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps pl080_ops = {
25
14
.endianness = DEVICE_NATIVE_ENDIAN,
26
#include "qemu/osdep.h"
15
};
27
#include "qemu/log.h"
16
28
+#include "qapi/error.h"
17
+static void pl080_reset(DeviceState *dev)
29
+#include "crypto/random.h"
30
#include "hw/misc/bcm2835_rng.h"
31
32
+static uint32_t get_random_bytes(void)
33
+{
18
+{
34
+ uint32_t res;
19
+ PL080State *s = PL080(dev);
35
+ Error *err = NULL;
20
+ int i;
36
+
21
+
37
+ if (qcrypto_random_bytes((uint8_t *)&res, sizeof(res), &err) < 0) {
22
+ s->tc_int = 0;
38
+ /* On failure we don't want to return the guest a non-random
23
+ s->tc_mask = 0;
39
+ * value in case they're really using it for cryptographic
24
+ s->err_int = 0;
40
+ * purposes, so the best we can do is die here.
25
+ s->err_mask = 0;
41
+ * This shouldn't happen unless something's broken.
26
+ s->conf = 0;
42
+ * In theory we could implement this device's full FIFO
27
+ s->sync = 0;
43
+ * and interrupt semantics and then just stop filling the
28
+ s->req_single = 0;
44
+ * FIFO. That's a lot of work, though, so we assume any
29
+ s->req_burst = 0;
45
+ * errors are systematic problems and trust that if we didn't
30
+ s->running = 0;
46
+ * fail as the guest inited then we won't fail later on
31
+
47
+ * mid-run.
32
+ for (i = 0; i < s->nchannels; i++) {
48
+ */
33
+ s->chan[i].src = 0;
49
+ error_report_err(err);
34
+ s->chan[i].dest = 0;
50
+ exit(1);
35
+ s->chan[i].lli = 0;
36
+ s->chan[i].ctrl = 0;
37
+ s->chan[i].conf = 0;
51
+ }
38
+ }
52
+ return res;
53
+}
39
+}
54
+
40
+
55
static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
41
static void pl080_init(Object *obj)
56
unsigned size)
57
{
42
{
58
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
43
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
59
res = s->rng_status | (1 << 24);
44
@@ -XXX,XX +XXX,XX @@ static void pl080_class_init(ObjectClass *oc, void *data)
60
break;
45
dc->vmsd = &vmstate_pl080;
61
case 0x8: /* rng_data */
46
dc->realize = pl080_realize;
62
- res = rand();
47
dc->props = pl080_properties;
63
+ res = get_random_bytes();
48
+ dc->reset = pl080_reset;
64
break;
49
}
65
50
66
default:
51
static const TypeInfo pl080_info = {
67
--
52
--
68
2.7.4
53
2.18.0
69
54
70
55
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 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
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
Deleted patch
1
In get_page_addr_code(), if the guest PC doesn't correspond to RAM
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
1
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
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <rth@twiddle.net>
23
---
24
cputlb.c | 15 +++++++--------
25
1 file changed, 7 insertions(+), 8 deletions(-)
26
27
diff --git a/cputlb.c b/cputlb.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/cputlb.c
30
+++ b/cputlb.c
31
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
32
pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
33
mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
34
if (memory_region_is_unassigned(mr)) {
35
- CPUClass *cc = CPU_GET_CLASS(cpu);
36
-
37
- if (cc->do_unassigned_access) {
38
- cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
39
- } else {
40
- report_bad_exec(cpu, addr);
41
- exit(1);
42
- }
43
+ cpu_unassigned_access(cpu, addr, false, true, 0, 4);
44
+ /* The CPU's unassigned access hook might have longjumped out
45
+ * with an exception. If it didn't (or there was no hook) then
46
+ * we can't proceed further.
47
+ */
48
+ report_bad_exec(cpu, addr);
49
+ exit(1);
50
}
51
p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
52
return qemu_ram_addr_from_host_nofail(p);
53
--
54
2.7.4
55
56
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
A bug in the handling of the register address decode logic
2
for the PL08x meant that we were incorrectly treating
3
accesses to the DMA channel registers (DMACCxSrcAddr,
4
DMACCxDestaddr, DMACCxLLI, DMACCxControl, DMACCxConfiguration)
5
as bad offsets. Fix this long-standing bug.
2
6
3
The VECTCLRACTIVE and VECTRESET bits in the AIRCR are both
7
Fixes: https://bugs.launchpad.net/qemu/+bug/1637974
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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
---
10
---
19
hw/intc/armv7m_nvic.c | 8 ++++++--
11
hw/dma/pl080.c | 5 +++--
20
1 file changed, 6 insertions(+), 2 deletions(-)
12
1 file changed, 3 insertions(+), 2 deletions(-)
21
13
22
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
14
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
23
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/armv7m_nvic.c
16
--- a/hw/dma/pl080.c
25
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/hw/dma/pl080.c
26
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
18
@@ -XXX,XX +XXX,XX @@ static uint64_t pl080_read(void *opaque, hwaddr offset,
27
qemu_irq_pulse(s->sysresetreq);
19
i = (offset & 0xe0) >> 5;
28
}
20
if (i >= s->nchannels)
29
if (value & 2) {
21
goto bad_offset;
30
- qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
22
- switch (offset >> 2) {
31
+ qemu_log_mask(LOG_GUEST_ERROR,
23
+ switch ((offset >> 2) & 7) {
32
+ "Setting VECTCLRACTIVE when not in DEBUG mode "
24
case 0: /* SrcAddr */
33
+ "is UNPREDICTABLE\n");
25
return s->chan[i].src;
34
}
26
case 1: /* DestAddr */
35
if (value & 1) {
27
@@ -XXX,XX +XXX,XX @@ static void pl080_write(void *opaque, hwaddr offset,
36
- qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
28
i = (offset & 0xe0) >> 5;
37
+ qemu_log_mask(LOG_GUEST_ERROR,
29
if (i >= s->nchannels)
38
+ "Setting VECTRESET when not in DEBUG mode "
30
goto bad_offset;
39
+ "is UNPREDICTABLE\n");
31
- switch (offset >> 2) {
40
}
32
+ switch ((offset >> 2) & 7) {
41
s->prigroup = extract32(value, 8, 3);
33
case 0: /* SrcAddr */
42
nvic_irq_update(s);
34
s->chan[i].src = value;
35
break;
36
@@ -XXX,XX +XXX,XX @@ static void pl080_write(void *opaque, hwaddr offset,
37
pl080_run(s);
38
break;
39
}
40
+ return;
41
}
42
switch (offset >> 2) {
43
case 2: /* IntTCClear */
43
--
44
--
44
2.7.4
45
2.18.0
45
46
46
47
diff view generated by jsdifflib
1
Add a state field for the v7M PRIGROUP register and implent
1
The PL08x model currently will unconditionally call hw_error()
2
reading and writing it. The current NVIC doesn't honour
2
if the DMA engine is enabled by the guest. This has been
3
the values written, but the new version will.
3
present since the PL080 model was edded in 2006, and is
4
presumably either unintentional debug code left enabled,
5
or a guard against untested DMA engine code being used.
6
7
Remove the hw_error(), since we now have a guest which
8
will actually try to use the DMA engine (the self-test
9
binary for the AN505 MPS2 FPGA image).
4
10
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
---
13
---
9
hw/intc/armv7m_nvic.c | 14 ++++++++------
14
hw/dma/pl080.c | 1 -
10
1 file changed, 8 insertions(+), 6 deletions(-)
15
1 file changed, 1 deletion(-)
11
16
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
17
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
19
--- a/hw/dma/pl080.c
15
+++ b/hw/intc/armv7m_nvic.c
20
+++ b/hw/dma/pl080.c
16
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void pl080_run(PL080State *s)
17
typedef struct NVICState {
22
if ((s->conf & PL080_CONF_E) == 0)
18
GICState gic;
23
return;
19
ARMCPU *cpu;
24
20
+
25
-hw_error("DMA active\n");
21
+ uint32_t prigroup;
26
/* If we are already in the middle of a DMA operation then indicate that
22
+
27
there may be new DMA requests and return immediately. */
23
struct {
28
if (s->running) {
24
uint32_t control;
25
uint32_t reload;
26
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
27
case 0xd08: /* Vector Table Offset. */
28
return cpu->env.v7m.vecbase;
29
case 0xd0c: /* Application Interrupt/Reset Control. */
30
- return 0xfa050000;
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
}
62
};
63
--
29
--
64
2.7.4
30
2.18.0
65
31
66
32
diff view generated by jsdifflib
Deleted patch
1
Implement the NVIC SHCSR write behaviour which allows pending and
2
active status of some exceptions to be changed.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
---
7
hw/intc/armv7m_nvic.c | 13 +++++++++++--
8
1 file changed, 11 insertions(+), 2 deletions(-)
9
10
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/intc/armv7m_nvic.c
13
+++ b/hw/intc/armv7m_nvic.c
14
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
15
cpu->env.v7m.ccr = value;
16
break;
17
case 0xd24: /* System Handler Control. */
18
- /* TODO: Real hardware allows you to set/clear the active bits
19
- under some circumstances. We don't implement this. */
20
+ s->vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
21
+ s->vectors[ARMV7M_EXCP_BUS].active = (value & (1 << 1)) != 0;
22
+ s->vectors[ARMV7M_EXCP_USAGE].active = (value & (1 << 3)) != 0;
23
+ s->vectors[ARMV7M_EXCP_SVC].active = (value & (1 << 7)) != 0;
24
+ s->vectors[ARMV7M_EXCP_DEBUG].active = (value & (1 << 8)) != 0;
25
+ s->vectors[ARMV7M_EXCP_PENDSV].active = (value & (1 << 10)) != 0;
26
+ s->vectors[ARMV7M_EXCP_SYSTICK].active = (value & (1 << 11)) != 0;
27
+ s->vectors[ARMV7M_EXCP_USAGE].pending = (value & (1 << 12)) != 0;
28
+ s->vectors[ARMV7M_EXCP_MEM].pending = (value & (1 << 13)) != 0;
29
+ s->vectors[ARMV7M_EXCP_BUS].pending = (value & (1 << 14)) != 0;
30
+ s->vectors[ARMV7M_EXCP_SVC].pending = (value & (1 << 15)) != 0;
31
s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
32
s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
33
s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
34
--
35
2.7.4
36
37
diff view generated by jsdifflib