1
Some more outstanding target-arm patches; nothing terribly
1
Arm changes for before softfreeze: mostly my PL061/GPIO patches,
2
exciting. Mostly they're mine; I'm trying to reduce the
2
but also a new M-profile board and various other things.
3
number of patches I still have in flight, so I've picked
4
out some of the reviewed patches from a couple of sets I've
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.
8
3
9
thanks
4
thanks
10
-- PMM
5
-- PMM
11
6
7
The following changes since commit 05de778b5b8ab0b402996769117b88c7ea5c7c61:
12
8
13
The following changes since commit adaec191bfb31e12d40af8ab1b869f5b40d61ee9:
9
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2021-07-09 14:30:01 +0100)
14
15
Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging (2018-08-20 09:48:03 +0100)
16
10
17
are available in the Git repository at:
11
are available in the Git repository at:
18
12
19
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180820
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210709
20
14
21
for you to fetch changes up to b85fad1588e812566f897f747e38da345a7016d6:
15
for you to fetch changes up to 05449abb1d4c5f0c69ceb3d8d03cbc75de39b646:
22
16
23
hw/dma/pl080: Remove hw_error() if DMA is enabled (2018-08-20 11:24:33 +0100)
17
hw/intc: Improve formatting of MEMTX_ERROR guest error message (2021-07-09 16:09:12 +0100)
24
18
25
----------------------------------------------------------------
19
----------------------------------------------------------------
26
target-arm queue:
20
target-arm queue:
27
* Fix crash on conditional instruction in an IT block
21
* New machine type: stm32vldiscovery
28
* docs/generic-loader: mention U-Boot and Intel HEX executable formats
22
* hw/intc/arm_gicv3_cpuif: Fix virtual irq number check in icv_[dir|eoir]_write
29
* hw/intc/arm_gicv3_its: downgrade error_report to warn_report in kvm_arm_its_reset
23
* hw/gpio/pl061: Honour Luminary PL061 PUR and PDR registers
30
* imx_serial: Generate interrupt on receive data ready if enabled
24
* virt: Fix implementation of GPIO-based powerdown/shutdown mechanism
31
* Fix various minor bugs in AArch32 Hyp related coprocessor registers
25
* Correct the encoding of MDCCSR_EL0 and DBGDSCRint
32
* Permit accesses to ELR_Hyp from Hyp mode via MSR/MRS (banked)
26
* hw/intc: Improve formatting of MEMTX_ERROR guest error message
33
* Implement AArch32 ERET instruction
34
* hw/arm/virt: Add virt-3.1 machine type
35
* sdhci: add i.MX SD Stable Clock bit
36
* Remove now-obsolete MMIO request_ptr APIs
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
41
27
42
----------------------------------------------------------------
28
----------------------------------------------------------------
43
Andrew Jones (1):
29
Alexandre Iooss (4):
44
hw/arm/virt: Add virt-3.1 machine type
30
stm32f100: Add the stm32f100 SoC
31
stm32vldiscovery: Add the STM32VLDISCOVERY Machine
32
docs/system: arm: Add stm32 boards description
33
tests/boot-serial-test: Add STM32VLDISCOVERY board testcase
45
34
46
Hans-Erik Floryd (2):
35
Peter Maydell (10):
47
imx_serial: Generate interrupt on receive data ready if enabled
36
hw/gpio/pl061: Convert DPRINTF to tracepoints
48
sdhci: add i.MX SD Stable Clock bit
37
hw/gpio/pl061: Clean up read/write offset handling logic
38
hw/gpio/pl061: Add tracepoints for register read and write
39
hw/gpio/pl061: Document the interface of this device
40
hw/gpio/pl061: Honour Luminary PL061 PUR and PDR registers
41
hw/gpio/pl061: Make pullup/pulldown of outputs configurable
42
hw/arm/virt: Make PL061 GPIO lines pulled low, not high
43
hw/gpio/pl061: Convert to 3-phase reset and assert GPIO lines correctly on reset
44
hw/gpio/pl061: Document a shortcoming in our implementation
45
hw/arm/stellaris: Expand comment about handling of OLED chipselect
49
46
50
Jia He (1):
47
Rebecca Cran (1):
51
hw/intc/arm_gicv3_its: downgrade error_report to warn_report in kvm_arm_its_reset
48
hw/intc: Improve formatting of MEMTX_ERROR guest error message
52
49
53
Peter Maydell (19):
50
Ricardo Koller (1):
54
target/arm: Correct typo in HAMAIR1 regdef name
51
hw/intc/arm_gicv3_cpuif: Fix virtual irq number check in icv_[dir|eoir]_write
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
73
52
74
Roman Kapl (1):
53
hnick@vmware.com (1):
75
target/arm: Fix crash on conditional instruction in an IT block
54
target/arm: Correct the encoding of MDCCSR_EL0 and DBGDSCRint
76
55
77
Stefan Hajnoczi (1):
56
docs/system/arm/stm32.rst | 66 +++++++
78
docs/generic-loader: mention U-Boot and Intel HEX executable formats
57
docs/system/target-arm.rst | 1 +
58
default-configs/devices/arm-softmmu.mak | 1 +
59
include/hw/arm/stm32f100_soc.h | 57 ++++++
60
hw/arm/stellaris.c | 56 +++++-
61
hw/arm/stm32f100_soc.c | 182 +++++++++++++++++
62
hw/arm/stm32vldiscovery.c | 66 +++++++
63
hw/arm/virt.c | 3 +
64
hw/gpio/pl061.c | 341 +++++++++++++++++++++++++-------
65
hw/intc/arm_gicv3_cpuif.c | 4 +-
66
hw/intc/arm_gicv3_redist.c | 4 +-
67
target/arm/helper.c | 16 +-
68
tests/qtest/boot-serial-test.c | 37 ++++
69
MAINTAINERS | 13 ++
70
hw/arm/Kconfig | 10 +
71
hw/arm/meson.build | 2 +
72
hw/gpio/trace-events | 9 +
73
17 files changed, 790 insertions(+), 78 deletions(-)
74
create mode 100644 docs/system/arm/stm32.rst
75
create mode 100644 include/hw/arm/stm32f100_soc.h
76
create mode 100644 hw/arm/stm32f100_soc.c
77
create mode 100644 hw/arm/stm32vldiscovery.c
79
78
80
docs/generic-loader.txt | 20 +-
81
Makefile.objs | 1 +
82
hw/misc/Makefile.objs | 1 -
83
hw/watchdog/Makefile.objs | 1 +
84
hw/sd/sdhci-internal.h | 2 +
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
118
diff view generated by jsdifflib
1
The Arm Cortex-M System Design Kit includes a simple watchdog module
1
From: Alexandre Iooss <erdnaxe@crans.org>
2
based on a 32-bit down-counter. Implement this.
2
3
3
This SoC is similar to stm32f205 SoC.
4
This will be used by the STM32VLDISCOVERY to create a machine.
5
6
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210617165647.2575955-2-erdnaxe@crans.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
---
10
---
6
Makefile.objs | 1 +
11
include/hw/arm/stm32f100_soc.h | 57 +++++++++++
7
hw/watchdog/Makefile.objs | 1 +
12
hw/arm/stm32f100_soc.c | 182 +++++++++++++++++++++++++++++++++
8
include/hw/watchdog/cmsdk-apb-watchdog.h | 59 ++++
13
MAINTAINERS | 6 ++
9
hw/watchdog/cmsdk-apb-watchdog.c | 326 +++++++++++++++++++++++
14
hw/arm/Kconfig | 6 ++
10
MAINTAINERS | 2 +
15
hw/arm/meson.build | 1 +
11
default-configs/arm-softmmu.mak | 1 +
16
5 files changed, 252 insertions(+)
12
hw/watchdog/trace-events | 6 +
17
create mode 100644 include/hw/arm/stm32f100_soc.h
13
7 files changed, 396 insertions(+)
18
create mode 100644 hw/arm/stm32f100_soc.c
14
create mode 100644 include/hw/watchdog/cmsdk-apb-watchdog.h
19
15
create mode 100644 hw/watchdog/cmsdk-apb-watchdog.c
20
diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
16
create mode 100644 hw/watchdog/trace-events
17
18
diff --git a/Makefile.objs b/Makefile.objs
19
index XXXXXXX..XXXXXXX 100644
20
--- a/Makefile.objs
21
+++ b/Makefile.objs
22
@@ -XXX,XX +XXX,XX @@ trace-events-subdirs += hw/tpm
23
trace-events-subdirs += hw/usb
24
trace-events-subdirs += hw/vfio
25
trace-events-subdirs += hw/virtio
26
+trace-events-subdirs += hw/watchdog
27
trace-events-subdirs += hw/xen
28
trace-events-subdirs += io
29
trace-events-subdirs += linux-user
30
diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/watchdog/Makefile.objs
33
+++ b/hw/watchdog/Makefile.objs
34
@@ -XXX,XX +XXX,XX @@
35
common-obj-y += watchdog.o
36
+common-obj-$(CONFIG_CMSDK_APB_WATCHDOG) += cmsdk-apb-watchdog.o
37
common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
38
common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
39
common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
40
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
41
new file mode 100644
21
new file mode 100644
42
index XXXXXXX..XXXXXXX
22
index XXXXXXX..XXXXXXX
43
--- /dev/null
23
--- /dev/null
44
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
24
+++ b/include/hw/arm/stm32f100_soc.h
45
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
46
+/*
26
+/*
47
+ * ARM CMSDK APB watchdog emulation
27
+ * STM32F100 SoC
48
+ *
28
+ *
49
+ * Copyright (c) 2018 Linaro Limited
29
+ * Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
50
+ * Written by Peter Maydell
30
+ *
51
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
52
+ * This program is free software; you can redistribute it and/or modify
32
+ * of this software and associated documentation files (the "Software"), to deal
53
+ * it under the terms of the GNU General Public License version 2 or
33
+ * in the Software without restriction, including without limitation the rights
54
+ * (at your option) any later version.
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
55
+ */
48
+ */
56
+
49
+
57
+/*
50
+#ifndef HW_ARM_STM32F100_SOC_H
58
+ * This is a model of the "APB watchdog" which is part of the Cortex-M
51
+#define HW_ARM_STM32F100_SOC_H
59
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
52
+
60
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
53
+#include "hw/char/stm32f2xx_usart.h"
61
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
54
+#include "hw/ssi/stm32f2xx_spi.h"
62
+ *
55
+#include "hw/arm/armv7m.h"
63
+ * QEMU interface:
56
+#include "qom/object.h"
64
+ * + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
57
+
65
+ * + sysbus MMIO region 0: the register bank
58
+#define TYPE_STM32F100_SOC "stm32f100-soc"
66
+ * + sysbus IRQ 0: watchdog interrupt
59
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F100State, STM32F100_SOC)
67
+ *
60
+
68
+ * In real hardware the watchdog's reset output is just a GPIO line
61
+#define STM_NUM_USARTS 3
69
+ * which can then be masked by the board or treated as a simple interrupt.
62
+#define STM_NUM_SPIS 2
70
+ * (For instance the IoTKit does this with the non-secure watchdog, so that
63
+
71
+ * secure code can control whether non-secure code can perform a system
64
+#define FLASH_BASE_ADDRESS 0x08000000
72
+ * reset via its watchdog.) In QEMU, we just wire up the watchdog reset
65
+#define FLASH_SIZE (128 * 1024)
73
+ * to watchdog_perform_action(), at least for the moment.
66
+#define SRAM_BASE_ADDRESS 0x20000000
74
+ */
67
+#define SRAM_SIZE (8 * 1024)
75
+
68
+
76
+#ifndef CMSDK_APB_WATCHDOG_H
69
+struct STM32F100State {
77
+#define CMSDK_APB_WATCHDOG_H
78
+
79
+#include "hw/sysbus.h"
80
+#include "hw/ptimer.h"
81
+
82
+#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
83
+#define CMSDK_APB_WATCHDOG(obj) OBJECT_CHECK(CMSDKAPBWatchdog, (obj), \
84
+ TYPE_CMSDK_APB_WATCHDOG)
85
+
86
+typedef struct CMSDKAPBWatchdog {
87
+ /*< private >*/
70
+ /*< private >*/
88
+ SysBusDevice parent_obj;
71
+ SysBusDevice parent_obj;
89
+
72
+
90
+ /*< public >*/
73
+ /*< public >*/
91
+ MemoryRegion iomem;
74
+ char *cpu_type;
92
+ qemu_irq wdogint;
75
+
93
+ uint32_t wdogclk_frq;
76
+ ARMv7MState armv7m;
94
+ struct ptimer_state *timer;
77
+
95
+
78
+ STM32F2XXUsartState usart[STM_NUM_USARTS];
96
+ uint32_t control;
79
+ STM32F2XXSPIState spi[STM_NUM_SPIS];
97
+ uint32_t intstatus;
80
+};
98
+ uint32_t lock;
99
+ uint32_t itcr;
100
+ uint32_t itop;
101
+ uint32_t resetstatus;
102
+} CMSDKAPBWatchdog;
103
+
81
+
104
+#endif
82
+#endif
105
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
83
diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c
106
new file mode 100644
84
new file mode 100644
107
index XXXXXXX..XXXXXXX
85
index XXXXXXX..XXXXXXX
108
--- /dev/null
86
--- /dev/null
109
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
87
+++ b/hw/arm/stm32f100_soc.c
110
@@ -XXX,XX +XXX,XX @@
88
@@ -XXX,XX +XXX,XX @@
111
+/*
89
+/*
112
+ * ARM CMSDK APB watchdog emulation
90
+ * STM32F100 SoC
113
+ *
91
+ *
114
+ * Copyright (c) 2018 Linaro Limited
92
+ * Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
115
+ * Written by Peter Maydell
93
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
116
+ *
94
+ *
117
+ * This program is free software; you can redistribute it and/or modify
95
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
118
+ * it under the terms of the GNU General Public License version 2 or
96
+ * of this software and associated documentation files (the "Software"), to deal
119
+ * (at your option) any later version.
97
+ * in the Software without restriction, including without limitation the rights
98
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99
+ * copies of the Software, and to permit persons to whom the Software is
100
+ * furnished to do so, subject to the following conditions:
101
+ *
102
+ * The above copyright notice and this permission notice shall be included in
103
+ * all copies or substantial portions of the Software.
104
+ *
105
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
106
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
107
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
108
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
109
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
110
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
111
+ * THE SOFTWARE.
120
+ */
112
+ */
121
+
113
+
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
127
+ */
128
+
129
+#include "qemu/osdep.h"
114
+#include "qemu/osdep.h"
130
+#include "qemu/log.h"
131
+#include "trace.h"
132
+#include "qapi/error.h"
115
+#include "qapi/error.h"
133
+#include "qemu/main-loop.h"
116
+#include "qemu/module.h"
134
+#include "sysemu/watchdog.h"
117
+#include "hw/arm/boot.h"
135
+#include "hw/sysbus.h"
118
+#include "exec/address-spaces.h"
136
+#include "hw/registerfields.h"
119
+#include "hw/arm/stm32f100_soc.h"
137
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
120
+#include "hw/qdev-properties.h"
138
+
121
+#include "hw/misc/unimp.h"
139
+REG32(WDOGLOAD, 0x0)
122
+#include "sysemu/sysemu.h"
140
+REG32(WDOGVALUE, 0x4)
123
+
141
+REG32(WDOGCONTROL, 0x8)
124
+/* stm32f100_soc implementation is derived from stm32f205_soc */
142
+ FIELD(WDOGCONTROL, INTEN, 0, 1)
125
+
143
+ FIELD(WDOGCONTROL, RESEN, 1, 1)
126
+static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40013800, 0x40004400,
144
+#define R_WDOGCONTROL_VALID_MASK (R_WDOGCONTROL_INTEN_MASK | \
127
+ 0x40004800 };
145
+ R_WDOGCONTROL_RESEN_MASK)
128
+static const uint32_t spi_addr[STM_NUM_SPIS] = { 0x40013000, 0x40003800 };
146
+REG32(WDOGINTCLR, 0xc)
129
+
147
+REG32(WDOGRIS, 0x10)
130
+static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39};
148
+ FIELD(WDOGRIS, INT, 0, 1)
131
+static const int spi_irq[STM_NUM_SPIS] = {35, 36};
149
+REG32(WDOGMIS, 0x14)
132
+
150
+REG32(WDOGLOCK, 0xc00)
133
+static void stm32f100_soc_initfn(Object *obj)
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
+{
134
+{
182
+ /* Return masked interrupt status */
135
+ STM32F100State *s = STM32F100_SOC(obj);
183
+ return s->intstatus && (s->control & R_WDOGCONTROL_INTEN_MASK);
136
+ int i;
137
+
138
+ object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M);
139
+
140
+ for (i = 0; i < STM_NUM_USARTS; i++) {
141
+ object_initialize_child(obj, "usart[*]", &s->usart[i],
142
+ TYPE_STM32F2XX_USART);
143
+ }
144
+
145
+ for (i = 0; i < STM_NUM_SPIS; i++) {
146
+ object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_STM32F2XX_SPI);
147
+ }
184
+}
148
+}
185
+
149
+
186
+static bool cmsdk_apb_watchdog_resetstatus(CMSDKAPBWatchdog *s)
150
+static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
187
+{
151
+{
188
+ /* Return masked reset status */
152
+ STM32F100State *s = STM32F100_SOC(dev_soc);
189
+ return s->resetstatus && (s->control & R_WDOGCONTROL_RESEN_MASK);
153
+ DeviceState *dev, *armv7m;
154
+ SysBusDevice *busdev;
155
+ int i;
156
+
157
+ MemoryRegion *system_memory = get_system_memory();
158
+ MemoryRegion *sram = g_new(MemoryRegion, 1);
159
+ MemoryRegion *flash = g_new(MemoryRegion, 1);
160
+ MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
161
+
162
+ /*
163
+ * Init flash region
164
+ * Flash starts at 0x08000000 and then is aliased to boot memory at 0x0
165
+ */
166
+ memory_region_init_rom(flash, OBJECT(dev_soc), "STM32F100.flash",
167
+ FLASH_SIZE, &error_fatal);
168
+ memory_region_init_alias(flash_alias, OBJECT(dev_soc),
169
+ "STM32F100.flash.alias", flash, 0, FLASH_SIZE);
170
+ memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
171
+ memory_region_add_subregion(system_memory, 0, flash_alias);
172
+
173
+ /* Init SRAM region */
174
+ memory_region_init_ram(sram, NULL, "STM32F100.sram", SRAM_SIZE,
175
+ &error_fatal);
176
+ memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
177
+
178
+ /* Init ARMv7m */
179
+ armv7m = DEVICE(&s->armv7m);
180
+ qdev_prop_set_uint32(armv7m, "num-irq", 61);
181
+ qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
182
+ qdev_prop_set_bit(armv7m, "enable-bitband", true);
183
+ object_property_set_link(OBJECT(&s->armv7m), "memory",
184
+ OBJECT(get_system_memory()), &error_abort);
185
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
186
+ return;
187
+ }
188
+
189
+ /* Attach UART (uses USART registers) and USART controllers */
190
+ for (i = 0; i < STM_NUM_USARTS; i++) {
191
+ dev = DEVICE(&(s->usart[i]));
192
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
193
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->usart[i]), errp)) {
194
+ return;
195
+ }
196
+ busdev = SYS_BUS_DEVICE(dev);
197
+ sysbus_mmio_map(busdev, 0, usart_addr[i]);
198
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
199
+ }
200
+
201
+ /* SPI 1 and 2 */
202
+ for (i = 0; i < STM_NUM_SPIS; i++) {
203
+ dev = DEVICE(&(s->spi[i]));
204
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
205
+ return;
206
+ }
207
+ busdev = SYS_BUS_DEVICE(dev);
208
+ sysbus_mmio_map(busdev, 0, spi_addr[i]);
209
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
210
+ }
211
+
212
+ create_unimplemented_device("timer[2]", 0x40000000, 0x400);
213
+ create_unimplemented_device("timer[3]", 0x40000400, 0x400);
214
+ create_unimplemented_device("timer[4]", 0x40000800, 0x400);
215
+ create_unimplemented_device("timer[6]", 0x40001000, 0x400);
216
+ create_unimplemented_device("timer[7]", 0x40001400, 0x400);
217
+ create_unimplemented_device("RTC", 0x40002800, 0x400);
218
+ create_unimplemented_device("WWDG", 0x40002C00, 0x400);
219
+ create_unimplemented_device("IWDG", 0x40003000, 0x400);
220
+ create_unimplemented_device("I2C1", 0x40005400, 0x400);
221
+ create_unimplemented_device("I2C2", 0x40005800, 0x400);
222
+ create_unimplemented_device("BKP", 0x40006C00, 0x400);
223
+ create_unimplemented_device("PWR", 0x40007000, 0x400);
224
+ create_unimplemented_device("DAC", 0x40007400, 0x400);
225
+ create_unimplemented_device("CEC", 0x40007800, 0x400);
226
+ create_unimplemented_device("AFIO", 0x40010000, 0x400);
227
+ create_unimplemented_device("EXTI", 0x40010400, 0x400);
228
+ create_unimplemented_device("GPIOA", 0x40010800, 0x400);
229
+ create_unimplemented_device("GPIOB", 0x40010C00, 0x400);
230
+ create_unimplemented_device("GPIOC", 0x40011000, 0x400);
231
+ create_unimplemented_device("GPIOD", 0x40011400, 0x400);
232
+ create_unimplemented_device("GPIOE", 0x40011800, 0x400);
233
+ create_unimplemented_device("ADC1", 0x40012400, 0x400);
234
+ create_unimplemented_device("timer[1]", 0x40012C00, 0x400);
235
+ create_unimplemented_device("timer[15]", 0x40014000, 0x400);
236
+ create_unimplemented_device("timer[16]", 0x40014400, 0x400);
237
+ create_unimplemented_device("timer[17]", 0x40014800, 0x400);
238
+ create_unimplemented_device("DMA", 0x40020000, 0x400);
239
+ create_unimplemented_device("RCC", 0x40021000, 0x400);
240
+ create_unimplemented_device("Flash Int", 0x40022000, 0x400);
241
+ create_unimplemented_device("CRC", 0x40023000, 0x400);
190
+}
242
+}
191
+
243
+
192
+static void cmsdk_apb_watchdog_update(CMSDKAPBWatchdog *s)
244
+static Property stm32f100_soc_properties[] = {
193
+{
245
+ DEFINE_PROP_STRING("cpu-type", STM32F100State, cpu_type),
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;
216
+
217
+ switch (offset) {
218
+ case A_WDOGLOAD:
219
+ r = ptimer_get_limit(s->timer);
220
+ break;
221
+ case A_WDOGVALUE:
222
+ r = ptimer_get_count(s->timer);
223
+ break;
224
+ case A_WDOGCONTROL:
225
+ r = s->control;
226
+ break;
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;
249
+ default:
250
+ qemu_log_mask(LOG_GUEST_ERROR,
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",
308
+ (int)offset);
309
+ break;
310
+ default:
311
+ qemu_log_mask(LOG_GUEST_ERROR,
312
+ "CMSDK APB watchdog write: bad offset 0x%x\n",
313
+ (int)offset);
314
+ break;
315
+ }
316
+}
317
+
318
+static const MemoryRegionOps cmsdk_apb_watchdog_ops = {
319
+ .read = cmsdk_apb_watchdog_read,
320
+ .write = cmsdk_apb_watchdog_write,
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,
327
+};
328
+
329
+static void cmsdk_apb_watchdog_tick(void *opaque)
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",
394
+ .version_id = 1,
395
+ .minimum_version_id = 1,
396
+ .fields = (VMStateField[]) {
397
+ VMSTATE_PTIMER(timer, CMSDKAPBWatchdog),
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),
404
+ VMSTATE_END_OF_LIST()
405
+ }
406
+};
407
+
408
+static Property cmsdk_apb_watchdog_properties[] = {
409
+ DEFINE_PROP_UINT32("wdogclk-frq", CMSDKAPBWatchdog, wdogclk_frq, 0),
410
+ DEFINE_PROP_END_OF_LIST(),
246
+ DEFINE_PROP_END_OF_LIST(),
411
+};
247
+};
412
+
248
+
413
+static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
249
+static void stm32f100_soc_class_init(ObjectClass *klass, void *data)
414
+{
250
+{
415
+ DeviceClass *dc = DEVICE_CLASS(klass);
251
+ DeviceClass *dc = DEVICE_CLASS(klass);
416
+
252
+
417
+ dc->realize = cmsdk_apb_watchdog_realize;
253
+ dc->realize = stm32f100_soc_realize;
418
+ dc->vmsd = &cmsdk_apb_watchdog_vmstate;
254
+ device_class_set_props(dc, stm32f100_soc_properties);
419
+ dc->reset = cmsdk_apb_watchdog_reset;
420
+ dc->props = cmsdk_apb_watchdog_properties;
421
+}
255
+}
422
+
256
+
423
+static const TypeInfo cmsdk_apb_watchdog_info = {
257
+static const TypeInfo stm32f100_soc_info = {
424
+ .name = TYPE_CMSDK_APB_WATCHDOG,
258
+ .name = TYPE_STM32F100_SOC,
425
+ .parent = TYPE_SYS_BUS_DEVICE,
259
+ .parent = TYPE_SYS_BUS_DEVICE,
426
+ .instance_size = sizeof(CMSDKAPBWatchdog),
260
+ .instance_size = sizeof(STM32F100State),
427
+ .instance_init = cmsdk_apb_watchdog_init,
261
+ .instance_init = stm32f100_soc_initfn,
428
+ .class_init = cmsdk_apb_watchdog_class_init,
262
+ .class_init = stm32f100_soc_class_init,
429
+};
263
+};
430
+
264
+
431
+static void cmsdk_apb_watchdog_register_types(void)
265
+static void stm32f100_soc_types(void)
432
+{
266
+{
433
+ type_register_static(&cmsdk_apb_watchdog_info);
267
+ type_register_static(&stm32f100_soc_info);
434
+}
268
+}
435
+
269
+
436
+type_init(cmsdk_apb_watchdog_register_types);
270
+type_init(stm32f100_soc_types)
437
diff --git a/MAINTAINERS b/MAINTAINERS
271
diff --git a/MAINTAINERS b/MAINTAINERS
438
index XXXXXXX..XXXXXXX 100644
272
index XXXXXXX..XXXXXXX 100644
439
--- a/MAINTAINERS
273
--- a/MAINTAINERS
440
+++ b/MAINTAINERS
274
+++ b/MAINTAINERS
441
@@ -XXX,XX +XXX,XX @@ F: hw/timer/cmsdk-apb-timer.c
275
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
442
F: include/hw/timer/cmsdk-apb-timer.h
276
S: Maintained
443
F: hw/char/cmsdk-apb-uart.c
277
F: hw/arm/virt-acpi-build.c
444
F: include/hw/char/cmsdk-apb-uart.h
278
445
+F: hw/watchdog/cmsdk-apb-watchdog.c
279
+STM32F100
446
+F: include/hw/watchdog/cmsdk-apb-watchdog.h
280
+M: Alexandre Iooss <erdnaxe@crans.org>
447
F: hw/misc/tz-ppc.c
281
+L: qemu-arm@nongnu.org
448
F: include/hw/misc/tz-ppc.h
282
+S: Maintained
449
F: hw/misc/tz-mpc.c
283
+F: hw/arm/stm32f100_soc.c
450
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
284
+
285
STM32F205
286
M: Alistair Francis <alistair@alistair23.me>
287
M: Peter Maydell <peter.maydell@linaro.org>
288
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
451
index XXXXXXX..XXXXXXX 100644
289
index XXXXXXX..XXXXXXX 100644
452
--- a/default-configs/arm-softmmu.mak
290
--- a/hw/arm/Kconfig
453
+++ b/default-configs/arm-softmmu.mak
291
+++ b/hw/arm/Kconfig
454
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
292
@@ -XXX,XX +XXX,XX @@ config RASPI
455
293
select SDHCI
456
CONFIG_CMSDK_APB_TIMER=y
294
select USB_DWC2
457
CONFIG_CMSDK_APB_UART=y
295
458
+CONFIG_CMSDK_APB_WATCHDOG=y
296
+config STM32F100_SOC
459
297
+ bool
460
CONFIG_MPS2_FPGAIO=y
298
+ select ARM_V7M
461
CONFIG_MPS2_SCC=y
299
+ select STM32F2XX_USART
462
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
300
+ select STM32F2XX_SPI
463
new file mode 100644
301
+
464
index XXXXXXX..XXXXXXX
302
config STM32F205_SOC
465
--- /dev/null
303
bool
466
+++ b/hw/watchdog/trace-events
304
select ARM_V7M
467
@@ -XXX,XX +XXX,XX @@
305
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
468
+# See docs/devel/tracing.txt for syntax documentation.
306
index XXXXXXX..XXXXXXX 100644
469
+
307
--- a/hw/arm/meson.build
470
+# hw/char/cmsdk_apb_watchdog.c
308
+++ b/hw/arm/meson.build
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"
309
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c'))
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"
310
arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c'))
473
+cmsdk_apb_watchdog_reset(void) "CMSDK APB watchdog: reset"
311
arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c'))
312
arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c', 'bcm2836.c', 'raspi.c'))
313
+arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
314
arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
315
arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
316
arm_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp.c', 'xlnx-zcu102.c'))
474
--
317
--
475
2.18.0
318
2.20.1
476
319
477
320
diff view generated by jsdifflib
1
Create a new include file for the pl081's device struct,
1
From: Alexandre Iooss <erdnaxe@crans.org>
2
type macros, etc, so that it can be instantiated using
3
the "embedded struct" coding style.
4
2
3
This is a Cortex-M3 based machine. Information can be found at:
4
https://www.st.com/en/evaluation-tools/stm32vldiscovery.html
5
6
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210617165647.2575955-3-erdnaxe@crans.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
---
10
---
8
include/hw/dma/pl080.h | 62 ++++++++++++++++++++++++++++++++++++++++++
11
default-configs/devices/arm-softmmu.mak | 1 +
9
hw/dma/pl080.c | 34 ++---------------------
12
hw/arm/stm32vldiscovery.c | 66 +++++++++++++++++++++++++
10
MAINTAINERS | 1 +
13
MAINTAINERS | 6 +++
11
3 files changed, 65 insertions(+), 32 deletions(-)
14
hw/arm/Kconfig | 4 ++
12
create mode 100644 include/hw/dma/pl080.h
15
hw/arm/meson.build | 1 +
16
5 files changed, 78 insertions(+)
17
create mode 100644 hw/arm/stm32vldiscovery.c
13
18
14
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
19
diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
20
index XXXXXXX..XXXXXXX 100644
21
--- a/default-configs/devices/arm-softmmu.mak
22
+++ b/default-configs/devices/arm-softmmu.mak
23
@@ -XXX,XX +XXX,XX @@ CONFIG_CHEETAH=y
24
CONFIG_SX1=y
25
CONFIG_NSERIES=y
26
CONFIG_STELLARIS=y
27
+CONFIG_STM32VLDISCOVERY=y
28
CONFIG_REALVIEW=y
29
CONFIG_VERSATILE=y
30
CONFIG_VEXPRESS=y
31
diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c
15
new file mode 100644
32
new file mode 100644
16
index XXXXXXX..XXXXXXX
33
index XXXXXXX..XXXXXXX
17
--- /dev/null
34
--- /dev/null
18
+++ b/include/hw/dma/pl080.h
35
+++ b/hw/arm/stm32vldiscovery.c
19
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
20
+/*
37
+/*
21
+ * ARM PrimeCell PL080/PL081 DMA controller
38
+ * ST STM32VLDISCOVERY machine
22
+ *
39
+ *
23
+ * Copyright (c) 2006 CodeSourcery.
40
+ * Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
24
+ * Copyright (c) 2018 Linaro Limited
41
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
25
+ * Written by Paul Brook, Peter Maydell
26
+ *
42
+ *
27
+ * This program is free software; you can redistribute it and/or modify
43
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
28
+ * it under the terms of the GNU General Public License version 2 or
44
+ * of this software and associated documentation files (the "Software"), to deal
29
+ * (at your option) any later version.
45
+ * in the Software without restriction, including without limitation the rights
46
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
47
+ * copies of the Software, and to permit persons to whom the Software is
48
+ * furnished to do so, subject to the following conditions:
49
+ *
50
+ * The above copyright notice and this permission notice shall be included in
51
+ * all copies or substantial portions of the Software.
52
+ *
53
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
54
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
55
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
56
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
57
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
58
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
59
+ * THE SOFTWARE.
30
+ */
60
+ */
31
+
61
+
32
+/* This is a model of the Arm PrimeCell PL080/PL081 DMA controller:
62
+#include "qemu/osdep.h"
33
+ * The PL080 TRM is:
63
+#include "qapi/error.h"
34
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0196g/DDI0196.pdf
64
+#include "hw/boards.h"
35
+ * and the PL081 TRM is:
65
+#include "hw/qdev-properties.h"
36
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0218e/DDI0218.pdf
66
+#include "qemu/error-report.h"
37
+ *
67
+#include "hw/arm/stm32f100_soc.h"
38
+ * QEMU interface:
68
+#include "hw/arm/boot.h"
39
+ * + sysbus IRQ: DMACINTR combined interrupt line
40
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
41
+ */
42
+
69
+
43
+#ifndef HW_DMA_PL080_H
70
+/* stm32vldiscovery implementation is derived from netduinoplus2 */
44
+#define HW_DMA_PL080_H
45
+
71
+
46
+#include "hw/sysbus.h"
72
+/* Main SYSCLK frequency in Hz (24MHz) */
73
+#define SYSCLK_FRQ 24000000ULL
47
+
74
+
48
+#define PL080_MAX_CHANNELS 8
75
+static void stm32vldiscovery_init(MachineState *machine)
76
+{
77
+ DeviceState *dev;
49
+
78
+
50
+typedef struct {
79
+ /*
51
+ uint32_t src;
80
+ * TODO: ideally we would model the SoC RCC and let it handle
52
+ uint32_t dest;
81
+ * system_clock_scale, including its ability to define different
53
+ uint32_t lli;
82
+ * possible SYSCLK sources.
54
+ uint32_t ctrl;
83
+ */
55
+ uint32_t conf;
84
+ system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
56
+} pl080_channel;
57
+
85
+
58
+#define TYPE_PL080 "pl080"
86
+ dev = qdev_new(TYPE_STM32F100_SOC);
59
+#define TYPE_PL081 "pl081"
87
+ qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
60
+#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080)
88
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
61
+
89
+
62
+typedef struct PL080State {
90
+ armv7m_load_kernel(ARM_CPU(first_cpu),
63
+ SysBusDevice parent_obj;
91
+ machine->kernel_filename,
92
+ FLASH_SIZE);
93
+}
64
+
94
+
65
+ MemoryRegion iomem;
95
+static void stm32vldiscovery_machine_init(MachineClass *mc)
66
+ uint8_t tc_int;
96
+{
67
+ uint8_t tc_mask;
97
+ mc->desc = "ST STM32VLDISCOVERY (Cortex-M3)";
68
+ uint8_t err_int;
98
+ mc->init = stm32vldiscovery_init;
69
+ uint8_t err_mask;
99
+}
70
+ uint32_t conf;
71
+ uint32_t sync;
72
+ uint32_t req_single;
73
+ uint32_t req_burst;
74
+ pl080_channel chan[PL080_MAX_CHANNELS];
75
+ int nchannels;
76
+ /* Flag to avoid recursive DMA invocations. */
77
+ int running;
78
+ qemu_irq irq;
79
+} PL080State;
80
+
100
+
81
+#endif
101
+DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init)
82
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
102
+
83
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/dma/pl080.c
85
+++ b/hw/dma/pl080.c
86
@@ -XXX,XX +XXX,XX @@
87
#include "hw/sysbus.h"
88
#include "exec/address-spaces.h"
89
#include "qemu/log.h"
90
+#include "hw/dma/pl080.h"
91
92
-#define PL080_MAX_CHANNELS 8
93
#define PL080_CONF_E 0x1
94
#define PL080_CONF_M1 0x2
95
#define PL080_CONF_M2 0x4
96
@@ -XXX,XX +XXX,XX @@
97
#define PL080_CCTRL_D 0x02000000
98
#define PL080_CCTRL_S 0x01000000
99
100
-typedef struct {
101
- uint32_t src;
102
- uint32_t dest;
103
- uint32_t lli;
104
- uint32_t ctrl;
105
- uint32_t conf;
106
-} pl080_channel;
107
-
108
-#define TYPE_PL080 "pl080"
109
-#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080)
110
-
111
-typedef struct PL080State {
112
- SysBusDevice parent_obj;
113
-
114
- MemoryRegion iomem;
115
- uint8_t tc_int;
116
- uint8_t tc_mask;
117
- uint8_t err_int;
118
- uint8_t err_mask;
119
- uint32_t conf;
120
- uint32_t sync;
121
- uint32_t req_single;
122
- uint32_t req_burst;
123
- pl080_channel chan[PL080_MAX_CHANNELS];
124
- int nchannels;
125
- /* Flag to avoid recursive DMA invocations. */
126
- int running;
127
- qemu_irq irq;
128
-} PL080State;
129
-
130
static const VMStateDescription vmstate_pl080_channel = {
131
.name = "pl080_channel",
132
.version_id = 1,
133
@@ -XXX,XX +XXX,XX @@ static const TypeInfo pl080_info = {
134
};
135
136
static const TypeInfo pl081_info = {
137
- .name = "pl081",
138
+ .name = TYPE_PL081,
139
.parent = TYPE_PL080,
140
.instance_init = pl081_init,
141
};
142
diff --git a/MAINTAINERS b/MAINTAINERS
103
diff --git a/MAINTAINERS b/MAINTAINERS
143
index XXXXXXX..XXXXXXX 100644
104
index XXXXXXX..XXXXXXX 100644
144
--- a/MAINTAINERS
105
--- a/MAINTAINERS
145
+++ b/MAINTAINERS
106
+++ b/MAINTAINERS
146
@@ -XXX,XX +XXX,XX @@ F: hw/char/pl011.c
107
@@ -XXX,XX +XXX,XX @@ F: hw/*/stellaris*
147
F: include/hw/char/pl011.h
108
F: include/hw/input/gamepad.h
148
F: hw/display/pl110*
109
F: docs/system/arm/stellaris.rst
149
F: hw/dma/pl080.c
110
150
+F: include/hw/dma/pl080.h
111
+STM32VLDISCOVERY
151
F: hw/dma/pl330.c
112
+M: Alexandre Iooss <erdnaxe@crans.org>
152
F: hw/gpio/pl061.c
113
+L: qemu-arm@nongnu.org
153
F: hw/input/pl050.c
114
+S: Maintained
115
+F: hw/arm/stm32vldiscovery.c
116
+
117
Versatile Express
118
M: Peter Maydell <peter.maydell@linaro.org>
119
L: qemu-arm@nongnu.org
120
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/arm/Kconfig
123
+++ b/hw/arm/Kconfig
124
@@ -XXX,XX +XXX,XX @@ config STELLARIS
125
select STELLARIS_ENET # ethernet
126
select UNIMP
127
128
+config STM32VLDISCOVERY
129
+ bool
130
+ select STM32F100_SOC
131
+
132
config STRONGARM
133
bool
134
select PXA2XX
135
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/arm/meson.build
138
+++ b/hw/arm/meson.build
139
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_Z2', if_true: files('z2.c'))
140
arm_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview.c'))
141
arm_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa-ref.c'))
142
arm_ss.add(when: 'CONFIG_STELLARIS', if_true: files('stellaris.c'))
143
+arm_ss.add(when: 'CONFIG_STM32VLDISCOVERY', if_true: files('stm32vldiscovery.c'))
144
arm_ss.add(when: 'CONFIG_COLLIE', if_true: files('collie.c'))
145
arm_ss.add(when: 'CONFIG_VERSATILE', if_true: files('versatilepb.c'))
146
arm_ss.add(when: 'CONFIG_VEXPRESS', if_true: files('vexpress.c'))
154
--
147
--
155
2.18.0
148
2.20.1
156
149
157
150
diff view generated by jsdifflib
1
From: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
1
From: Alexandre Iooss <erdnaxe@crans.org>
2
2
3
Generate an interrupt if USR2_RDR and UCR4_DREN are both set.
3
This adds the target guide for Netduino 2, Netduino Plus 2 and STM32VLDISCOVERY.
4
4
5
Signed-off-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
5
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
6
Message-id: 1534341354-11956-1-git-send-email-hans-erik.floryd@rt-labs.com
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20210617165647.2575955-4-erdnaxe@crans.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
include/hw/char/imx_serial.h | 1 +
10
docs/system/arm/stm32.rst | 66 ++++++++++++++++++++++++++++++++++++++
11
hw/char/imx_serial.c | 3 ++-
11
docs/system/target-arm.rst | 1 +
12
2 files changed, 3 insertions(+), 1 deletion(-)
12
MAINTAINERS | 1 +
13
3 files changed, 68 insertions(+)
14
create mode 100644 docs/system/arm/stm32.rst
13
15
14
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
16
diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst
17
new file mode 100644
18
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
+++ b/docs/system/arm/stm32.rst
21
@@ -XXX,XX +XXX,XX @@
22
+STMicroelectronics STM32 boards (``netduino2``, ``netduinoplus2``, ``stm32vldiscovery``)
23
+========================================================================================
24
+
25
+The `STM32`_ chips are a family of 32-bit ARM-based microcontroller by
26
+STMicroelectronics.
27
+
28
+.. _STM32: https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html
29
+
30
+The STM32F1 series is based on ARM Cortex-M3 core. The following machines are
31
+based on this chip :
32
+
33
+- ``stm32vldiscovery`` STM32VLDISCOVERY board with STM32F100RBT6 microcontroller
34
+
35
+The STM32F2 series is based on ARM Cortex-M3 core. The following machines are
36
+based on this chip :
37
+
38
+- ``netduino2`` Netduino 2 board with STM32F205RFT6 microcontroller
39
+
40
+The STM32F4 series is based on ARM Cortex-M4F core. This series is pin-to-pin
41
+compatible with STM32F2 series. The following machines are based on this chip :
42
+
43
+- ``netduinoplus2`` Netduino Plus 2 board with STM32F405RGT6 microcontroller
44
+
45
+There are many other STM32 series that are currently not supported by QEMU.
46
+
47
+Supported devices
48
+-----------------
49
+
50
+ * ARM Cortex-M3, Cortex M4F
51
+ * Analog to Digital Converter (ADC)
52
+ * EXTI interrupt
53
+ * Serial ports (USART)
54
+ * SPI controller
55
+ * System configuration (SYSCFG)
56
+ * Timer controller (TIMER)
57
+
58
+Missing devices
59
+---------------
60
+
61
+ * Camera interface (DCMI)
62
+ * Controller Area Network (CAN)
63
+ * Cycle Redundancy Check (CRC) calculation unit
64
+ * Digital to Analog Converter (DAC)
65
+ * DMA controller
66
+ * Ethernet controller
67
+ * Flash Interface Unit
68
+ * GPIO controller
69
+ * I2C controller
70
+ * Inter-Integrated Sound (I2S) controller
71
+ * Power supply configuration (PWR)
72
+ * Random Number Generator (RNG)
73
+ * Real-Time Clock (RTC) controller
74
+ * Reset and Clock Controller (RCC)
75
+ * Secure Digital Input/Output (SDIO) interface
76
+ * USB OTG
77
+ * Watchdog controller (IWDG, WWDG)
78
+
79
+Boot options
80
+------------
81
+
82
+The STM32 machines can be started using the ``-kernel`` option to load a
83
+firmware. Example:
84
+
85
+.. code-block:: bash
86
+
87
+ $ qemu-system-arm -M stm32vldiscovery -kernel firmware.bin
88
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
15
index XXXXXXX..XXXXXXX 100644
89
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/char/imx_serial.h
90
--- a/docs/system/target-arm.rst
17
+++ b/include/hw/char/imx_serial.h
91
+++ b/docs/system/target-arm.rst
18
@@ -XXX,XX +XXX,XX @@
92
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
19
#define UCR2_RXEN (1<<1) /* Receiver enable */
93
arm/collie
20
#define UCR2_SRST (1<<0) /* Reset complete */
94
arm/sx1
21
95
arm/stellaris
22
+#define UCR4_DREN BIT(0) /* Receive Data Ready interrupt enable */
96
+ arm/stm32
23
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
97
arm/virt
24
98
arm/xlnx-versal-virt
25
#define UTS1_TXEMPTY (1<<6)
99
26
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
100
diff --git a/MAINTAINERS b/MAINTAINERS
27
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/char/imx_serial.c
102
--- a/MAINTAINERS
29
+++ b/hw/char/imx_serial.c
103
+++ b/MAINTAINERS
30
@@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s)
104
@@ -XXX,XX +XXX,XX @@ M: Alexandre Iooss <erdnaxe@crans.org>
31
mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
105
L: qemu-arm@nongnu.org
32
/*
106
S: Maintained
33
* TCEN and TXDC are both bit 3
107
F: hw/arm/stm32vldiscovery.c
34
+ * RDR and DREN are both bit 0
108
+F: docs/system/arm/stm32.rst
35
*/
109
36
- mask |= s->ucr4 & UCR4_TCEN;
110
Versatile Express
37
+ mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
111
M: Peter Maydell <peter.maydell@linaro.org>
38
39
usr2 = s->usr2 & mask;
40
41
--
112
--
42
2.18.0
113
2.20.1
43
114
44
115
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Alexandre Iooss <erdnaxe@crans.org>
2
2
3
The generic loader device supports the U-Boot and Intel HEX executable
3
New mini-kernel test for STM32VLDISCOVERY USART1.
4
formats in addition to the document raw and ELF formats. Reword the
5
documentation to include these formats and explain how various options
6
depend on the executable format.
7
4
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Acked-by: Thomas Huth <thuth@redhat.com>
10
Message-id: 20180816145554.9814-1-stefanha@redhat.com
7
Acked-by: Alistair Francis <alistair.francis@wdc.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20210617165647.2575955-5-erdnaxe@crans.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
docs/generic-loader.txt | 20 ++++++++++----------
11
tests/qtest/boot-serial-test.c | 37 ++++++++++++++++++++++++++++++++++
15
1 file changed, 10 insertions(+), 10 deletions(-)
12
1 file changed, 37 insertions(+)
16
13
17
diff --git a/docs/generic-loader.txt b/docs/generic-loader.txt
14
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/generic-loader.txt
16
--- a/tests/qtest/boot-serial-test.c
20
+++ b/docs/generic-loader.txt
17
+++ b/tests/qtest/boot-serial-test.c
21
@@ -XXX,XX +XXX,XX @@ An example of setting CPU 0's PC to 0x8000 is:
18
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_nrf51[] = {
22
19
0x1c, 0x25, 0x00, 0x40 /* 0x4000251c = UART TXD */
23
Loading Files
20
};
24
-------------
21
25
-The loader device also allows files to be loaded into memory. It can load raw
22
+static const uint8_t kernel_stm32vldiscovery[] = {
26
-files and ELF executable files. Raw files are loaded verbatim. ELF executable
23
+ 0x00, 0x00, 0x00, 0x00, /* Stack top address */
27
-files are loaded by an ELF loader. The syntax is shown below:
24
+ 0x1d, 0x00, 0x00, 0x00, /* Reset handler address */
28
+The loader device also allows files to be loaded into memory. It can load ELF,
25
+ 0x00, 0x00, 0x00, 0x00, /* NMI */
29
+U-Boot, and Intel HEX executable formats as well as raw images. The syntax is
26
+ 0x00, 0x00, 0x00, 0x00, /* Hard fault */
30
+shown below:
27
+ 0x00, 0x00, 0x00, 0x00, /* Memory management fault */
31
28
+ 0x00, 0x00, 0x00, 0x00, /* Bus fault */
32
-device loader,file=<file>[,addr=<addr>][,cpu-num=<cpu-num>][,force-raw=<raw>]
29
+ 0x00, 0x00, 0x00, 0x00, /* Usage fault */
33
30
+ 0x0b, 0x4b, /* ldr r3, [pc, #44] Get RCC */
34
<file> - A file to be loaded into memory
31
+ 0x44, 0xf2, 0x04, 0x02, /* movw r2, #16388 */
35
- <addr> - The addr in memory that the file should be loaded. This is
32
+ 0x1a, 0x60, /* str r2, [r3] */
36
- ignored if you are using an ELF (unless force-raw is true).
33
+ 0x0a, 0x4b, /* ldr r3, [pc, #40] Get GPIOA */
37
- This is required if you aren't loading an ELF.
34
+ 0x1a, 0x68, /* ldr r2, [r3] */
38
+ <addr> - The memory address where the file should be loaded. This is
35
+ 0x22, 0xf0, 0xf0, 0x02, /* bic r2, r2, #240 */
39
+ required for raw images and ignored for non-raw files.
36
+ 0x1a, 0x60, /* str r2, [r3] */
40
<cpu-num> - This specifies the CPU that should be used. This is an
37
+ 0x1a, 0x68, /* ldr r2, [r3] */
41
optional argument and will cause the CPU's PC to be set to
38
+ 0x42, 0xf0, 0xb0, 0x02, /* orr r2, r2, #176 */
42
- where the image is stored or in the case of an ELF file to
39
+ 0x1a, 0x60, /* str r2, [r3] */
43
- the value in the header. This option should only be used
40
+ 0x07, 0x4b, /* ldr r3, [pc, #26] Get BAUD */
44
- for the boot image.
41
+ 0x45, 0x22, /* movs r2, #69 */
45
+ the memory address where the raw file is loaded or the entry
42
+ 0x1a, 0x60, /* str r2, [r3] */
46
+ point specified in the executable format header. This option
43
+ 0x06, 0x4b, /* ldr r3, [pc, #24] Get ENABLE */
47
+ should only be used for the boot image.
44
+ 0x42, 0xf2, 0x08, 0x02, /* movw r2, #8200 */
48
This will also cause the image to be written to the specified
45
+ 0x1a, 0x60, /* str r2, [r3] */
49
CPU's address space. If not specified, the default is CPU 0.
46
+ 0x05, 0x4b, /* ldr r3, [pc, #20] Get TXD */
50
<force-raw> - Setting force-raw=on forces the file to be treated as a raw
47
+ 0x54, 0x22, /* movs r2, 'T' */
51
- image. This can be used to load ELF files as if they were raw.
48
+ 0x1a, 0x60, /* str r2, [r3] */
52
+ image. This can be used to load supported executable formats
49
+ 0xfe, 0xe7, /* b . */
53
+ as if they were raw.
50
+ 0x18, 0x10, 0x02, 0x40, /* 0x40021018 = RCC */
54
51
+ 0x04, 0x08, 0x01, 0x40, /* 0x40010804 = GPIOA */
55
All values are parsed using the standard QemuOps parsing. This allows the user
52
+ 0x08, 0x38, 0x01, 0x40, /* 0x40013808 = USART1 BAUD */
56
to specify any values in any format supported. By default the values
53
+ 0x0c, 0x38, 0x01, 0x40, /* 0x4001380c = USART1 ENABLE */
54
+ 0x04, 0x38, 0x01, 0x40 /* 0x40013804 = USART1 TXD */
55
+};
56
+
57
typedef struct testdef {
58
const char *arch; /* Target architecture */
59
const char *machine; /* Name of the machine */
60
@@ -XXX,XX +XXX,XX @@ static testdef_t tests[] = {
61
{ "aarch64", "virt", "-cpu max", "TT", sizeof(kernel_aarch64),
62
kernel_aarch64 },
63
{ "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },
64
+ { "arm", "stm32vldiscovery", "", "T",
65
+ sizeof(kernel_stm32vldiscovery), kernel_stm32vldiscovery },
66
67
{ NULL }
68
};
57
--
69
--
58
2.18.0
70
2.20.1
59
71
60
72
diff view generated by jsdifflib
1
From: Jia He <hejianet@gmail.com>
1
From: Ricardo Koller <ricarkol@google.com>
2
2
3
In scripts/arch-run.bash of kvm-unit-tests, it will check the qemu
3
icv_eoir_write() and icv_dir_write() ignore invalid virtual IRQ numbers
4
output log with:
4
(like LPIs). The issue is that these functions check against the number
5
if [ -z "$(echo "$errors" | grep -vi warning)" ]; then
5
of implemented IRQs (QEMU's default is num_irq=288) which can be lower
6
than the maximum virtual IRQ number (1020 - 1). The consequence is that
7
if a hypervisor creates an LR for an IRQ between 288 and 1020, then the
8
guest is unable to deactivate the resulting IRQ. Note that other
9
functions that deal with large IRQ numbers, like icv_iar_read, check
10
against 1020 and not against num_irq.
6
11
7
Thus without the warning prefix, all of the test fail.
12
Fix the checks by using GICV3_MAXIRQ (1020) instead of the number of
13
implemented IRQs.
8
14
9
Since it is not unrecoverable error in kvm_arm_its_reset for
15
Signed-off-by: Ricardo Koller <ricarkol@google.com>
10
current implementation, downgrading the report from error to
16
Message-id: 20210702233701.3369-1-ricarkol@google.com
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
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
19
---
18
hw/intc/arm_gicv3_its_kvm.c | 2 +-
20
hw/intc/arm_gicv3_cpuif.c | 4 ++--
19
1 file changed, 1 insertion(+), 1 deletion(-)
21
1 file changed, 2 insertions(+), 2 deletions(-)
20
22
21
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
23
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
22
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/intc/arm_gicv3_its_kvm.c
25
--- a/hw/intc/arm_gicv3_cpuif.c
24
+++ b/hw/intc/arm_gicv3_its_kvm.c
26
+++ b/hw/intc/arm_gicv3_cpuif.c
25
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_reset(DeviceState *dev)
27
@@ -XXX,XX +XXX,XX @@ static void icv_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
28
29
trace_gicv3_icv_dir_write(gicv3_redist_affid(cs), value);
30
31
- if (irq >= cs->gic->num_irq) {
32
+ if (irq >= GICV3_MAXIRQ) {
33
/* Also catches special interrupt numbers and LPIs */
26
return;
34
return;
27
}
35
}
28
36
@@ -XXX,XX +XXX,XX @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
29
- error_report("ITS KVM: full reset is not supported by the host kernel");
37
trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1,
30
+ warn_report("ITS KVM: full reset is not supported by the host kernel");
38
gicv3_redist_affid(cs), value);
31
39
32
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
40
- if (irq >= cs->gic->num_irq) {
33
GITS_CTLR)) {
41
+ if (irq >= GICV3_MAXIRQ) {
42
/* Also catches special interrupt numbers and LPIs */
43
return;
44
}
34
--
45
--
35
2.18.0
46
2.20.1
36
47
37
48
diff view generated by jsdifflib
1
The MSR (banked) and MRS (banked) instructions allow accesses to ELR_Hyp
1
Convert the use of the DPRINTF debug macro in the PL061 model to
2
from either Monitor or Hyp mode. Our translate time check
2
use tracepoints.
3
was overly strict and only permitted access from Monitor mode.
4
5
The runtime check we do in msr_mrs_banked_exc_checks() had the
6
correct code in it, but never got there because of the earlier
7
"currmode == tgtmode" check. Special case ELR_Hyp.
8
3
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180814124254.5229-9-peter.maydell@linaro.org
13
---
7
---
14
target/arm/op_helper.c | 22 +++++++++++-----------
8
hw/gpio/pl061.c | 27 +++++++++------------------
15
target/arm/translate.c | 10 +++++++---
9
hw/gpio/trace-events | 6 ++++++
16
2 files changed, 18 insertions(+), 14 deletions(-)
10
2 files changed, 15 insertions(+), 18 deletions(-)
17
11
18
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
12
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/op_helper.c
14
--- a/hw/gpio/pl061.c
21
+++ b/target/arm/op_helper.c
15
+++ b/hw/gpio/pl061.c
22
@@ -XXX,XX +XXX,XX @@ static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
16
@@ -XXX,XX +XXX,XX @@
23
*/
17
#include "qemu/log.h"
24
int curmode = env->uncached_cpsr & CPSR_M;
18
#include "qemu/module.h"
25
19
#include "qom/object.h"
26
+ if (regno == 17) {
20
-
27
+ /* ELR_Hyp: a special case because access from tgtmode is OK */
21
-//#define DEBUG_PL061 1
28
+ if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
22
-
29
+ goto undef;
23
-#ifdef DEBUG_PL061
30
+ }
24
-#define DPRINTF(fmt, ...) \
31
+ return;
25
-do { printf("pl061: " fmt , ## __VA_ARGS__); } while (0)
32
+ }
26
-#define BADF(fmt, ...) \
33
+
27
-do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
34
if (curmode == tgtmode) {
28
-#else
35
goto undef;
29
-#define DPRINTF(fmt, ...) do {} while(0)
36
}
30
-#define BADF(fmt, ...) \
37
@@ -XXX,XX +XXX,XX @@ static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
31
-do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__);} while (0)
38
}
32
-#endif
39
33
+#include "trace.h"
40
if (tgtmode == ARM_CPU_MODE_HYP) {
34
41
- switch (regno) {
35
static const uint8_t pl061_id[12] =
42
- case 17: /* ELR_Hyp */
36
{ 0x00, 0x00, 0x00, 0x00, 0x61, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
43
- if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
37
@@ -XXX,XX +XXX,XX @@ static void pl061_update(PL061State *s)
44
- goto undef;
38
uint8_t out;
45
- }
39
int i;
46
- break;
40
47
- default:
41
- DPRINTF("dir = %d, data = %d\n", s->dir, s->data);
48
- if (curmode != ARM_CPU_MODE_MON) {
42
+ trace_pl061_update(DEVICE(s)->canonical_path, s->dir, s->data);
49
- goto undef;
43
50
- }
44
/* Outputs float high. */
51
- break;
45
/* FIXME: This is board dependent. */
52
+ /* SPSR_Hyp, r13_hyp: accessible from Monitor mode only */
46
@@ -XXX,XX +XXX,XX @@ static void pl061_update(PL061State *s)
53
+ if (curmode != ARM_CPU_MODE_MON) {
47
for (i = 0; i < N_GPIOS; i++) {
54
+ goto undef;
48
mask = 1 << i;
49
if (changed & mask) {
50
- DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
51
- qemu_set_irq(s->out[i], (out & mask) != 0);
52
+ int level = (out & mask) != 0;
53
+ trace_pl061_set_output(DEVICE(s)->canonical_path, i, level);
54
+ qemu_set_irq(s->out[i], level);
55
}
55
}
56
}
56
}
57
}
57
58
@@ -XXX,XX +XXX,XX @@ static void pl061_update(PL061State *s)
58
diff --git a/target/arm/translate.c b/target/arm/translate.c
59
for (i = 0; i < N_GPIOS; i++) {
60
mask = 1 << i;
61
if (changed & mask) {
62
- DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0);
63
+ trace_pl061_input_change(DEVICE(s)->canonical_path, i,
64
+ (s->data & mask) != 0);
65
66
if (!(s->isense & mask)) {
67
/* Edge interrupt */
68
@@ -XXX,XX +XXX,XX @@ static void pl061_update(PL061State *s)
69
/* Level interrupt */
70
s->istate |= ~(s->data ^ s->iev) & s->isense;
71
72
- DPRINTF("istate = %02X\n", s->istate);
73
+ trace_pl061_update_istate(DEVICE(s)->canonical_path,
74
+ s->istate, s->im, (s->istate & s->im) != 0);
75
76
qemu_set_irq(s->irq, (s->istate & s->im) != 0);
77
}
78
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
59
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate.c
80
--- a/hw/gpio/trace-events
61
+++ b/target/arm/translate.c
81
+++ b/hw/gpio/trace-events
62
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
82
@@ -XXX,XX +XXX,XX @@ nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x
63
}
83
nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
64
break;
84
nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
65
case ARM_CPU_MODE_HYP:
85
66
- /* Note that we can forbid accesses from EL2 here because they
86
+# pl061.c
67
- * must be from Hyp mode itself
87
+pl061_update(const char *id, uint32_t dir, uint32_t data) "%s GPIODIR 0x%x GPIODATA 0x%x"
68
+ /*
88
+pl061_set_output(const char *id, int gpio, int level) "%s setting output %d to %d"
69
+ * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
89
+pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to %d"
70
+ * (and so we can forbid accesses from EL2 or below). elr_hyp
90
+pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
71
+ * can be accessed also from Hyp mode, so forbid accesses from
91
+
72
+ * EL0 or EL1.
92
# sifive_gpio.c
73
*/
93
sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
74
- if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 3) {
94
sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
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;
80
--
95
--
81
2.18.0
96
2.20.1
82
97
83
98
diff view generated by jsdifflib
1
We now support direct execution from MMIO regions in the
1
Currently the pl061_read() and pl061_write() functions handle offsets
2
core memory subsystem. This means that we don't need to
2
using a combination of three if() statements and a switch(). Clean
3
have device-specific support for it, and we can remove
3
this up to use just a switch, using case ranges.
4
the request_ptr handling from the Xilinx SPIPS device.
4
5
(It was broken anyway due to race conditions, and disabled
5
This requires that instead of catching accesses to the luminary-only
6
by default.)
6
registers on a stock PL061 via a check on s->rsvd_start we use
7
7
an "is this luminary?" check in the cases for each luminary-only
8
This device is the only in-tree user of this API.
8
register.
9
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Reviewed-by: Richard Henderson <richard.henderson@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
15
---
12
---
16
hw/ssi/xilinx_spips.c | 46 -------------------------------------------
13
hw/gpio/pl061.c | 104 ++++++++++++++++++++++++++++++++++++------------
17
1 file changed, 46 deletions(-)
14
1 file changed, 79 insertions(+), 25 deletions(-)
18
15
19
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
16
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/ssi/xilinx_spips.c
18
--- a/hw/gpio/pl061.c
22
+++ b/hw/ssi/xilinx_spips.c
19
+++ b/hw/gpio/pl061.c
23
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps spips_ops = {
20
@@ -XXX,XX +XXX,XX @@ struct PL061State {
24
21
qemu_irq irq;
25
static void xilinx_qspips_invalidate_mmio_ptr(XilinxQSPIPS *q)
22
qemu_irq out[N_GPIOS];
23
const unsigned char *id;
24
- uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */
25
};
26
27
static const VMStateDescription vmstate_pl061 = {
28
@@ -XXX,XX +XXX,XX @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
26
{
29
{
27
- XilinxSPIPS *s = &q->parent_obj;
30
PL061State *s = (PL061State *)opaque;
28
-
31
29
- if ((q->mmio_execution_enabled) && (q->lqspi_cached_addr != ~0ULL)) {
32
- if (offset < 0x400) {
30
- /* Invalidate the current mapped mmio */
33
- return s->data & (offset >> 2);
31
- memory_region_invalidate_mmio_ptr(&s->mmlqspi, q->lqspi_cached_addr,
34
- }
32
- LQSPI_CACHE_SIZE);
35
- if (offset >= s->rsvd_start && offset <= 0xfcc) {
33
- }
36
- goto err_out;
34
-
37
- }
35
q->lqspi_cached_addr = ~0ULL;
38
- if (offset >= 0xfd0 && offset < 0x1000) {
39
- return s->id[(offset - 0xfd0) >> 2];
40
- }
41
switch (offset) {
42
+ case 0x0 ... 0x3ff: /* Data */
43
+ return s->data & (offset >> 2);
44
case 0x400: /* Direction */
45
return s->dir;
46
case 0x404: /* Interrupt sense */
47
@@ -XXX,XX +XXX,XX @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
48
case 0x420: /* Alternate function select */
49
return s->afsel;
50
case 0x500: /* 2mA drive */
51
+ if (s->id != pl061_id_luminary) {
52
+ goto bad_offset;
53
+ }
54
return s->dr2r;
55
case 0x504: /* 4mA drive */
56
+ if (s->id != pl061_id_luminary) {
57
+ goto bad_offset;
58
+ }
59
return s->dr4r;
60
case 0x508: /* 8mA drive */
61
+ if (s->id != pl061_id_luminary) {
62
+ goto bad_offset;
63
+ }
64
return s->dr8r;
65
case 0x50c: /* Open drain */
66
+ if (s->id != pl061_id_luminary) {
67
+ goto bad_offset;
68
+ }
69
return s->odr;
70
case 0x510: /* Pull-up */
71
+ if (s->id != pl061_id_luminary) {
72
+ goto bad_offset;
73
+ }
74
return s->pur;
75
case 0x514: /* Pull-down */
76
+ if (s->id != pl061_id_luminary) {
77
+ goto bad_offset;
78
+ }
79
return s->pdr;
80
case 0x518: /* Slew rate control */
81
+ if (s->id != pl061_id_luminary) {
82
+ goto bad_offset;
83
+ }
84
return s->slr;
85
case 0x51c: /* Digital enable */
86
+ if (s->id != pl061_id_luminary) {
87
+ goto bad_offset;
88
+ }
89
return s->den;
90
case 0x520: /* Lock */
91
+ if (s->id != pl061_id_luminary) {
92
+ goto bad_offset;
93
+ }
94
return s->locked;
95
case 0x524: /* Commit */
96
+ if (s->id != pl061_id_luminary) {
97
+ goto bad_offset;
98
+ }
99
return s->cr;
100
case 0x528: /* Analog mode select */
101
+ if (s->id != pl061_id_luminary) {
102
+ goto bad_offset;
103
+ }
104
return s->amsel;
105
+ case 0xfd0 ... 0xfff: /* ID registers */
106
+ return s->id[(offset - 0xfd0) >> 2];
107
default:
108
+ bad_offset:
109
+ qemu_log_mask(LOG_GUEST_ERROR,
110
+ "pl061_read: Bad offset %x\n", (int)offset);
111
break;
112
}
113
-err_out:
114
- qemu_log_mask(LOG_GUEST_ERROR,
115
- "pl061_read: Bad offset %x\n", (int)offset);
116
return 0;
36
}
117
}
37
118
38
@@ -XXX,XX +XXX,XX @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
119
@@ -XXX,XX +XXX,XX @@ static void pl061_write(void *opaque, hwaddr offset,
120
PL061State *s = (PL061State *)opaque;
121
uint8_t mask;
122
123
- if (offset < 0x400) {
124
+ switch (offset) {
125
+ case 0 ... 0x3ff:
126
mask = (offset >> 2) & s->dir;
127
s->data = (s->data & ~mask) | (value & mask);
128
pl061_update(s);
129
return;
130
- }
131
- if (offset >= s->rsvd_start) {
132
- goto err_out;
133
- }
134
- switch (offset) {
135
case 0x400: /* Direction */
136
s->dir = value & 0xff;
137
break;
138
@@ -XXX,XX +XXX,XX @@ static void pl061_write(void *opaque, hwaddr offset,
139
s->afsel = (s->afsel & ~mask) | (value & mask);
140
break;
141
case 0x500: /* 2mA drive */
142
+ if (s->id != pl061_id_luminary) {
143
+ goto bad_offset;
144
+ }
145
s->dr2r = value & 0xff;
146
break;
147
case 0x504: /* 4mA drive */
148
+ if (s->id != pl061_id_luminary) {
149
+ goto bad_offset;
150
+ }
151
s->dr4r = value & 0xff;
152
break;
153
case 0x508: /* 8mA drive */
154
+ if (s->id != pl061_id_luminary) {
155
+ goto bad_offset;
156
+ }
157
s->dr8r = value & 0xff;
158
break;
159
case 0x50c: /* Open drain */
160
+ if (s->id != pl061_id_luminary) {
161
+ goto bad_offset;
162
+ }
163
s->odr = value & 0xff;
164
break;
165
case 0x510: /* Pull-up */
166
+ if (s->id != pl061_id_luminary) {
167
+ goto bad_offset;
168
+ }
169
s->pur = value & 0xff;
170
break;
171
case 0x514: /* Pull-down */
172
+ if (s->id != pl061_id_luminary) {
173
+ goto bad_offset;
174
+ }
175
s->pdr = value & 0xff;
176
break;
177
case 0x518: /* Slew rate control */
178
+ if (s->id != pl061_id_luminary) {
179
+ goto bad_offset;
180
+ }
181
s->slr = value & 0xff;
182
break;
183
case 0x51c: /* Digital enable */
184
+ if (s->id != pl061_id_luminary) {
185
+ goto bad_offset;
186
+ }
187
s->den = value & 0xff;
188
break;
189
case 0x520: /* Lock */
190
+ if (s->id != pl061_id_luminary) {
191
+ goto bad_offset;
192
+ }
193
s->locked = (value != 0xacce551);
194
break;
195
case 0x524: /* Commit */
196
+ if (s->id != pl061_id_luminary) {
197
+ goto bad_offset;
198
+ }
199
if (!s->locked)
200
s->cr = value & 0xff;
201
break;
202
case 0x528:
203
+ if (s->id != pl061_id_luminary) {
204
+ goto bad_offset;
205
+ }
206
s->amsel = value & 0xff;
207
break;
208
default:
209
- goto err_out;
210
+ bad_offset:
211
+ qemu_log_mask(LOG_GUEST_ERROR,
212
+ "pl061_write: Bad offset %x\n", (int)offset);
213
+ return;
39
}
214
}
215
pl061_update(s);
216
return;
217
-err_out:
218
- qemu_log_mask(LOG_GUEST_ERROR,
219
- "pl061_write: Bad offset %x\n", (int)offset);
40
}
220
}
41
221
42
-static void *lqspi_request_mmio_ptr(void *opaque, hwaddr addr, unsigned *size,
222
static void pl061_reset(DeviceState *dev)
43
- unsigned *offset)
223
@@ -XXX,XX +XXX,XX @@ static void pl061_luminary_init(Object *obj)
44
-{
224
PL061State *s = PL061(obj);
45
- XilinxQSPIPS *q = opaque;
225
46
- hwaddr offset_within_the_region;
226
s->id = pl061_id_luminary;
47
-
227
- s->rsvd_start = 0x52c;
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)
61
{
62
@@ -XXX,XX +XXX,XX @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
63
64
static const MemoryRegionOps lqspi_ops = {
65
.read = lqspi_read,
66
- .request_ptr = lqspi_request_mmio_ptr,
67
.endianness = DEVICE_NATIVE_ENDIAN,
68
.valid = {
69
.min_access_size = 1,
70
@@ -XXX,XX +XXX,XX @@ static void xilinx_qspips_realize(DeviceState *dev, Error **errp)
71
sysbus_init_mmio(sbd, &s->mmlqspi);
72
73
q->lqspi_cached_addr = ~0ULL;
74
-
75
- /* mmio_execution breaks migration better aborting than having strange
76
- * bugs.
77
- */
78
- if (q->mmio_execution_enabled) {
79
- error_setg(&q->migration_blocker,
80
- "enabling mmio_execution breaks migration");
81
- migrate_add_blocker(q->migration_blocker, &error_fatal);
82
- }
83
}
228
}
84
229
85
static void xlnx_zynqmp_qspips_realize(DeviceState *dev, Error **errp)
230
static void pl061_init(Object *obj)
86
@@ -XXX,XX +XXX,XX @@ static Property xilinx_zynqmp_qspips_properties[] = {
231
@@ -XXX,XX +XXX,XX @@ static void pl061_init(Object *obj)
87
DEFINE_PROP_END_OF_LIST(),
232
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
88
};
233
89
234
s->id = pl061_id;
90
-static Property xilinx_qspips_properties[] = {
235
- s->rsvd_start = 0x424;
91
- /* We had to turn this off for 2.10 as it is not compatible with migration.
236
92
- * It can be enabled but will prevent the device to be migrated.
237
memory_region_init_io(&s->iomem, obj, &pl061_ops, s, "pl061", 0x1000);
93
- * This will go aways when a fix will be released.
238
sysbus_init_mmio(sbd, &s->iomem);
94
- */
95
- DEFINE_PROP_BOOL("x-mmio-exec", XilinxQSPIPS, mmio_execution_enabled,
96
- false),
97
- DEFINE_PROP_END_OF_LIST(),
98
-};
99
-
100
static Property xilinx_spips_properties[] = {
101
DEFINE_PROP_UINT8("num-busses", XilinxSPIPS, num_busses, 1),
102
DEFINE_PROP_UINT8("num-ss-bits", XilinxSPIPS, num_cs, 4),
103
@@ -XXX,XX +XXX,XX @@ static void xilinx_qspips_class_init(ObjectClass *klass, void * data)
104
XilinxSPIPSClass *xsc = XILINX_SPIPS_CLASS(klass);
105
106
dc->realize = xilinx_qspips_realize;
107
- dc->props = xilinx_qspips_properties;
108
xsc->reg_ops = &qspips_ops;
109
xsc->rx_fifo_size = RXFF_A_Q;
110
xsc->tx_fifo_size = TXFF_A_Q;
111
--
239
--
112
2.18.0
240
2.20.1
113
241
114
242
diff view generated by jsdifflib
1
The PL08x model currently will unconditionally call hw_error()
1
Add tracepoints for reads and writes to the PL061 registers. This requires
2
if the DMA engine is enabled by the guest. This has been
2
restructuring pl061_read() to only return after the tracepoint, rather
3
present since the PL080 model was edded in 2006, and is
3
than having lots of early-returns.
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).
10
4
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
---
8
---
14
hw/dma/pl080.c | 1 -
9
hw/gpio/pl061.c | 70 ++++++++++++++++++++++++++++++--------------
15
1 file changed, 1 deletion(-)
10
hw/gpio/trace-events | 2 ++
11
2 files changed, 50 insertions(+), 22 deletions(-)
16
12
17
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
13
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/dma/pl080.c
15
--- a/hw/gpio/pl061.c
20
+++ b/hw/dma/pl080.c
16
+++ b/hw/gpio/pl061.c
21
@@ -XXX,XX +XXX,XX @@ static void pl080_run(PL080State *s)
17
@@ -XXX,XX +XXX,XX @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
22
if ((s->conf & PL080_CONF_E) == 0)
18
unsigned size)
23
return;
19
{
24
20
PL061State *s = (PL061State *)opaque;
25
-hw_error("DMA active\n");
21
+ uint64_t r = 0;
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
switch (offset) {
28
if (s->running) {
24
case 0x0 ... 0x3ff: /* Data */
25
- return s->data & (offset >> 2);
26
+ r = s->data & (offset >> 2);
27
+ break;
28
case 0x400: /* Direction */
29
- return s->dir;
30
+ r = s->dir;
31
+ break;
32
case 0x404: /* Interrupt sense */
33
- return s->isense;
34
+ r = s->isense;
35
+ break;
36
case 0x408: /* Interrupt both edges */
37
- return s->ibe;
38
+ r = s->ibe;
39
+ break;
40
case 0x40c: /* Interrupt event */
41
- return s->iev;
42
+ r = s->iev;
43
+ break;
44
case 0x410: /* Interrupt mask */
45
- return s->im;
46
+ r = s->im;
47
+ break;
48
case 0x414: /* Raw interrupt status */
49
- return s->istate;
50
+ r = s->istate;
51
+ break;
52
case 0x418: /* Masked interrupt status */
53
- return s->istate & s->im;
54
+ r = s->istate & s->im;
55
+ break;
56
case 0x420: /* Alternate function select */
57
- return s->afsel;
58
+ r = s->afsel;
59
+ break;
60
case 0x500: /* 2mA drive */
61
if (s->id != pl061_id_luminary) {
62
goto bad_offset;
63
}
64
- return s->dr2r;
65
+ r = s->dr2r;
66
+ break;
67
case 0x504: /* 4mA drive */
68
if (s->id != pl061_id_luminary) {
69
goto bad_offset;
70
}
71
- return s->dr4r;
72
+ r = s->dr4r;
73
+ break;
74
case 0x508: /* 8mA drive */
75
if (s->id != pl061_id_luminary) {
76
goto bad_offset;
77
}
78
- return s->dr8r;
79
+ r = s->dr8r;
80
+ break;
81
case 0x50c: /* Open drain */
82
if (s->id != pl061_id_luminary) {
83
goto bad_offset;
84
}
85
- return s->odr;
86
+ r = s->odr;
87
+ break;
88
case 0x510: /* Pull-up */
89
if (s->id != pl061_id_luminary) {
90
goto bad_offset;
91
}
92
- return s->pur;
93
+ r = s->pur;
94
+ break;
95
case 0x514: /* Pull-down */
96
if (s->id != pl061_id_luminary) {
97
goto bad_offset;
98
}
99
- return s->pdr;
100
+ r = s->pdr;
101
+ break;
102
case 0x518: /* Slew rate control */
103
if (s->id != pl061_id_luminary) {
104
goto bad_offset;
105
}
106
- return s->slr;
107
+ r = s->slr;
108
+ break;
109
case 0x51c: /* Digital enable */
110
if (s->id != pl061_id_luminary) {
111
goto bad_offset;
112
}
113
- return s->den;
114
+ r = s->den;
115
+ break;
116
case 0x520: /* Lock */
117
if (s->id != pl061_id_luminary) {
118
goto bad_offset;
119
}
120
- return s->locked;
121
+ r = s->locked;
122
+ break;
123
case 0x524: /* Commit */
124
if (s->id != pl061_id_luminary) {
125
goto bad_offset;
126
}
127
- return s->cr;
128
+ r = s->cr;
129
+ break;
130
case 0x528: /* Analog mode select */
131
if (s->id != pl061_id_luminary) {
132
goto bad_offset;
133
}
134
- return s->amsel;
135
+ r = s->amsel;
136
+ break;
137
case 0xfd0 ... 0xfff: /* ID registers */
138
- return s->id[(offset - 0xfd0) >> 2];
139
+ r = s->id[(offset - 0xfd0) >> 2];
140
+ break;
141
default:
142
bad_offset:
143
qemu_log_mask(LOG_GUEST_ERROR,
144
"pl061_read: Bad offset %x\n", (int)offset);
145
break;
146
}
147
- return 0;
148
+
149
+ trace_pl061_read(DEVICE(s)->canonical_path, offset, r);
150
+ return r;
151
}
152
153
static void pl061_write(void *opaque, hwaddr offset,
154
@@ -XXX,XX +XXX,XX @@ static void pl061_write(void *opaque, hwaddr offset,
155
PL061State *s = (PL061State *)opaque;
156
uint8_t mask;
157
158
+ trace_pl061_write(DEVICE(s)->canonical_path, offset, value);
159
+
160
switch (offset) {
161
case 0 ... 0x3ff:
162
mask = (offset >> 2) & s->dir;
163
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
164
index XXXXXXX..XXXXXXX 100644
165
--- a/hw/gpio/trace-events
166
+++ b/hw/gpio/trace-events
167
@@ -XXX,XX +XXX,XX @@ pl061_update(const char *id, uint32_t dir, uint32_t data) "%s GPIODIR 0x%x GPIOD
168
pl061_set_output(const char *id, int gpio, int level) "%s setting output %d to %d"
169
pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to %d"
170
pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
171
+pl061_read(const char *id, uint64_t offset, uint64_t r) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
172
+pl061_write(const char *id, uint64_t offset, uint64_t value) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
173
174
# sifive_gpio.c
175
sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
29
--
176
--
30
2.18.0
177
2.20.1
31
178
32
179
diff view generated by jsdifflib
1
The PL080 and PL081 have three outgoing interrupt lines:
1
Add a comment documenting the "QEMU interface" of this device:
2
* DMACINTERR signals DMA errors
2
which MMIO regions, IRQ lines, GPIO lines, etc it exposes.
3
* DMACINTTC is the DMA count interrupt
4
* DMACINTR is a combined interrupt, the logical OR of the other two
5
6
We currently only implement DMACINTR, because that's all the
7
realview and versatile boards needed, but the instances of the
8
PL081 in the MPS2 firmware images use all three interrupt lines.
9
Implement the missing DMACINTERR and DMACINTTC.
10
3
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
---
6
---
14
include/hw/dma/pl080.h | 6 +++++-
7
hw/gpio/pl061.c | 7 +++++++
15
hw/dma/pl080.c | 13 ++++++++-----
8
1 file changed, 7 insertions(+)
16
2 files changed, 13 insertions(+), 6 deletions(-)
17
9
18
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
10
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
19
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/dma/pl080.h
12
--- a/hw/gpio/pl061.c
21
+++ b/include/hw/dma/pl080.h
13
+++ b/hw/gpio/pl061.c
22
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@
23
* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0218e/DDI0218.pdf
15
* Written by Paul Brook
24
*
16
*
25
* QEMU interface:
17
* This code is licensed under the GPL.
26
- * + sysbus IRQ: DMACINTR combined interrupt line
18
+ *
27
+ * + sysbus IRQ 0: DMACINTR combined interrupt line
19
+ * QEMU interface:
28
+ * + sysbus IRQ 1: DMACINTERR error interrupt request
20
+ * + sysbus MMIO region 0: the device registers
29
+ * + sysbus IRQ 2: DMACINTTC count interrupt request
21
+ * + sysbus IRQ: the GPIOINTR interrupt line
30
* + sysbus MMIO region 0: MemoryRegion for the device's registers
22
+ * + unnamed GPIO inputs 0..7: inputs to connect to the emulated GPIO lines
23
+ * + unnamed GPIO outputs 0..7: the emulated GPIO lines, considered as
24
+ * outputs
31
*/
25
*/
32
26
33
@@ -XXX,XX +XXX,XX @@ typedef struct PL080State {
27
#include "qemu/osdep.h"
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);
61
}
62
63
static void pl080_run(PL080State *s)
64
@@ -XXX,XX +XXX,XX @@ static void pl080_init(Object *obj)
65
memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
66
sysbus_init_mmio(sbd, &s->iomem);
67
sysbus_init_irq(sbd, &s->irq);
68
+ sysbus_init_irq(sbd, &s->interr);
69
+ sysbus_init_irq(sbd, &s->inttc);
70
s->nchannels = 8;
71
}
72
73
--
28
--
74
2.18.0
29
2.20.1
75
30
76
31
diff view generated by jsdifflib
1
The PL080/PL081 model is missing a reset function; implement it.
1
The Luminary variant of the PL061 has registers GPIOPUR and GPIOPDR
2
which lets the guest configure whether the GPIO lines are pull-up,
3
pull-down, or truly floating. Instead of assuming all lines are pulled
4
high, honour the PUR and PDR registers.
5
6
For the plain PL061, continue to assume that lines have an external
7
pull-up resistor, as we did before.
8
9
The stellaris board actually relies on this behaviour -- the CD line
10
of the ssd0323 display device is connected to GPIO output C7, and it
11
is only because of a different bug which we're about to fix that we
12
weren't incorrectly driving this line high on reset and putting the
13
ssd0323 into data mode.
2
14
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
17
---
6
hw/dma/pl080.c | 25 +++++++++++++++++++++++++
18
hw/gpio/pl061.c | 58 +++++++++++++++++++++++++++++++++++++++++---
7
1 file changed, 25 insertions(+)
19
hw/gpio/trace-events | 2 +-
20
2 files changed, 55 insertions(+), 5 deletions(-)
8
21
9
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
22
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
10
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
11
--- a/hw/dma/pl080.c
24
--- a/hw/gpio/pl061.c
12
+++ b/hw/dma/pl080.c
25
+++ b/hw/gpio/pl061.c
13
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps pl080_ops = {
26
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl061 = {
14
.endianness = DEVICE_NATIVE_ENDIAN,
27
}
15
};
28
};
16
29
17
+static void pl080_reset(DeviceState *dev)
30
+static uint8_t pl061_floating(PL061State *s)
18
+{
31
+{
19
+ PL080State *s = PL080(dev);
32
+ /*
20
+ int i;
33
+ * Return mask of bits which correspond to pins configured as inputs
34
+ * and which are floating (neither pulled up to 1 nor down to 0).
35
+ */
36
+ uint8_t floating;
21
+
37
+
22
+ s->tc_int = 0;
38
+ if (s->id == pl061_id_luminary) {
23
+ s->tc_mask = 0;
39
+ /*
24
+ s->err_int = 0;
40
+ * If both PUR and PDR bits are clear, there is neither a pullup
25
+ s->err_mask = 0;
41
+ * nor a pulldown in place, and the output truly floats.
26
+ s->conf = 0;
42
+ */
27
+ s->sync = 0;
43
+ floating = ~(s->pur | s->pdr);
28
+ s->req_single = 0;
44
+ } else {
29
+ s->req_burst = 0;
45
+ /* Assume outputs are pulled high. FIXME: this is board dependent. */
30
+ s->running = 0;
46
+ floating = 0;
31
+
32
+ for (i = 0; i < s->nchannels; i++) {
33
+ s->chan[i].src = 0;
34
+ s->chan[i].dest = 0;
35
+ s->chan[i].lli = 0;
36
+ s->chan[i].ctrl = 0;
37
+ s->chan[i].conf = 0;
38
+ }
47
+ }
48
+ return floating & ~s->dir;
39
+}
49
+}
40
+
50
+
41
static void pl080_init(Object *obj)
51
+static uint8_t pl061_pullups(PL061State *s)
52
+{
53
+ /*
54
+ * Return mask of bits which correspond to pins configured as inputs
55
+ * and which are pulled up to 1.
56
+ */
57
+ uint8_t pullups;
58
+
59
+ if (s->id == pl061_id_luminary) {
60
+ /*
61
+ * The Luminary variant of the PL061 has an extra registers which
62
+ * the guest can use to configure whether lines should be pullup
63
+ * or pulldown.
64
+ */
65
+ pullups = s->pur;
66
+ } else {
67
+ /* Assume outputs are pulled high. FIXME: this is board dependent. */
68
+ pullups = 0xff;
69
+ }
70
+ return pullups & ~s->dir;
71
+}
72
+
73
static void pl061_update(PL061State *s)
42
{
74
{
43
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
75
uint8_t changed;
44
@@ -XXX,XX +XXX,XX @@ static void pl080_class_init(ObjectClass *oc, void *data)
76
uint8_t mask;
45
dc->vmsd = &vmstate_pl080;
77
uint8_t out;
46
dc->realize = pl080_realize;
78
int i;
47
dc->props = pl080_properties;
79
+ uint8_t pullups = pl061_pullups(s);
48
+ dc->reset = pl080_reset;
80
+ uint8_t floating = pl061_floating(s);
49
}
81
50
82
- trace_pl061_update(DEVICE(s)->canonical_path, s->dir, s->data);
51
static const TypeInfo pl080_info = {
83
+ trace_pl061_update(DEVICE(s)->canonical_path, s->dir, s->data,
84
+ pullups, floating);
85
86
- /* Outputs float high. */
87
- /* FIXME: This is board dependent. */
88
- out = (s->data & s->dir) | ~s->dir;
89
+ /*
90
+ * Pins configured as output are driven from the data register;
91
+ * otherwise if they're pulled up they're 1, and if they're floating
92
+ * then we give them the same value they had previously, so we don't
93
+ * report any change to the other end.
94
+ */
95
+ out = (s->data & s->dir) | pullups | (s->old_out_data & floating);
96
changed = s->old_out_data ^ out;
97
if (changed) {
98
s->old_out_data = out;
99
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/gpio/trace-events
102
+++ b/hw/gpio/trace-events
103
@@ -XXX,XX +XXX,XX @@ nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
104
nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
105
106
# pl061.c
107
-pl061_update(const char *id, uint32_t dir, uint32_t data) "%s GPIODIR 0x%x GPIODATA 0x%x"
108
+pl061_update(const char *id, uint32_t dir, uint32_t data, uint32_t pullups, uint32_t floating) "%s GPIODIR 0x%x GPIODATA 0x%x pullups 0x%x floating 0x%x"
109
pl061_set_output(const char *id, int gpio, int level) "%s setting output %d to %d"
110
pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to %d"
111
pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
52
--
112
--
53
2.18.0
113
2.20.1
54
114
55
115
diff view generated by jsdifflib
1
Currently our PL080/PL081 model uses a combination of the CPU's
1
The PL061 GPIO does not itself include pullup or pulldown resistors
2
address space (via cpu_physical_memory_{read,write}()) and the
2
to set the value of a GPIO line treated as an output when it is
3
system address space for performing DMA accesses.
3
configured as an input (ie when the PL061 itself is not driving it).
4
In real hardware it is up to the board to add suitable pullups or
5
pulldowns. Currently our implementation hardwires this to "outputs
6
pulled high", which is correct for some boards (eg the realview ones:
7
see figure 3-29 in the "RealView Platform Baseboard for ARM926EJ-S
8
User Guide" DUI0224I), but wrong for others.
4
9
5
For the PL081s in the MPS FPGA images, their DMA accesses
10
In particular, the wiring in the 'virt' board and the gpio-pwr device
6
must go via Master Security Controllers. Switch the
11
assumes that wires should be pulled low, because otherwise the
7
PL080/PL081 model to take a MemoryRegion property which
12
pull-to-high will trigger a shutdown or reset action. (The only
8
defines its downstream for making DMA accesses.
13
reason this doesn't happen immediately on startup is due to another
14
bug in the PL061, where we don't assert the GPIOs to the correct
15
value on reset, but will do so as soon as the guest touches a
16
register and pl061_update() gets called.)
9
17
10
Since the PL08x are only used in two board models, we
18
Add properties to the pl061 so the board can configure whether it
11
make provision of the 'downstream' link mandatory and convert
19
wants GPIO lines to have pullup, pulldown, or neither.
12
both users at once, rather than having it be optional with
13
a default to the system address space.
14
20
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
---
23
---
18
include/hw/dma/pl080.h | 5 +++++
24
hw/gpio/pl061.c | 51 +++++++++++++++++++++++++++++++++++++++++++++----
19
hw/arm/realview.c | 8 +++++++-
25
1 file changed, 47 insertions(+), 4 deletions(-)
20
hw/arm/versatilepb.c | 9 ++++++++-
21
hw/dma/pl080.c | 35 +++++++++++++++++++++++++++++------
22
4 files changed, 49 insertions(+), 8 deletions(-)
23
26
24
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
27
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
25
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/dma/pl080.h
29
--- a/hw/gpio/pl061.c
27
+++ b/include/hw/dma/pl080.h
30
+++ b/hw/gpio/pl061.c
28
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
29
* + sysbus IRQ 1: DMACINTERR error interrupt request
32
* + unnamed GPIO inputs 0..7: inputs to connect to the emulated GPIO lines
30
* + sysbus IRQ 2: DMACINTTC count interrupt request
33
* + unnamed GPIO outputs 0..7: the emulated GPIO lines, considered as
31
* + sysbus MMIO region 0: MemoryRegion for the device's registers
34
* outputs
32
+ * + QOM property "downstream": MemoryRegion defining where DMA
35
+ * + QOM property "pullups": an integer defining whether non-floating lines
33
+ * bus master transactions are made
36
+ * configured as inputs should be pulled up to logical 1 (ie whether in
37
+ * real hardware they have a pullup resistor on the line out of the PL061).
38
+ * This should be an 8-bit value, where bit 0 is 1 if GPIO line 0 should
39
+ * be pulled high, bit 1 configures line 1, and so on. The default is 0xff,
40
+ * indicating that all GPIO lines are pulled up to logical 1.
41
+ * + QOM property "pulldowns": an integer defining whether non-floating lines
42
+ * configured as inputs should be pulled down to logical 0 (ie whether in
43
+ * real hardware they have a pulldown resistor on the line out of the PL061).
44
+ * This should be an 8-bit value, where bit 0 is 1 if GPIO line 0 should
45
+ * be pulled low, bit 1 configures line 1, and so on. The default is 0x0.
46
+ * It is an error to set a bit in both "pullups" and "pulldowns". If a bit
47
+ * is 0 in both, then the line is considered to be floating, and it will
48
+ * not have qemu_set_irq() called on it when it is configured as an input.
34
*/
49
*/
35
50
36
#ifndef HW_DMA_PL080_H
51
#include "qemu/osdep.h"
37
@@ -XXX,XX +XXX,XX @@ typedef struct PL080State {
52
#include "hw/irq.h"
53
#include "hw/sysbus.h"
54
+#include "hw/qdev-properties.h"
55
#include "migration/vmstate.h"
56
+#include "qapi/error.h"
57
#include "qemu/log.h"
58
#include "qemu/module.h"
59
#include "qom/object.h"
60
@@ -XXX,XX +XXX,XX @@ struct PL061State {
38
qemu_irq irq;
61
qemu_irq irq;
39
qemu_irq interr;
62
qemu_irq out[N_GPIOS];
40
qemu_irq inttc;
63
const unsigned char *id;
64
+ /* Properties, for non-Luminary PL061 */
65
+ uint32_t pullups;
66
+ uint32_t pulldowns;
67
};
68
69
static const VMStateDescription vmstate_pl061 = {
70
@@ -XXX,XX +XXX,XX @@ static uint8_t pl061_floating(PL061State *s)
71
*/
72
floating = ~(s->pur | s->pdr);
73
} else {
74
- /* Assume outputs are pulled high. FIXME: this is board dependent. */
75
- floating = 0;
76
+ floating = ~(s->pullups | s->pulldowns);
77
}
78
return floating & ~s->dir;
79
}
80
@@ -XXX,XX +XXX,XX @@ static uint8_t pl061_pullups(PL061State *s)
81
*/
82
pullups = s->pur;
83
} else {
84
- /* Assume outputs are pulled high. FIXME: this is board dependent. */
85
- pullups = 0xff;
86
+ pullups = s->pullups;
87
}
88
return pullups & ~s->dir;
89
}
90
@@ -XXX,XX +XXX,XX @@ static void pl061_init(Object *obj)
91
qdev_init_gpio_out(dev, s->out, N_GPIOS);
92
}
93
94
+static void pl061_realize(DeviceState *dev, Error **errp)
95
+{
96
+ PL061State *s = PL061(dev);
41
+
97
+
42
+ MemoryRegion *downstream;
98
+ if (s->pullups > 0xff) {
43
+ AddressSpace downstream_as;
99
+ error_setg(errp, "pullups property must be between 0 and 0xff");
44
} PL080State;
45
46
#endif
47
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/realview.c
50
+++ b/hw/arm/realview.c
51
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
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;
143
}
144
145
+static void pl080_realize(DeviceState *dev, Error **errp)
146
+{
147
+ PL080State *s = PL080(dev);
148
+
149
+ if (!s->downstream) {
150
+ error_setg(errp, "PL080 'downstream' link not set");
151
+ return;
100
+ return;
152
+ }
101
+ }
153
+
102
+ if (s->pulldowns > 0xff) {
154
+ address_space_init(&s->downstream_as, s->downstream, "pl080-downstream");
103
+ error_setg(errp, "pulldowns property must be between 0 and 0xff");
104
+ return;
105
+ }
106
+ if (s->pullups & s->pulldowns) {
107
+ error_setg(errp, "no bit may be set both in pullups and pulldowns");
108
+ return;
109
+ }
155
+}
110
+}
156
+
111
+
157
static void pl081_init(Object *obj)
112
+static Property pl061_props[] = {
158
{
113
+ DEFINE_PROP_UINT32("pullups", PL061State, pullups, 0xff),
159
PL080State *s = PL080(obj);
114
+ DEFINE_PROP_UINT32("pulldowns", PL061State, pulldowns, 0x0),
160
@@ -XXX,XX +XXX,XX @@ static void pl081_init(Object *obj)
115
+ DEFINE_PROP_END_OF_LIST()
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
+};
116
+};
169
+
117
+
170
static void pl080_class_init(ObjectClass *oc, void *data)
118
static void pl061_class_init(ObjectClass *klass, void *data)
171
{
119
{
172
DeviceClass *dc = DEVICE_CLASS(oc);
120
DeviceClass *dc = DEVICE_CLASS(klass);
173
121
174
dc->vmsd = &vmstate_pl080;
122
dc->vmsd = &vmstate_pl061;
175
+ dc->realize = pl080_realize;
123
dc->reset = &pl061_reset;
176
+ dc->props = pl080_properties;
124
+ dc->realize = pl061_realize;
125
+ device_class_set_props(dc, pl061_props);
177
}
126
}
178
127
179
static const TypeInfo pl080_info = {
128
static const TypeInfo pl061_info = {
180
--
129
--
181
2.18.0
130
2.20.1
182
131
183
132
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
For the virt board we have two PL061 devices -- one for NonSecure which
2
is inputs only, and one for Secure which is outputs only. For the former,
3
we don't care whether its outputs are pulled low or high when the line is
4
configured as an input, because we don't connect them. For the latter,
5
we do care, because we wire the lines up to the gpio-pwr device, which
6
assumes that level 1 means "do the action" and 1 means "do nothing".
7
For consistency in case we add more outputs in future, configure both
8
PL061s to pull GPIO lines down to 0.
2
9
3
Signed-off-by: Andrew Jones <drjones@redhat.com>
10
Reported-by: Maxim Uvarov <maxim.uvarov@linaro.org>
4
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
13
---
8
hw/arm/virt.c | 23 +++++++++++++++++------
14
hw/arm/virt.c | 3 +++
9
1 file changed, 17 insertions(+), 6 deletions(-)
15
1 file changed, 3 insertions(+)
10
16
11
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
17
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/virt.c
19
--- a/hw/arm/virt.c
14
+++ b/hw/arm/virt.c
20
+++ b/hw/arm/virt.c
15
@@ -XXX,XX +XXX,XX @@ static void machvirt_machine_init(void)
21
@@ -XXX,XX +XXX,XX @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
16
}
22
MachineState *ms = MACHINE(vms);
17
type_init(machvirt_machine_init);
23
18
24
pl061_dev = qdev_new("pl061");
19
-#define VIRT_COMPAT_2_12 \
25
+ /* Pull lines down to 0 if not driven by the PL061 */
20
- HW_COMPAT_2_12
26
+ qdev_prop_set_uint32(pl061_dev, "pullups", 0);
21
-
27
+ qdev_prop_set_uint32(pl061_dev, "pulldowns", 0xff);
22
-static void virt_3_0_instance_init(Object *obj)
28
s = SYS_BUS_DEVICE(pl061_dev);
23
+static void virt_3_1_instance_init(Object *obj)
29
sysbus_realize_and_unref(s, &error_fatal);
24
{
30
memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
25
VirtMachineState *vms = VIRT_MACHINE(obj);
26
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
27
@@ -XXX,XX +XXX,XX @@ static void virt_3_0_instance_init(Object *obj)
28
vms->irqmap = a15irqmap;
29
}
30
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)
39
+{
40
+ virt_3_1_instance_init(obj);
41
+}
42
+
43
+static void virt_machine_3_0_options(MachineClass *mc)
44
+{
45
+ virt_machine_3_1_options(mc);
46
+}
47
+DEFINE_VIRT_MACHINE(3, 0)
48
+
49
+#define VIRT_COMPAT_2_12 \
50
+ HW_COMPAT_2_12
51
52
static void virt_2_12_instance_init(Object *obj)
53
{
54
--
31
--
55
2.18.0
32
2.20.1
56
33
57
34
diff view generated by jsdifflib
1
Move the m48t59 device away from using old_mmio MemoryRegionOps
1
The PL061 comes out of reset with all its lines configured as input,
2
accessors.
2
which means they might need to be pulled to 0 or 1 depending on the
3
'pullups' and 'pulldowns' properties. Currently we do not assert
4
these lines on reset; they will only be set whenever the guest first
5
touches a register that triggers a call to pl061_update().
6
7
Convert the device to three-phase reset so we have a place where we
8
can safely call qemu_set_irq() to set the floating lines to their
9
correct values.
3
10
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180802180602.22047-1-peter.maydell@linaro.org
8
---
14
---
9
hw/timer/m48t59.c | 59 +++++++++--------------------------------------
15
hw/gpio/pl061.c | 29 +++++++++++++++++++++++++----
10
1 file changed, 11 insertions(+), 48 deletions(-)
16
hw/gpio/trace-events | 1 +
17
2 files changed, 26 insertions(+), 4 deletions(-)
11
18
12
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
19
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/timer/m48t59.c
21
--- a/hw/gpio/pl061.c
15
+++ b/hw/timer/m48t59.c
22
+++ b/hw/gpio/pl061.c
16
@@ -XXX,XX +XXX,XX @@ static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size)
23
@@ -XXX,XX +XXX,XX @@ static void pl061_write(void *opaque, hwaddr offset,
17
return retval;
24
return;
18
}
25
}
19
26
20
-static void nvram_writeb (void *opaque, hwaddr addr, uint32_t value)
27
-static void pl061_reset(DeviceState *dev)
21
-{
28
+static void pl061_enter_reset(Object *obj, ResetType type)
22
- M48t59State *NVRAM = opaque;
23
-
24
- m48t59_write(NVRAM, addr, value & 0xff);
25
-}
26
-
27
-static void nvram_writew (void *opaque, hwaddr addr, uint32_t value)
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)
47
{
29
{
48
M48t59State *NVRAM = opaque;
30
- PL061State *s = PL061(dev);
49
31
+ PL061State *s = PL061(obj);
50
return m48t59_read(NVRAM, addr);
32
+
33
+ trace_pl061_reset(DEVICE(s)->canonical_path);
34
35
/* reset values from PL061 TRM, Stellaris LM3S5P31 & LM3S8962 Data Sheet */
36
s->data = 0;
37
- s->old_out_data = 0;
38
s->old_in_data = 0;
39
s->dir = 0;
40
s->isense = 0;
41
@@ -XXX,XX +XXX,XX @@ static void pl061_reset(DeviceState *dev)
42
s->amsel = 0;
51
}
43
}
52
44
53
-static uint32_t nvram_readw (void *opaque, hwaddr addr)
45
+static void pl061_hold_reset(Object *obj)
54
+static void nvram_write(void *opaque, hwaddr addr, uint64_t value,
46
+{
55
+ unsigned size)
47
+ PL061State *s = PL061(obj);
48
+ int i, level;
49
+ uint8_t floating = pl061_floating(s);
50
+ uint8_t pullups = pl061_pullups(s);
51
+
52
+ for (i = 0; i < N_GPIOS; i++) {
53
+ if (extract32(floating, i, 1)) {
54
+ continue;
55
+ }
56
+ level = extract32(pullups, i, 1);
57
+ trace_pl061_set_output(DEVICE(s)->canonical_path, i, level);
58
+ qemu_set_irq(s->out[i], level);
59
+ }
60
+ s->old_out_data = pullups;
61
+}
62
+
63
static void pl061_set_irq(void * opaque, int irq, int level)
56
{
64
{
57
M48t59State *NVRAM = opaque;
65
PL061State *s = (PL061State *)opaque;
58
- uint32_t retval;
66
@@ -XXX,XX +XXX,XX @@ static Property pl061_props[] = {
59
67
static void pl061_class_init(ObjectClass *klass, void *data)
60
- retval = m48t59_read(NVRAM, addr) << 8;
68
{
61
- retval |= m48t59_read(NVRAM, addr + 1);
69
DeviceClass *dc = DEVICE_CLASS(klass);
62
- return retval;
70
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
63
-}
71
64
-
72
dc->vmsd = &vmstate_pl061;
65
-static uint32_t nvram_readl (void *opaque, hwaddr addr)
73
- dc->reset = &pl061_reset;
66
-{
74
dc->realize = pl061_realize;
67
- M48t59State *NVRAM = opaque;
75
device_class_set_props(dc, pl061_props);
68
- uint32_t retval;
76
+ rc->phases.enter = pl061_enter_reset;
69
-
77
+ rc->phases.hold = pl061_hold_reset;
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
}
78
}
77
79
78
static const MemoryRegionOps nvram_ops = {
80
static const TypeInfo pl061_info = {
79
- .old_mmio = {
81
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
80
- .read = { nvram_readb, nvram_readw, nvram_readl, },
82
index XXXXXXX..XXXXXXX 100644
81
- .write = { nvram_writeb, nvram_writew, nvram_writel, },
83
--- a/hw/gpio/trace-events
82
- },
84
+++ b/hw/gpio/trace-events
83
- .endianness = DEVICE_NATIVE_ENDIAN,
85
@@ -XXX,XX +XXX,XX @@ pl061_input_change(const char *id, int gpio, int level) "%s input %d changed to
84
+ .read = nvram_read,
86
pl061_update_istate(const char *id, uint32_t istate, uint32_t im, int level) "%s GPIORIS 0x%x GPIOIE 0x%x interrupt level %d"
85
+ .write = nvram_write,
87
pl061_read(const char *id, uint64_t offset, uint64_t r) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
86
+ .impl.min_access_size = 1,
88
pl061_write(const char *id, uint64_t offset, uint64_t value) "%s offset 0x%" PRIx64 " value 0x%" PRIx64
87
+ .impl.max_access_size = 1,
89
+pl061_reset(const char *id) "%s reset"
88
+ .valid.min_access_size = 1,
90
89
+ .valid.max_access_size = 4,
91
# sifive_gpio.c
90
+ .endianness = DEVICE_BIG_ENDIAN,
92
sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
91
};
92
93
static const VMStateDescription vmstate_m48t59 = {
94
--
93
--
95
2.18.0
94
2.20.1
96
95
97
96
diff view generated by jsdifflib
1
On real v7M hardware, the NMI line is an externally visible signal
1
The Luminary PL061s in the Stellaris LM3S9695 don't all have the same
2
that an SoC or board can toggle to assert an NMI. Expose it in
2
reset value for GPIOPUR. We can get away with not letting the board
3
our QEMU NVIC and armv7m container objects so that a board model
3
configure the PUR reset value because we don't actually wire anything
4
can wire it up if it needs to.
4
up to the lines which should reset to pull-up. Add a comment noting
5
5
this omission.
6
In particular, the MPS2 watchdog is wired to NMI.
7
6
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
---
9
---
11
hw/arm/armv7m.c | 1 +
10
hw/gpio/pl061.c | 9 +++++++++
12
hw/intc/armv7m_nvic.c | 19 +++++++++++++++++++
11
1 file changed, 9 insertions(+)
13
hw/intc/trace-events | 1 +
14
3 files changed, 21 insertions(+)
15
12
16
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
13
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/armv7m.c
15
--- a/hw/gpio/pl061.c
19
+++ b/hw/arm/armv7m.c
16
+++ b/hw/gpio/pl061.c
20
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
17
@@ -XXX,XX +XXX,XX @@ static void pl061_enter_reset(Object *obj, ResetType type)
21
*/
18
trace_pl061_reset(DEVICE(s)->canonical_path);
22
qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
19
23
qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
20
/* reset values from PL061 TRM, Stellaris LM3S5P31 & LM3S8962 Data Sheet */
24
+ qdev_pass_gpios(DEVICE(&s->nvic), dev, "NMI");
25
26
/* Wire the NVIC up to the CPU */
27
sbd = SYS_BUS_DEVICE(&s->nvic);
28
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/intc/armv7m_nvic.c
31
+++ b/hw/intc/armv7m_nvic.c
32
@@ -XXX,XX +XXX,XX @@ static void set_irq_level(void *opaque, int n, int level)
33
}
34
}
35
36
+/* callback when external NMI line is changed */
37
+static void nvic_nmi_trigger(void *opaque, int n, int level)
38
+{
39
+ NVICState *s = opaque;
40
+
41
+ trace_nvic_set_nmi_level(level);
42
+
21
+
43
+ /*
22
+ /*
44
+ * The architecture doesn't specify whether NMI should share
23
+ * FIXME: For the LM3S6965, not all of the PL061 instances have the
45
+ * the normal-interrupt behaviour of being resampled on
24
+ * same reset values for GPIOPUR, GPIOAFSEL and GPIODEN, so in theory
46
+ * exception handler return. We choose not to, so just
25
+ * we should allow the board to configure these via properties.
47
+ * set NMI pending here and don't track the current level.
26
+ * In practice, we don't wire anything up to the affected GPIO lines
27
+ * (PB7, PC0, PC1, PC2, PC3 -- they're used for JTAG), so we can
28
+ * get away with this inaccuracy.
48
+ */
29
+ */
49
+ if (level) {
30
s->data = 0;
50
+ armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI, false);
31
s->old_in_data = 0;
51
+ }
32
s->dir = 0;
52
+}
53
+
54
static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
55
{
56
ARMCPU *cpu = s->cpu;
57
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
58
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
59
qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger",
60
M_REG_NUM_BANKS);
61
+ qdev_init_gpio_in_named(dev, nvic_nmi_trigger, "NMI", 1);
62
}
63
64
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
65
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/intc/trace-events
68
+++ b/hw/intc/trace-events
69
@@ -XXX,XX +XXX,XX @@ nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (pr
70
nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
71
nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
72
nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
73
+nvic_set_nmi_level(int level) "NVIC external NMI level set to %d"
74
nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
75
nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
76
77
--
33
--
78
2.18.0
34
2.20.1
79
35
80
36
diff view generated by jsdifflib
1
From: Roman Kapl <rka@sysgo.com>
1
The stellaris board doesn't emulate the handling of the OLED
2
chipselect line correctly. Expand the comment describing this,
3
including a sketch of the theoretical correct way to do it.
2
4
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.
6
7
CBZ in IT block is an UNPREDICTABLE behavior, but we should not
8
crash. Honouring the condition code is allowed by the spec in this
9
case (constrained unpredictable, ARMv8, section K1.1.7), and matches
10
what we do for other "UNPREDICTABLE inside an IT block" instructions.
11
12
Fix the 'skip on condition' code to create a new label only if it
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]
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
6
---
23
target/arm/translate.c | 35 +++++++++++++++++++++--------------
7
hw/arm/stellaris.c | 56 +++++++++++++++++++++++++++++++++++++++++++++-
24
1 file changed, 21 insertions(+), 14 deletions(-)
8
1 file changed, 55 insertions(+), 1 deletion(-)
25
9
26
diff --git a/target/arm/translate.c b/target/arm/translate.c
10
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
27
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/translate.c
12
--- a/hw/arm/stellaris.c
29
+++ b/target/arm/translate.c
13
+++ b/hw/arm/stellaris.c
30
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
14
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
31
s->base.is_jmp = DISAS_UPDATE;
15
DeviceState *sddev;
32
}
16
DeviceState *ssddev;
33
17
34
+/* Generate a label used for skipping this instruction */
18
- /* Some boards have both an OLED controller and SD card connected to
35
+static void arm_gen_condlabel(DisasContext *s)
19
+ /*
36
+{
20
+ * Some boards have both an OLED controller and SD card connected to
37
+ if (!s->condjmp) {
21
* the same SSI port, with the SD card chip select connected to a
38
+ s->condlabel = gen_new_label();
22
* GPIO pin. Technically the OLED chip select is connected to the
39
+ s->condjmp = 1;
23
* SSI Fss pin. We do not bother emulating that as both devices
40
+ }
24
* should never be selected simultaneously, and our OLED controller
41
+}
25
* ignores stray 0xff commands that occur when deselecting the SD
42
+
26
* card.
43
+/* Skip this instruction if the ARM condition is false */
27
+ *
44
+static void arm_skip_unless(DisasContext *s, uint32_t cond)
28
+ * The h/w wiring is:
45
+{
29
+ * - GPIO pin D0 is wired to the active-low SD card chip select
46
+ arm_gen_condlabel(s);
30
+ * - GPIO pin A3 is wired to the active-low OLED chip select
47
+ arm_gen_test_cc(cond ^ 1, s->condlabel);
31
+ * - The SoC wiring of the PL061 "auxiliary function" for A3 is
48
+}
32
+ * SSI0Fss ("frame signal"), which is an output from the SoC's
49
+
33
+ * SSI controller. The SSI controller takes SSI0Fss low when it
50
static void disas_arm_insn(DisasContext *s, unsigned int insn)
34
+ * transmits a frame, so it can work as a chip-select signal.
51
{
35
+ * - GPIO A4 is aux-function SSI0Rx, and wired to the SD card Tx
52
unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
36
+ * (the OLED never sends data to the CPU, so no wiring needed)
53
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
37
+ * - GPIO A5 is aux-function SSI0Tx, and wired to the SD card Rx
54
if (cond != 0xe) {
38
+ * and the OLED display-data-in
55
/* if not always execute, we generate a conditional jump to
39
+ * - GPIO A2 is aux-function SSI0Clk, wired to SD card and OLED
56
next instruction */
40
+ * serial-clock input
57
- s->condlabel = gen_new_label();
41
+ * So a guest that wants to use the OLED can configure the PL061
58
- arm_gen_test_cc(cond ^ 1, s->condlabel);
42
+ * to make pins A2, A3, A5 aux-function, so they are connected
59
- s->condjmp = 1;
43
+ * directly to the SSI controller. When the SSI controller sends
60
+ arm_skip_unless(s, cond);
44
+ * data it asserts SSI0Fss which selects the OLED.
61
}
45
+ * A guest that wants to use the SD card configures A2, A4 and A5
62
if ((insn & 0x0f900000) == 0x03000000) {
46
+ * as aux-function, but leaves A3 as a software-controlled GPIO
63
if ((insn & (1 << 21)) == 0) {
47
+ * line. It asserts the SD card chip-select by using the PL061
64
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
48
+ * to control pin D0, and lets the SSI controller handle Clk, Tx
65
/* Conditional branch. */
49
+ * and Rx. (The SSI controller asserts Fss during tx cycles as
66
op = (insn >> 22) & 0xf;
50
+ * usual, but because A3 is not set to aux-function this is not
67
/* Generate a conditional jump to next instruction. */
51
+ * forwarded to the OLED, and so the OLED stays unselected.)
68
- s->condlabel = gen_new_label();
52
+ *
69
- arm_gen_test_cc(op ^ 1, s->condlabel);
53
+ * The QEMU implementation instead is:
70
- s->condjmp = 1;
54
+ * - GPIO pin D0 is wired to the active-low SD card chip select,
71
+ arm_skip_unless(s, op);
55
+ * and also to the OLED chip-select which is implemented
72
56
+ * as *active-high*
73
/* offset[11:1] = insn[10:0] */
57
+ * - SSI controller signals go to the devices regardless of
74
offset = (insn & 0x7ff) << 1;
58
+ * whether the guest programs A2, A4, A5 as aux-function or not
75
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
59
+ *
76
case 1: case 3: case 9: case 11: /* czb */
60
+ * The problem with this implementation is if the guest doesn't
77
rm = insn & 7;
61
+ * care about the SD card and only uses the OLED. In that case it
78
tmp = load_reg(s, rm);
62
+ * may choose never to do anything with D0 (leaving it in its
79
- s->condlabel = gen_new_label();
63
+ * default floating state, which reliably leaves the card disabled
80
- s->condjmp = 1;
64
+ * because an SD card has a pullup on CS within the card itself),
81
+ arm_gen_condlabel(s);
65
+ * and only set up A2, A3, A5. This for us would mean the OLED
82
if (insn & (1 << 11))
66
+ * never gets the chip-select assert it needs. We work around
83
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
67
+ * this with a manual raise of D0 here (despite board creation
84
else
68
+ * code being the wrong place to raise IRQ lines) to put the OLED
85
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
69
+ * into an initially selected state.
86
break;
70
+ *
87
}
71
+ * In theory the right way to model this would be:
88
/* generate a conditional jump to next instruction */
72
+ * - Implement aux-function support in the PL061, with an
89
- s->condlabel = gen_new_label();
73
+ * extra set of AFIN and AFOUT GPIO lines (set up so that
90
- arm_gen_test_cc(cond ^ 1, s->condlabel);
74
+ * if a GPIO line is in auxfn mode the main GPIO in and out
91
- s->condjmp = 1;
75
+ * track the AFIN and AFOUT lines)
92
+ arm_skip_unless(s, cond);
76
+ * - Wire the AFOUT for D0 up to either a line from the
93
77
+ * SSI controller that's pulled low around every transmit,
94
/* jump to the offset */
78
+ * or at least to an always-0 line here on the board
95
val = (uint32_t)s->pc + 2;
79
+ * - Make the ssd0323 OLED controller chipselect active-low
96
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
80
*/
97
uint32_t cond = dc->condexec_cond;
81
bus = qdev_get_child_bus(dev, "ssi");
98
99
if (cond != 0x0e) { /* Skip conditional when condition is AL. */
100
- dc->condlabel = gen_new_label();
101
- arm_gen_test_cc(cond ^ 1, dc->condlabel);
102
- dc->condjmp = 1;
103
+ arm_skip_unless(dc, cond);
104
}
105
}
106
82
107
--
83
--
108
2.18.0
84
2.20.1
109
85
110
86
diff view generated by jsdifflib
Deleted patch
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).
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Message-id: 20180814124254.5229-2-peter.maydell@linaro.org
9
---
10
target/arm/helper.c | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
18
.opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0,
19
.access = PL2_RW, .type = ARM_CP_CONST,
20
.resetvalue = 0 },
21
- { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
22
+ { .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
23
.opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
24
.access = PL2_RW, .type = ARM_CP_CONST,
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 },
35
--
36
2.18.0
37
38
diff view generated by jsdifflib
Deleted patch
1
ARMCPRegInfo structs will default to .cp = 15 if they
2
are ARM_CP_STATE_BOTH, but not if they are ARM_CP_STATE_AA32
3
(because a coprocessor number of 0 is valid for AArch32).
4
We forgot to explicitly set .cp = 15 for the HMAIR1 and
5
HAMAIR1 regdefs, which meant they would UNDEF when the guest
6
tried to access them under cp15.
7
1
8
Signed-off-by: Peter Maydell <peter.maydell@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
12
---
13
target/arm/helper.c | 8 ++++----
14
1 file changed, 4 insertions(+), 4 deletions(-)
15
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
19
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
21
.access = PL2_RW, .type = ARM_CP_CONST,
22
.resetvalue = 0 },
23
{ .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
24
- .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
25
+ .cp = 15, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
26
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
27
{ .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH,
28
.opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0,
29
.access = PL2_RW, .type = ARM_CP_CONST,
30
.resetvalue = 0 },
31
{ .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
32
- .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
33
+ .cp = 15, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
34
.access = PL2_RW, .type = ARM_CP_CONST,
35
.resetvalue = 0 },
36
{ .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH,
37
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
38
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[2]),
39
.resetvalue = 0 },
40
{ .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
41
- .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
42
+ .cp = 15, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
43
.access = PL2_RW, .type = ARM_CP_ALIAS,
44
.fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el[2]) },
45
{ .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH,
46
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
47
.resetvalue = 0 },
48
/* HAMAIR1 is mapped to AMAIR_EL2[63:32] */
49
{ .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
50
- .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
51
+ .cp = 15, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
52
.access = PL2_RW, .type = ARM_CP_CONST,
53
.resetvalue = 0 },
54
{ .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH,
55
--
56
2.18.0
57
58
diff view generated by jsdifflib
Deleted patch
1
Implement the AArch32 HVBAR register; we can do this just by
2
making the existing VBAR_EL2 regdefs be STATE_BOTH.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@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
8
---
9
target/arm/helper.c | 4 ++--
10
1 file changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
15
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
17
18
/* Used to describe the behaviour of EL2 regs when EL2 does not exist. */
19
static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
20
- { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64,
21
+ { .name = "VBAR_EL2", .state = ARM_CP_STATE_BOTH,
22
.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
23
.access = PL2_RW,
24
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
25
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
26
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0,
27
.access = PL2_RW,
28
.fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) },
29
- { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64,
30
+ { .name = "VBAR_EL2", .state = ARM_CP_STATE_BOTH,
31
.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
32
.access = PL2_RW, .writefn = vbar_write,
33
.fieldoffset = offsetof(CPUARMState, cp15.vbar_el[2]),
34
--
35
2.18.0
36
37
diff view generated by jsdifflib
Deleted patch
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)
5
1
6
Implement the accessors for these. This fixes in passing a bug
7
where we weren't implementing the "RES0 from EL3 if EL2 not
8
implemented" behaviour for AArch64 FAR_EL2.
9
10
Signed-off-by: Peter Maydell <peter.maydell@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
14
---
15
target/arm/helper.c | 14 +++++++++++++-
16
1 file changed, 13 insertions(+), 1 deletion(-)
17
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
21
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
23
{ .name = "HSTR_EL2", .state = ARM_CP_STATE_BOTH,
24
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
25
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
26
+ { .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
27
+ .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0,
28
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
29
+ { .name = "HIFAR", .state = ARM_CP_STATE_AA32,
30
+ .type = ARM_CP_CONST,
31
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
32
+ .access = PL2_RW, .resetvalue = 0 },
33
REGINFO_SENTINEL
34
};
35
36
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
37
{ .name = "ESR_EL2", .state = ARM_CP_STATE_AA64,
38
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
39
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) },
40
- { .name = "FAR_EL2", .state = ARM_CP_STATE_AA64,
41
+ { .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
42
.opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0,
43
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[2]) },
44
+ { .name = "HIFAR", .state = ARM_CP_STATE_AA32,
45
+ .type = ARM_CP_ALIAS,
46
+ .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
47
+ .access = PL2_RW,
48
+ .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[2]) },
49
{ .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64,
50
.type = ARM_CP_ALIAS,
51
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0,
52
--
53
2.18.0
54
55
diff view generated by jsdifflib
1
The AArch32 HSR is the equivalent of AArch64 ESR_EL2;
1
From: "hnick@vmware.com" <hnick@vmware.com>
2
we can implement it by marking our existing ESR_EL2 regdef
3
as STATE_BOTH. It also needs to be "RES0 from EL3 if
4
EL2 not implemented", so add the missing stanza to
5
el3_no_el2_cp_reginfo.
6
2
3
Signed-off-by: Nick Hudson <hnick@vmware.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@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
11
---
6
---
12
target/arm/helper.c | 6 +++++-
7
target/arm/helper.c | 16 +++++++++++++---
13
1 file changed, 5 insertions(+), 1 deletion(-)
8
1 file changed, 13 insertions(+), 3 deletions(-)
14
9
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
10
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
12
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
13
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
14
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
20
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
15
.access = PL1_RW, .accessfn = access_tda,
21
.access = PL2_RW,
16
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1),
22
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
17
.resetvalue = 0 },
23
+ { .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
18
- /* MDCCSR_EL0, aka DBGDSCRint. This is a read-only mirror of MDSCR_EL1.
24
+ .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
19
+ /*
25
+ .access = PL2_RW,
20
+ * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external
21
+ * Debug Communication Channel is not implemented.
22
+ */
23
+ { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64,
24
+ .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0,
25
+ .access = PL0_R, .accessfn = access_tda,
26
+ .type = ARM_CP_CONST, .resetvalue = 0 },
26
+ .type = ARM_CP_CONST, .resetvalue = 0 },
27
{ .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH,
27
+ /*
28
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2,
28
+ * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as
29
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
29
+ * it is unlikely a guest will care.
30
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
30
* We don't implement the configurable EL0 access.
31
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
31
*/
32
.access = PL2_RW,
32
- { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_BOTH,
33
.fieldoffset = offsetof(CPUARMState, elr_el[2]) },
33
- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
34
- { .name = "ESR_EL2", .state = ARM_CP_STATE_AA64,
34
+ { .name = "DBGDSCRint", .state = ARM_CP_STATE_AA32,
35
+ { .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
35
+ .cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
36
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
36
.type = ARM_CP_ALIAS,
37
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) },
37
.access = PL1_R, .accessfn = access_tda,
38
{ .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
38
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },
39
--
39
--
40
2.18.0
40
2.20.1
41
41
42
42
diff view generated by jsdifflib
Deleted patch
1
ARMv7VE introduced the ERET instruction, which is necessary to
2
return from an exception taken to Hyp mode. Implement this.
3
In A32 encoding it is a completely new encoding; in T32 it
4
is an adjustment of the behaviour of the existing
5
"SUBS PC, LR, #<imm8>" instruction.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@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
11
---
12
target/arm/translate.c | 31 +++++++++++++++++++++++++++++--
13
1 file changed, 29 insertions(+), 2 deletions(-)
14
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
18
+++ b/target/arm/translate.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
20
tcg_temp_free_i32(tmp2);
21
store_reg(s, rd, tmp);
22
break;
23
+ case 0x6: /* ERET */
24
+ if (op1 != 3) {
25
+ goto illegal_op;
26
+ }
27
+ if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
28
+ goto illegal_op;
29
+ }
30
+ if ((insn & 0x000fff0f) != 0x0000000e) {
31
+ /* UNPREDICTABLE; we choose to UNDEF */
32
+ goto illegal_op;
33
+ }
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 */
64
--
65
2.18.0
66
67
diff view generated by jsdifflib
1
From: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
1
From: Rebecca Cran <rebecca@nuviainc.com>
2
2
3
Add the ESDHC PRSSTAT_SDSTB bit, using the value of SDHC_CLOCK_INT_STABLE.
3
Add a space in the message printed when gicr_read*/gicr_write* returns
4
Freescale recommends checking this bit when changing clock frequency.
4
MEMTX_ERROR in arm_gicv3_redist.c.
5
5
6
Signed-off-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
6
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
7
Message-id: 1534507843-4251-1-git-send-email-hans-erik.floryd@rt-labs.com
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
[PMM: fixed indentation]
8
Message-id: 20210706211432.31902-1-rebecca@nuviainc.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/sd/sdhci-internal.h | 2 ++
11
hw/intc/arm_gicv3_redist.c | 4 ++--
13
hw/sd/sdhci.c | 8 ++++++++
12
1 file changed, 2 insertions(+), 2 deletions(-)
14
2 files changed, 10 insertions(+)
15
13
16
diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
14
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/sd/sdhci-internal.h
16
--- a/hw/intc/arm_gicv3_redist.c
19
+++ b/hw/sd/sdhci-internal.h
17
+++ b/hw/intc/arm_gicv3_redist.c
20
@@ -XXX,XX +XXX,XX @@ extern const VMStateDescription sdhci_vmstate;
18
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
21
#define ESDHC_CTRL_4BITBUS (0x1 << 1)
19
if (r == MEMTX_ERROR) {
22
#define ESDHC_CTRL_8BITBUS (0x2 << 1)
20
qemu_log_mask(LOG_GUEST_ERROR,
23
21
"%s: invalid guest read at offset " TARGET_FMT_plx
24
+#define ESDHC_PRNSTS_SDSTB (1 << 3)
22
- "size %u\n", __func__, offset, size);
25
+
23
+ " size %u\n", __func__, offset, size);
26
#endif
24
trace_gicv3_redist_badread(gicv3_redist_affid(cs), offset,
27
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
25
size, attrs.secure);
28
index XXXXXXX..XXXXXXX 100644
26
/* The spec requires that reserved registers are RAZ/WI;
29
--- a/hw/sd/sdhci.c
27
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
30
+++ b/hw/sd/sdhci.c
28
if (r == MEMTX_ERROR) {
31
@@ -XXX,XX +XXX,XX @@ static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
29
qemu_log_mask(LOG_GUEST_ERROR,
32
30
"%s: invalid guest write at offset " TARGET_FMT_plx
33
break;
31
- "size %u\n", __func__, offset, size);
34
32
+ " size %u\n", __func__, offset, size);
35
+ case SDHC_PRNSTS:
33
trace_gicv3_redist_badwrite(gicv3_redist_affid(cs), offset, data,
36
+ /* Add SDSTB (SD Clock Stable) bit to PRNSTS */
34
size, attrs.secure);
37
+ ret = sdhci_read(opaque, offset, size) & ~ESDHC_PRNSTS_SDSTB;
35
/* The spec requires that reserved registers are RAZ/WI;
38
+ if (s->clkcon & SDHC_CLOCK_INT_STABLE) {
39
+ ret |= ESDHC_PRNSTS_SDSTB;
40
+ }
41
+ break;
42
+
43
case ESDHC_DLL_CTRL:
44
case ESDHC_TUNE_CTRL_STATUS:
45
case ESDHC_UNDOCUMENTED_REG27:
46
--
36
--
47
2.18.0
37
2.20.1
48
38
49
39
diff view generated by jsdifflib
Deleted patch
1
Remove the obsolete MMIO request_ptr APIs; they have no
2
users now.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@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
9
---
10
include/exec/memory.h | 35 --------------
11
memory.c | 110 ------------------------------------------
12
2 files changed, 145 deletions(-)
13
14
diff --git a/include/exec/memory.h b/include/exec/memory.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/memory.h
17
+++ b/include/exec/memory.h
18
@@ -XXX,XX +XXX,XX @@ struct MemoryRegionOps {
19
uint64_t data,
20
unsigned size,
21
MemTxAttrs attrs);
22
- /* Instruction execution pre-callback:
23
- * @addr is the address of the access relative to the @mr.
24
- * @size is the size of the area returned by the callback.
25
- * @offset is the location of the pointer inside @mr.
26
- *
27
- * Returns a pointer to a location which contains guest code.
28
- */
29
- void *(*request_ptr)(void *opaque, hwaddr addr, unsigned *size,
30
- unsigned *offset);
31
32
enum device_endian endianness;
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
68
index XXXXXXX..XXXXXXX 100644
69
--- a/memory.c
70
+++ b/memory.c
71
@@ -XXX,XX +XXX,XX @@
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;
81
}
82
83
-bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr)
84
-{
85
- void *host;
86
- unsigned size = 0;
87
- unsigned offset = 0;
88
- Object *new_interface;
89
-
90
- if (!mr || !mr->ops->request_ptr) {
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)
193
{
194
memory_region_ref(root);
195
--
196
2.18.0
197
198
diff view generated by jsdifflib
Deleted patch
1
The mmio_interface device was a purely internal artifact
2
of the implementation of the memory subsystem's request_ptr
3
APIs. Now that we have removed those APIs, we can remove
4
the mmio_interface device too.
5
1
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
11
---
12
hw/misc/Makefile.objs | 1 -
13
include/hw/misc/mmio_interface.h | 49 -----------
14
hw/misc/mmio_interface.c | 135 -------------------------------
15
3 files changed, 185 deletions(-)
16
delete mode 100644 include/hw/misc/mmio_interface.h
17
delete mode 100644 hw/misc/mmio_interface.c
18
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
22
+++ b/hw/misc/Makefile.objs
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_PVPANIC) += pvpanic.o
24
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
25
obj-$(CONFIG_AUX) += auxbus.o
26
obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
27
-obj-y += mmio_interface.o
28
obj-$(CONFIG_MSF2) += msf2-sysreg.o
29
diff --git a/include/hw/misc/mmio_interface.h b/include/hw/misc/mmio_interface.h
30
deleted file mode 100644
31
index XXXXXXX..XXXXXXX
32
--- a/include/hw/misc/mmio_interface.h
33
+++ /dev/null
34
@@ -XXX,XX +XXX,XX @@
35
-/*
36
- * mmio_interface.h
37
- *
38
- * Copyright (C) 2017 : GreenSocs
39
- * http://www.greensocs.com/ , email: info@greensocs.com
40
- *
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
89
@@ -XXX,XX +XXX,XX @@
90
-/*
91
- * mmio_interface.c
92
- *
93
- * Copyright (C) 2017 : GreenSocs
94
- * http://www.greensocs.com/ , email: info@greensocs.com
95
- *
96
- * Developed by :
97
- * Frederic Konrad <fred.konrad@greensocs.com>
98
- *
99
- * This program is free software; you can redistribute it and/or modify
100
- * it under the terms of the GNU General Public License as published by
101
- * the Free Software Foundation, either version 2 of the License, or
102
- * (at your option)any later version.
103
- *
104
- * This program is distributed in the hope that it will be useful,
105
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
106
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
107
- * GNU General Public License for more details.
108
- *
109
- * You should have received a copy of the GNU General Public License along
110
- * with this program; if not, see <http://www.gnu.org/licenses/>.
111
- *
112
- */
113
-
114
-#include "qemu/osdep.h"
115
-#include "qemu/log.h"
116
-#include "trace.h"
117
-#include "hw/qdev-properties.h"
118
-#include "hw/misc/mmio_interface.h"
119
-#include "qapi/error.h"
120
-
121
-#ifndef DEBUG_MMIO_INTERFACE
122
-#define DEBUG_MMIO_INTERFACE 0
123
-#endif
124
-
125
-static uint64_t mmio_interface_counter;
126
-
127
-#define DPRINTF(fmt, ...) do { \
128
- if (DEBUG_MMIO_INTERFACE) { \
129
- qemu_log("mmio_interface: 0x%" PRIX64 ": " fmt, s->id, ## __VA_ARGS__);\
130
- } \
131
-} while (0)
132
-
133
-static void mmio_interface_init(Object *obj)
134
-{
135
- MMIOInterface *s = MMIO_INTERFACE(obj);
136
-
137
- if (DEBUG_MMIO_INTERFACE) {
138
- s->id = mmio_interface_counter++;
139
- }
140
-
141
- DPRINTF("interface created\n");
142
- s->host_ptr = 0;
143
- s->subregion = 0;
144
-}
145
-
146
-static void mmio_interface_realize(DeviceState *dev, Error **errp)
147
-{
148
- MMIOInterface *s = MMIO_INTERFACE(dev);
149
-
150
- DPRINTF("realize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
151
- " %p\n", s->start, s->end, s->host_ptr);
152
-
153
- if (!s->host_ptr) {
154
- error_setg(errp, "host_ptr property must be set");
155
- return;
156
- }
157
-
158
- if (!s->subregion) {
159
- error_setg(errp, "subregion property must be set");
160
- return;
161
- }
162
-
163
- memory_region_init_ram_ptr(&s->ram_mem, OBJECT(s), "ram",
164
- s->end - s->start + 1, s->host_ptr);
165
- memory_region_set_readonly(&s->ram_mem, s->ro);
166
- memory_region_add_subregion(s->subregion, s->start, &s->ram_mem);
167
-}
168
-
169
-static void mmio_interface_unrealize(DeviceState *dev, Error **errp)
170
-{
171
- MMIOInterface *s = MMIO_INTERFACE(dev);
172
-
173
- DPRINTF("unrealize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
174
- " %p\n", s->start, s->end, s->host_ptr);
175
- memory_region_del_subregion(s->subregion, &s->ram_mem);
176
-}
177
-
178
-static void mmio_interface_finalize(Object *obj)
179
-{
180
- MMIOInterface *s = MMIO_INTERFACE(obj);
181
-
182
- DPRINTF("finalize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
183
- " %p\n", s->start, s->end, s->host_ptr);
184
- object_unparent(OBJECT(&s->ram_mem));
185
-}
186
-
187
-static Property mmio_interface_properties[] = {
188
- DEFINE_PROP_UINT64("start", MMIOInterface, start, 0),
189
- DEFINE_PROP_UINT64("end", MMIOInterface, end, 0),
190
- DEFINE_PROP_PTR("host_ptr", MMIOInterface, host_ptr),
191
- DEFINE_PROP_BOOL("ro", MMIOInterface, ro, false),
192
- DEFINE_PROP_MEMORY_REGION("subregion", MMIOInterface, subregion),
193
- DEFINE_PROP_END_OF_LIST(),
194
-};
195
-
196
-static void mmio_interface_class_init(ObjectClass *oc, void *data)
197
-{
198
- DeviceClass *dc = DEVICE_CLASS(oc);
199
-
200
- dc->realize = mmio_interface_realize;
201
- dc->unrealize = mmio_interface_unrealize;
202
- dc->props = mmio_interface_properties;
203
- /* Reason: pointer property "host_ptr", and this device
204
- * is an implementation detail of the memory subsystem,
205
- * not intended to be created directly by the user.
206
- */
207
- dc->user_creatable = false;
208
-}
209
-
210
-static const TypeInfo mmio_interface_info = {
211
- .name = TYPE_MMIO_INTERFACE,
212
- .parent = TYPE_DEVICE,
213
- .instance_size = sizeof(MMIOInterface),
214
- .instance_init = mmio_interface_init,
215
- .instance_finalize = mmio_interface_finalize,
216
- .class_init = mmio_interface_class_init,
217
-};
218
-
219
-static void mmio_interface_register_types(void)
220
-{
221
- type_register_static(&mmio_interface_info);
222
-}
223
-
224
-type_init(mmio_interface_register_types)
225
--
226
2.18.0
227
228
diff view generated by jsdifflib
Deleted patch
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.
6
1
7
Fixes: https://bugs.launchpad.net/qemu/+bug/1637974
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
---
11
hw/dma/pl080.c | 5 +++--
12
1 file changed, 3 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/dma/pl080.c
17
+++ b/hw/dma/pl080.c
18
@@ -XXX,XX +XXX,XX @@ static uint64_t pl080_read(void *opaque, hwaddr offset,
19
i = (offset & 0xe0) >> 5;
20
if (i >= s->nchannels)
21
goto bad_offset;
22
- switch (offset >> 2) {
23
+ switch ((offset >> 2) & 7) {
24
case 0: /* SrcAddr */
25
return s->chan[i].src;
26
case 1: /* DestAddr */
27
@@ -XXX,XX +XXX,XX @@ static void pl080_write(void *opaque, hwaddr offset,
28
i = (offset & 0xe0) >> 5;
29
if (i >= s->nchannels)
30
goto bad_offset;
31
- switch (offset >> 2) {
32
+ switch ((offset >> 2) & 7) {
33
case 0: /* SrcAddr */
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 */
44
--
45
2.18.0
46
47
diff view generated by jsdifflib