1
ARM queue, various patches accumulated over the Christmas break.
1
target-arm queue: mostly aspeed changes from Cédric.
2
2
3
thanks
3
-- PMM
4
-- PMM
4
5
5
The following changes since commit 612061b277915fadd80631eb7a6926f48a110c44:
6
The following changes since commit 85182c96de61f0b600bbe834d5a23e713162e892:
6
7
7
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-01-10' into staging (2018-01-11 11:52:40 +0000)
8
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20190912a' into staging (2019-09-13 14:37:48 +0100)
8
9
9
are available in the git repository at:
10
are available in the Git repository at:
10
11
11
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180111
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190913
12
13
13
for you to fetch changes up to 0cf09852015e47a5fbb974ff7ac320366afd21ee:
14
for you to fetch changes up to 27a296fce9821e3608d537756cffa6e43a46df3b:
14
15
15
hw/intc/arm_gic: reserved register addresses are RAZ/WI (2018-01-11 13:25:40 +0000)
16
qemu-ga: Convert invocation documentation to rST (2019-09-13 16:05:01 +0100)
16
17
17
----------------------------------------------------------------
18
----------------------------------------------------------------
18
target-arm queue:
19
target-arm queue:
19
* add aarch64_be linux-user target
20
* aspeed: add a GPIO controller to the SoC
20
* Virt: ACPI: fix qemu assert due to re-assigned table data address
21
* aspeed: Various refactorings
21
* imx_fec: various bug fixes and cleanups
22
* aspeed: Improve DMA controller modelling
22
* hw/timer/pxa2xx_timer: replace hw_error() -> qemu_log_mask()
23
* atomic_template: fix indentation in GEN_ATOMIC_HELPER
23
* hw/sd/pxa2xx_mmci: add read/write() trace events
24
* qemu-ga: Convert invocation documentation to rST
24
* linux-user/arm/nwfpe: Check coprocessor number for FPA emulation
25
* target/arm: Make disas_thumb2_insn() generate its own UNDEF exceptions
26
* hw/intc/arm_gicv3: Make reserved register addresses RAZ/WI
27
* hw/intc/arm_gic: reserved register addresses are RAZ/WI
28
25
29
----------------------------------------------------------------
26
----------------------------------------------------------------
30
Andrey Smirnov (11):
27
Christian Svensson (1):
31
imx_fec: Do not link to netdev
28
aspeed/smc: Calculate checksum on normal DMA
32
imx_fec: Refactor imx_eth_enable_rx()
33
imx_fec: Change queue flushing heuristics
34
imx_fec: Move Tx frame buffer away from the stack
35
imx_fec: Use ENET_FTRL to determine truncation length
36
imx_fec: Use MIN instead of explicit ternary operator
37
imx_fec: Emulate SHIFT16 in ENETx_RACC
38
imx_fec: Add support for multiple Tx DMA rings
39
imx_fec: Use correct length for packet size
40
imx_fec: Fix a typo in imx_enet_receive()
41
imx_fec: Reserve full FSL_IMX25_FEC_SIZE page for the register file
42
29
43
Michael Weiser (8):
30
Cédric Le Goater (7):
44
linux-user: Add support for big-endian aarch64
31
aspeed: Remove unused SoC definitions
45
linux-user: Add separate aarch64_be uname
32
aspeed: Use consistent typenames
46
linux-user: Fix endianess of aarch64 signal trampoline
33
aspeed/smc: Add support for DMAs
47
configure: Add aarch64_be-linux-user target
34
aspeed/smc: Add DMA calibration settings
48
linux-user: Add aarch64_be magic numbers to qemu-binfmt-conf.sh
35
aspeed/smc: Inject errors in DMA checksum
49
linux-user: Separate binfmt arm CPU families
36
aspeed/scu: Introduce per-SoC SCU types
50
linux-user: Activate armeb handler registration
37
aspeed/scu: Introduce a aspeed_scu_get_apb_freq() routine
51
target/arm: Fix stlxp for aarch64_be
52
38
53
Peter Maydell (4):
39
Emilio G. Cota (1):
54
linux-user/arm/nwfpe: Check coprocessor number for FPA emulation
40
atomic_template: fix indentation in GEN_ATOMIC_HELPER
55
target/arm: Make disas_thumb2_insn() generate its own UNDEF exceptions
56
hw/intc/arm_gicv3: Make reserved register addresses RAZ/WI
57
hw/intc/arm_gic: reserved register addresses are RAZ/WI
58
41
59
Philippe Mathieu-Daudé (2):
42
Peter Maydell (1):
60
hw/timer/pxa2xx_timer: replace hw_error() -> qemu_log_mask()
43
qemu-ga: Convert invocation documentation to rST
61
hw/sd/pxa2xx_mmci: add read/write() trace events
62
44
63
Zhaoshenglong (1):
45
Rashmica Gupta (2):
64
Virt: ACPI: fix qemu assert due to re-assigned table data address
46
hw/gpio: Add basic Aspeed GPIO model for AST2400 and AST2500
47
aspeed: add a GPIO controller to the SoC
65
48
66
configure | 5 +-
49
Makefile | 24 +-
67
include/hw/arm/fsl-imx25.h | 1 -
50
hw/gpio/Makefile.objs | 1 +
68
include/hw/net/imx_fec.h | 27 +++-
51
accel/tcg/atomic_template.h | 2 +-
69
linux-user/aarch64/target_syscall.h | 4 +
52
include/hw/arm/aspeed_soc.h | 4 +-
70
hw/arm/fsl-imx6.c | 1 +
53
include/hw/gpio/aspeed_gpio.h | 100 +++++
71
hw/arm/virt-acpi-build.c | 18 ++-
54
include/hw/misc/aspeed_scu.h | 21 +-
72
hw/intc/arm_gic.c | 5 +-
55
include/hw/ssi/aspeed_smc.h | 7 +
73
hw/intc/arm_gicv3_dist.c | 13 ++
56
hw/arm/aspeed.c | 2 +
74
hw/intc/arm_gicv3_its_common.c | 8 +-
57
hw/arm/aspeed_soc.c | 63 ++-
75
hw/intc/arm_gicv3_redist.c | 13 ++
58
hw/gpio/aspeed_gpio.c | 884 ++++++++++++++++++++++++++++++++++++++++++
76
hw/net/imx_fec.c | 210 +++++++++++++++++++++++-------
59
hw/misc/aspeed_scu.c | 102 ++---
77
hw/sd/pxa2xx_mmci.c | 78 +++++++----
60
hw/ssi/aspeed_smc.c | 335 +++++++++++++++-
78
hw/timer/pxa2xx_timer.c | 17 ++-
61
hw/timer/aspeed_timer.c | 3 +-
79
linux-user/arm/nwfpe/fpa11.c | 9 ++
62
MAINTAINERS | 2 +-
80
linux-user/main.c | 6 +
63
docs/conf.py | 18 +-
81
linux-user/signal.c | 10 +-
64
docs/interop/conf.py | 7 +
82
target/arm/helper-a64.c | 7 +-
65
docs/interop/index.rst | 1 +
83
target/arm/translate.c | 23 ++--
66
docs/interop/qemu-ga.rst | 133 +++++++
84
default-configs/aarch64_be-linux-user.mak | 1 +
67
qemu-doc.texi | 5 -
85
hw/sd/trace-events | 4 +
68
qemu-ga.texi | 137 -------
86
scripts/qemu-binfmt-conf.sh | 15 ++-
69
20 files changed, 1585 insertions(+), 266 deletions(-)
87
21 files changed, 356 insertions(+), 119 deletions(-)
70
create mode 100644 include/hw/gpio/aspeed_gpio.h
88
create mode 100644 default-configs/aarch64_be-linux-user.mak
71
create mode 100644 hw/gpio/aspeed_gpio.c
72
create mode 100644 docs/interop/qemu-ga.rst
73
delete mode 100644 qemu-ga.texi
89
74
diff view generated by jsdifflib
Deleted patch
1
From: Michael Weiser <michael.weiser@gmx.de>
2
1
3
Enable big-endian mode for data accesses on aarch64 for big-endian linux
4
user mode. Activate it for all exception levels as documented by ARM:
5
Set the SCTLR EE bit for ELs 1 through 3. Additionally set bit E0E in
6
EL1 to enable it in EL0 as well.
7
8
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20171220212308.12614-2-michael.weiser@gmx.de
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
linux-user/main.c | 6 ++++++
14
1 file changed, 6 insertions(+)
15
16
diff --git a/linux-user/main.c b/linux-user/main.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/linux-user/main.c
19
+++ b/linux-user/main.c
20
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
21
}
22
env->pc = regs->pc;
23
env->xregs[31] = regs->sp;
24
+#ifdef TARGET_WORDS_BIGENDIAN
25
+ env->cp15.sctlr_el[1] |= SCTLR_E0E;
26
+ for (i = 1; i < 4; ++i) {
27
+ env->cp15.sctlr_el[i] |= SCTLR_EE;
28
+ }
29
+#endif
30
}
31
#elif defined(TARGET_ARM)
32
{
33
--
34
2.7.4
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Michael Weiser <michael.weiser@gmx.de>
2
1
3
Make big-endian aarch64 systems identify as aarch64_be as expected by
4
big-endian userland and toolchains.
5
6
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
9
Message-id: 20171220212308.12614-3-michael.weiser@gmx.de
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/aarch64/target_syscall.h | 4 ++++
13
1 file changed, 4 insertions(+)
14
15
diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/aarch64/target_syscall.h
18
+++ b/linux-user/aarch64/target_syscall.h
19
@@ -XXX,XX +XXX,XX @@ struct target_pt_regs {
20
uint64_t pstate;
21
};
22
23
+#if defined(TARGET_WORDS_BIGENDIAN)
24
+#define UNAME_MACHINE "aarch64_be"
25
+#else
26
#define UNAME_MACHINE "aarch64"
27
+#endif
28
#define UNAME_MINIMUM_RELEASE "3.8.0"
29
#define TARGET_CLONE_BACKWARDS
30
#define TARGET_MINSIGSTKSZ 2048
31
--
32
2.7.4
33
34
diff view generated by jsdifflib
Deleted patch
1
From: Michael Weiser <michael.weiser@gmx.de>
2
1
3
Since for aarch64 the signal trampoline is synthesized directly into the
4
signal frame we need to make sure the instructions end up little-endian.
5
Otherwise the wrong endianness will cause a SIGILL upon return from the
6
signal handler on big-endian targets.
7
8
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20171220212308.12614-4-michael.weiser@gmx.de
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
linux-user/signal.c | 10 +++++++---
14
1 file changed, 7 insertions(+), 3 deletions(-)
15
16
diff --git a/linux-user/signal.c b/linux-user/signal.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/linux-user/signal.c
19
+++ b/linux-user/signal.c
20
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
21
if (ka->sa_flags & TARGET_SA_RESTORER) {
22
return_addr = ka->sa_restorer;
23
} else {
24
- /* mov x8,#__NR_rt_sigreturn; svc #0 */
25
- __put_user(0xd2801168, &frame->tramp[0]);
26
- __put_user(0xd4000001, &frame->tramp[1]);
27
+ /*
28
+ * mov x8,#__NR_rt_sigreturn; svc #0
29
+ * Since these are instructions they need to be put as little-endian
30
+ * regardless of target default or current CPU endianness.
31
+ */
32
+ __put_user_e(0xd2801168, &frame->tramp[0], le);
33
+ __put_user_e(0xd4000001, &frame->tramp[1], le);
34
return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
35
}
36
env->xregs[0] = usig;
37
--
38
2.7.4
39
40
diff view generated by jsdifflib
1
From: Michael Weiser <michael.weiser@gmx.de>
1
From: Rashmica Gupta <rashmica.g@gmail.com>
2
2
3
Add target aarch64_be-linux-user. This allows a qemu-aarch64_be binary
3
GPIO pins are arranged in groups of 8 pins labeled A,B,..,Y,Z,AA,AB,AC.
4
to be built that will run big-endian aarch64 binaries.
4
(Note that the ast2400 controller only goes up to group AB).
5
A set has four groups (except set AC which only has one) and is
6
referred to by the groups it is composed of (eg ABCD,EFGH,...,YZAAAB).
7
Each set is accessed and controlled by a bank of 14 registers.
5
8
6
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
9
These registers operate on a per pin level where each bit in the register
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
corresponds to a pin, except for the command source registers. The command
8
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
11
source registers operate on a per group level where bits 24, 16, 8 and 0
9
Message-id: 20171220212308.12614-5-michael.weiser@gmx.de
12
correspond to each group in the set.
13
14
eg. registers for set ABCD:
15
|D7...D0|C7...C0|B7...B0|A7...A0| <- GPIOs
16
|31...24|23...16|15....8|7.....0| <- bit position
17
18
Note that there are a couple of groups that only have 4 pins.
19
20
There are two ways that this model deviates from the behaviour of the
21
actual controller:
22
(1) The only control source driving the GPIO pins in the model is the ARM
23
model (as there currently aren't models for the LPC or Coprocessor).
24
25
(2) None of the registers in the model are reset tolerant (needs
26
integration with the watchdog).
27
28
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
29
Tested-by: Andrew Jeffery <andrew@aj.id.au>
30
Reviewed-by: Cédric Le Goater <clg@kaod.org>
31
Signed-off-by: Cédric Le Goater <clg@kaod.org>
32
Message-id: 20190904070506.1052-2-clg@kaod.org
33
[clg: fixed missing header files
34
made use of HWADDR_PRIx to fix compilation on windows ]
35
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
37
---
12
configure | 5 +++--
38
hw/gpio/Makefile.objs | 1 +
13
default-configs/aarch64_be-linux-user.mak | 1 +
39
include/hw/gpio/aspeed_gpio.h | 100 ++++
14
2 files changed, 4 insertions(+), 2 deletions(-)
40
hw/gpio/aspeed_gpio.c | 884 ++++++++++++++++++++++++++++++++++
15
create mode 100644 default-configs/aarch64_be-linux-user.mak
41
3 files changed, 985 insertions(+)
42
create mode 100644 include/hw/gpio/aspeed_gpio.h
43
create mode 100644 hw/gpio/aspeed_gpio.c
16
44
17
diff --git a/configure b/configure
45
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
18
index XXXXXXX..XXXXXXX 100755
46
index XXXXXXX..XXXXXXX 100644
19
--- a/configure
47
--- a/hw/gpio/Makefile.objs
20
+++ b/configure
48
+++ b/hw/gpio/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ target_name=$(echo $target | cut -d '-' -f 1)
49
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_gpio.o
22
target_bigendian="no"
50
obj-$(CONFIG_IMX) += imx_gpio.o
23
51
obj-$(CONFIG_RASPI) += bcm2835_gpio.o
24
case "$target_name" in
52
obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o
25
- armeb|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
53
+obj-$(CONFIG_ASPEED_SOC) += aspeed_gpio.o
26
+ armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
54
diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h
27
target_bigendian=yes
28
;;
29
esac
30
@@ -XXX,XX +XXX,XX @@ case "$target_name" in
31
mttcg="yes"
32
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
33
;;
34
- aarch64)
35
+ aarch64|aarch64_be)
36
+ TARGET_ARCH=aarch64
37
TARGET_BASE_ARCH=arm
38
bflt="yes"
39
mttcg="yes"
40
diff --git a/default-configs/aarch64_be-linux-user.mak b/default-configs/aarch64_be-linux-user.mak
41
new file mode 100644
55
new file mode 100644
42
index XXXXXXX..XXXXXXX
56
index XXXXXXX..XXXXXXX
43
--- /dev/null
57
--- /dev/null
44
+++ b/default-configs/aarch64_be-linux-user.mak
58
+++ b/include/hw/gpio/aspeed_gpio.h
45
@@ -0,0 +1 @@
59
@@ -XXX,XX +XXX,XX @@
46
+# Default configuration for aarch64_be-linux-user
60
+/*
61
+ * ASPEED GPIO Controller
62
+ *
63
+ * Copyright (C) 2017-2018 IBM Corp.
64
+ *
65
+ * This code is licensed under the GPL version 2 or later. See
66
+ * the COPYING file in the top-level directory.
67
+ */
68
+
69
+#ifndef ASPEED_GPIO_H
70
+#define ASPEED_GPIO_H
71
+
72
+#include "hw/sysbus.h"
73
+
74
+#define TYPE_ASPEED_GPIO "aspeed.gpio"
75
+#define ASPEED_GPIO(obj) OBJECT_CHECK(AspeedGPIOState, (obj), TYPE_ASPEED_GPIO)
76
+#define ASPEED_GPIO_CLASS(klass) \
77
+ OBJECT_CLASS_CHECK(AspeedGPIOClass, (klass), TYPE_ASPEED_GPIO)
78
+#define ASPEED_GPIO_GET_CLASS(obj) \
79
+ OBJECT_GET_CLASS(AspeedGPIOClass, (obj), TYPE_ASPEED_GPIO)
80
+
81
+#define ASPEED_GPIO_MAX_NR_SETS 8
82
+#define ASPEED_REGS_PER_BANK 14
83
+#define ASPEED_GPIO_MAX_NR_REGS (ASPEED_REGS_PER_BANK * ASPEED_GPIO_MAX_NR_SETS)
84
+#define ASPEED_GPIO_NR_PINS 228
85
+#define ASPEED_GROUPS_PER_SET 4
86
+#define ASPEED_GPIO_NR_DEBOUNCE_REGS 3
87
+#define ASPEED_CHARS_PER_GROUP_LABEL 4
88
+
89
+typedef struct GPIOSets GPIOSets;
90
+
91
+typedef struct GPIOSetProperties {
92
+ uint32_t input;
93
+ uint32_t output;
94
+ char group_label[ASPEED_GROUPS_PER_SET][ASPEED_CHARS_PER_GROUP_LABEL];
95
+} GPIOSetProperties;
96
+
97
+enum GPIORegType {
98
+ gpio_not_a_reg,
99
+ gpio_reg_data_value,
100
+ gpio_reg_direction,
101
+ gpio_reg_int_enable,
102
+ gpio_reg_int_sens_0,
103
+ gpio_reg_int_sens_1,
104
+ gpio_reg_int_sens_2,
105
+ gpio_reg_int_status,
106
+ gpio_reg_reset_tolerant,
107
+ gpio_reg_debounce_1,
108
+ gpio_reg_debounce_2,
109
+ gpio_reg_cmd_source_0,
110
+ gpio_reg_cmd_source_1,
111
+ gpio_reg_data_read,
112
+ gpio_reg_input_mask,
113
+};
114
+
115
+typedef struct AspeedGPIOReg {
116
+ uint16_t set_idx;
117
+ enum GPIORegType type;
118
+ } AspeedGPIOReg;
119
+
120
+typedef struct AspeedGPIOClass {
121
+ SysBusDevice parent_obj;
122
+ const GPIOSetProperties *props;
123
+ uint32_t nr_gpio_pins;
124
+ uint32_t nr_gpio_sets;
125
+ uint32_t gap;
126
+ const AspeedGPIOReg *reg_table;
127
+} AspeedGPIOClass;
128
+
129
+typedef struct AspeedGPIOState {
130
+ /* <private> */
131
+ SysBusDevice parent;
132
+
133
+ /*< public >*/
134
+ MemoryRegion iomem;
135
+ int pending;
136
+ qemu_irq irq;
137
+ qemu_irq gpios[ASPEED_GPIO_NR_PINS];
138
+
139
+/* Parallel GPIO Registers */
140
+ uint32_t debounce_regs[ASPEED_GPIO_NR_DEBOUNCE_REGS];
141
+ struct GPIOSets {
142
+ uint32_t data_value; /* Reflects pin values */
143
+ uint32_t data_read; /* Contains last value written to data value */
144
+ uint32_t direction;
145
+ uint32_t int_enable;
146
+ uint32_t int_sens_0;
147
+ uint32_t int_sens_1;
148
+ uint32_t int_sens_2;
149
+ uint32_t int_status;
150
+ uint32_t reset_tol;
151
+ uint32_t cmd_source_0;
152
+ uint32_t cmd_source_1;
153
+ uint32_t debounce_1;
154
+ uint32_t debounce_2;
155
+ uint32_t input_mask;
156
+ } sets[ASPEED_GPIO_MAX_NR_SETS];
157
+} AspeedGPIOState;
158
+
159
+#endif /* _ASPEED_GPIO_H_ */
160
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
161
new file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- /dev/null
164
+++ b/hw/gpio/aspeed_gpio.c
165
@@ -XXX,XX +XXX,XX @@
166
+/*
167
+ * ASPEED GPIO Controller
168
+ *
169
+ * Copyright (C) 2017-2019 IBM Corp.
170
+ *
171
+ * SPDX-License-Identifier: GPL-2.0-or-later
172
+ */
173
+
174
+#include <assert.h>
175
+
176
+#include "qemu/osdep.h"
177
+#include "qemu/host-utils.h"
178
+#include "qemu/log.h"
179
+#include "hw/gpio/aspeed_gpio.h"
180
+#include "include/hw/misc/aspeed_scu.h"
181
+#include "qapi/error.h"
182
+#include "qapi/visitor.h"
183
+#include "hw/irq.h"
184
+#include "migration/vmstate.h"
185
+
186
+#define GPIOS_PER_REG 32
187
+#define GPIOS_PER_SET GPIOS_PER_REG
188
+#define GPIO_PIN_GAP_SIZE 4
189
+#define GPIOS_PER_GROUP 8
190
+#define GPIO_GROUP_SHIFT 3
191
+
192
+/* GPIO Source Types */
193
+#define ASPEED_CMD_SRC_MASK 0x01010101
194
+#define ASPEED_SOURCE_ARM 0
195
+#define ASPEED_SOURCE_LPC 1
196
+#define ASPEED_SOURCE_COPROCESSOR 2
197
+#define ASPEED_SOURCE_RESERVED 3
198
+
199
+/* GPIO Interrupt Triggers */
200
+/*
201
+ * For each set of gpios there are three sensitivity registers that control
202
+ * the interrupt trigger mode.
203
+ *
204
+ * | 2 | 1 | 0 | trigger mode
205
+ * -----------------------------
206
+ * | 0 | 0 | 0 | falling-edge
207
+ * | 0 | 0 | 1 | rising-edge
208
+ * | 0 | 1 | 0 | level-low
209
+ * | 0 | 1 | 1 | level-high
210
+ * | 1 | X | X | dual-edge
211
+ */
212
+#define ASPEED_FALLING_EDGE 0
213
+#define ASPEED_RISING_EDGE 1
214
+#define ASPEED_LEVEL_LOW 2
215
+#define ASPEED_LEVEL_HIGH 3
216
+#define ASPEED_DUAL_EDGE 4
217
+
218
+/* GPIO Register Address Offsets */
219
+#define GPIO_ABCD_DATA_VALUE (0x000 >> 2)
220
+#define GPIO_ABCD_DIRECTION (0x004 >> 2)
221
+#define GPIO_ABCD_INT_ENABLE (0x008 >> 2)
222
+#define GPIO_ABCD_INT_SENS_0 (0x00C >> 2)
223
+#define GPIO_ABCD_INT_SENS_1 (0x010 >> 2)
224
+#define GPIO_ABCD_INT_SENS_2 (0x014 >> 2)
225
+#define GPIO_ABCD_INT_STATUS (0x018 >> 2)
226
+#define GPIO_ABCD_RESET_TOLERANT (0x01C >> 2)
227
+#define GPIO_EFGH_DATA_VALUE (0x020 >> 2)
228
+#define GPIO_EFGH_DIRECTION (0x024 >> 2)
229
+#define GPIO_EFGH_INT_ENABLE (0x028 >> 2)
230
+#define GPIO_EFGH_INT_SENS_0 (0x02C >> 2)
231
+#define GPIO_EFGH_INT_SENS_1 (0x030 >> 2)
232
+#define GPIO_EFGH_INT_SENS_2 (0x034 >> 2)
233
+#define GPIO_EFGH_INT_STATUS (0x038 >> 2)
234
+#define GPIO_EFGH_RESET_TOLERANT (0x03C >> 2)
235
+#define GPIO_ABCD_DEBOUNCE_1 (0x040 >> 2)
236
+#define GPIO_ABCD_DEBOUNCE_2 (0x044 >> 2)
237
+#define GPIO_EFGH_DEBOUNCE_1 (0x048 >> 2)
238
+#define GPIO_EFGH_DEBOUNCE_2 (0x04C >> 2)
239
+#define GPIO_DEBOUNCE_TIME_1 (0x050 >> 2)
240
+#define GPIO_DEBOUNCE_TIME_2 (0x054 >> 2)
241
+#define GPIO_DEBOUNCE_TIME_3 (0x058 >> 2)
242
+#define GPIO_ABCD_COMMAND_SRC_0 (0x060 >> 2)
243
+#define GPIO_ABCD_COMMAND_SRC_1 (0x064 >> 2)
244
+#define GPIO_EFGH_COMMAND_SRC_0 (0x068 >> 2)
245
+#define GPIO_EFGH_COMMAND_SRC_1 (0x06C >> 2)
246
+#define GPIO_IJKL_DATA_VALUE (0x070 >> 2)
247
+#define GPIO_IJKL_DIRECTION (0x074 >> 2)
248
+#define GPIO_MNOP_DATA_VALUE (0x078 >> 2)
249
+#define GPIO_MNOP_DIRECTION (0x07C >> 2)
250
+#define GPIO_QRST_DATA_VALUE (0x080 >> 2)
251
+#define GPIO_QRST_DIRECTION (0x084 >> 2)
252
+#define GPIO_UVWX_DATA_VALUE (0x088 >> 2)
253
+#define GPIO_UVWX_DIRECTION (0x08C >> 2)
254
+#define GPIO_IJKL_COMMAND_SRC_0 (0x090 >> 2)
255
+#define GPIO_IJKL_COMMAND_SRC_1 (0x094 >> 2)
256
+#define GPIO_IJKL_INT_ENABLE (0x098 >> 2)
257
+#define GPIO_IJKL_INT_SENS_0 (0x09C >> 2)
258
+#define GPIO_IJKL_INT_SENS_1 (0x0A0 >> 2)
259
+#define GPIO_IJKL_INT_SENS_2 (0x0A4 >> 2)
260
+#define GPIO_IJKL_INT_STATUS (0x0A8 >> 2)
261
+#define GPIO_IJKL_RESET_TOLERANT (0x0AC >> 2)
262
+#define GPIO_IJKL_DEBOUNCE_1 (0x0B0 >> 2)
263
+#define GPIO_IJKL_DEBOUNCE_2 (0x0B4 >> 2)
264
+#define GPIO_IJKL_INPUT_MASK (0x0B8 >> 2)
265
+#define GPIO_ABCD_DATA_READ (0x0C0 >> 2)
266
+#define GPIO_EFGH_DATA_READ (0x0C4 >> 2)
267
+#define GPIO_IJKL_DATA_READ (0x0C8 >> 2)
268
+#define GPIO_MNOP_DATA_READ (0x0CC >> 2)
269
+#define GPIO_QRST_DATA_READ (0x0D0 >> 2)
270
+#define GPIO_UVWX_DATA_READ (0x0D4 >> 2)
271
+#define GPIO_YZAAAB_DATA_READ (0x0D8 >> 2)
272
+#define GPIO_AC_DATA_READ (0x0DC >> 2)
273
+#define GPIO_MNOP_COMMAND_SRC_0 (0x0E0 >> 2)
274
+#define GPIO_MNOP_COMMAND_SRC_1 (0x0E4 >> 2)
275
+#define GPIO_MNOP_INT_ENABLE (0x0E8 >> 2)
276
+#define GPIO_MNOP_INT_SENS_0 (0x0EC >> 2)
277
+#define GPIO_MNOP_INT_SENS_1 (0x0F0 >> 2)
278
+#define GPIO_MNOP_INT_SENS_2 (0x0F4 >> 2)
279
+#define GPIO_MNOP_INT_STATUS (0x0F8 >> 2)
280
+#define GPIO_MNOP_RESET_TOLERANT (0x0FC >> 2)
281
+#define GPIO_MNOP_DEBOUNCE_1 (0x100 >> 2)
282
+#define GPIO_MNOP_DEBOUNCE_2 (0x104 >> 2)
283
+#define GPIO_MNOP_INPUT_MASK (0x108 >> 2)
284
+#define GPIO_QRST_COMMAND_SRC_0 (0x110 >> 2)
285
+#define GPIO_QRST_COMMAND_SRC_1 (0x114 >> 2)
286
+#define GPIO_QRST_INT_ENABLE (0x118 >> 2)
287
+#define GPIO_QRST_INT_SENS_0 (0x11C >> 2)
288
+#define GPIO_QRST_INT_SENS_1 (0x120 >> 2)
289
+#define GPIO_QRST_INT_SENS_2 (0x124 >> 2)
290
+#define GPIO_QRST_INT_STATUS (0x128 >> 2)
291
+#define GPIO_QRST_RESET_TOLERANT (0x12C >> 2)
292
+#define GPIO_QRST_DEBOUNCE_1 (0x130 >> 2)
293
+#define GPIO_QRST_DEBOUNCE_2 (0x134 >> 2)
294
+#define GPIO_QRST_INPUT_MASK (0x138 >> 2)
295
+#define GPIO_UVWX_COMMAND_SRC_0 (0x140 >> 2)
296
+#define GPIO_UVWX_COMMAND_SRC_1 (0x144 >> 2)
297
+#define GPIO_UVWX_INT_ENABLE (0x148 >> 2)
298
+#define GPIO_UVWX_INT_SENS_0 (0x14C >> 2)
299
+#define GPIO_UVWX_INT_SENS_1 (0x150 >> 2)
300
+#define GPIO_UVWX_INT_SENS_2 (0x154 >> 2)
301
+#define GPIO_UVWX_INT_STATUS (0x158 >> 2)
302
+#define GPIO_UVWX_RESET_TOLERANT (0x15C >> 2)
303
+#define GPIO_UVWX_DEBOUNCE_1 (0x160 >> 2)
304
+#define GPIO_UVWX_DEBOUNCE_2 (0x164 >> 2)
305
+#define GPIO_UVWX_INPUT_MASK (0x168 >> 2)
306
+#define GPIO_YZAAAB_COMMAND_SRC_0 (0x170 >> 2)
307
+#define GPIO_YZAAAB_COMMAND_SRC_1 (0x174 >> 2)
308
+#define GPIO_YZAAAB_INT_ENABLE (0x178 >> 2)
309
+#define GPIO_YZAAAB_INT_SENS_0 (0x17C >> 2)
310
+#define GPIO_YZAAAB_INT_SENS_1 (0x180 >> 2)
311
+#define GPIO_YZAAAB_INT_SENS_2 (0x184 >> 2)
312
+#define GPIO_YZAAAB_INT_STATUS (0x188 >> 2)
313
+#define GPIO_YZAAAB_RESET_TOLERANT (0x18C >> 2)
314
+#define GPIO_YZAAAB_DEBOUNCE_1 (0x190 >> 2)
315
+#define GPIO_YZAAAB_DEBOUNCE_2 (0x194 >> 2)
316
+#define GPIO_YZAAAB_INPUT_MASK (0x198 >> 2)
317
+#define GPIO_AC_COMMAND_SRC_0 (0x1A0 >> 2)
318
+#define GPIO_AC_COMMAND_SRC_1 (0x1A4 >> 2)
319
+#define GPIO_AC_INT_ENABLE (0x1A8 >> 2)
320
+#define GPIO_AC_INT_SENS_0 (0x1AC >> 2)
321
+#define GPIO_AC_INT_SENS_1 (0x1B0 >> 2)
322
+#define GPIO_AC_INT_SENS_2 (0x1B4 >> 2)
323
+#define GPIO_AC_INT_STATUS (0x1B8 >> 2)
324
+#define GPIO_AC_RESET_TOLERANT (0x1BC >> 2)
325
+#define GPIO_AC_DEBOUNCE_1 (0x1C0 >> 2)
326
+#define GPIO_AC_DEBOUNCE_2 (0x1C4 >> 2)
327
+#define GPIO_AC_INPUT_MASK (0x1C8 >> 2)
328
+#define GPIO_ABCD_INPUT_MASK (0x1D0 >> 2)
329
+#define GPIO_EFGH_INPUT_MASK (0x1D4 >> 2)
330
+#define GPIO_YZAAAB_DATA_VALUE (0x1E0 >> 2)
331
+#define GPIO_YZAAAB_DIRECTION (0x1E4 >> 2)
332
+#define GPIO_AC_DATA_VALUE (0x1E8 >> 2)
333
+#define GPIO_AC_DIRECTION (0x1EC >> 2)
334
+#define GPIO_3_6V_MEM_SIZE 0x1F0
335
+#define GPIO_3_6V_REG_ARRAY_SIZE (GPIO_3_6V_MEM_SIZE >> 2)
336
+
337
+static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio)
338
+{
339
+ uint32_t falling_edge = 0, rising_edge = 0;
340
+ uint32_t int_trigger = extract32(regs->int_sens_0, gpio, 1)
341
+ | extract32(regs->int_sens_1, gpio, 1) << 1
342
+ | extract32(regs->int_sens_2, gpio, 1) << 2;
343
+ uint32_t gpio_curr_high = extract32(regs->data_value, gpio, 1);
344
+ uint32_t gpio_int_enabled = extract32(regs->int_enable, gpio, 1);
345
+
346
+ if (!gpio_int_enabled) {
347
+ return 0;
348
+ }
349
+
350
+ /* Detect edges */
351
+ if (gpio_curr_high && !gpio_prev_high) {
352
+ rising_edge = 1;
353
+ } else if (!gpio_curr_high && gpio_prev_high) {
354
+ falling_edge = 1;
355
+ }
356
+
357
+ if (((int_trigger == ASPEED_FALLING_EDGE) && falling_edge) ||
358
+ ((int_trigger == ASPEED_RISING_EDGE) && rising_edge) ||
359
+ ((int_trigger == ASPEED_LEVEL_LOW) && !gpio_curr_high) ||
360
+ ((int_trigger == ASPEED_LEVEL_HIGH) && gpio_curr_high) ||
361
+ ((int_trigger >= ASPEED_DUAL_EDGE) && (rising_edge || falling_edge)))
362
+ {
363
+ regs->int_status = deposit32(regs->int_status, gpio, 1, 1);
364
+ return 1;
365
+ }
366
+ return 0;
367
+}
368
+
369
+#define nested_struct_index(ta, pa, m, tb, pb) \
370
+ (pb - ((tb *)(((char *)pa) + offsetof(ta, m))))
371
+
372
+static ptrdiff_t aspeed_gpio_set_idx(AspeedGPIOState *s, GPIOSets *regs)
373
+{
374
+ return nested_struct_index(AspeedGPIOState, s, sets, GPIOSets, regs);
375
+}
376
+
377
+static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
378
+ uint32_t value)
379
+{
380
+ uint32_t input_mask = regs->input_mask;
381
+ uint32_t direction = regs->direction;
382
+ uint32_t old = regs->data_value;
383
+ uint32_t new = value;
384
+ uint32_t diff;
385
+ int gpio;
386
+
387
+ diff = old ^ new;
388
+ if (diff) {
389
+ for (gpio = 0; gpio < GPIOS_PER_REG; gpio++) {
390
+ uint32_t mask = 1 << gpio;
391
+
392
+ /* If the gpio needs to be updated... */
393
+ if (!(diff & mask)) {
394
+ continue;
395
+ }
396
+
397
+ /* ...and we're output or not input-masked... */
398
+ if (!(direction & mask) && (input_mask & mask)) {
399
+ continue;
400
+ }
401
+
402
+ /* ...then update the state. */
403
+ if (mask & new) {
404
+ regs->data_value |= mask;
405
+ } else {
406
+ regs->data_value &= ~mask;
407
+ }
408
+
409
+ /* If the gpio is set to output... */
410
+ if (direction & mask) {
411
+ /* ...trigger the line-state IRQ */
412
+ ptrdiff_t set = aspeed_gpio_set_idx(s, regs);
413
+ size_t offset = set * GPIOS_PER_SET + gpio;
414
+ qemu_set_irq(s->gpios[offset], !!(new & mask));
415
+ } else {
416
+ /* ...otherwise if we meet the line's current IRQ policy... */
417
+ if (aspeed_evaluate_irq(regs, old & mask, gpio)) {
418
+ /* ...trigger the VIC IRQ */
419
+ s->pending++;
420
+ }
421
+ }
422
+ }
423
+ }
424
+ qemu_set_irq(s->irq, !!(s->pending));
425
+}
426
+
427
+static uint32_t aspeed_adjust_pin(AspeedGPIOState *s, uint32_t pin)
428
+{
429
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
430
+ /*
431
+ * The 2500 has a 4 pin gap in group AB and the 2400 has a 4 pin
432
+ * gap in group Y (and only four pins in AB but this is the last group so
433
+ * it doesn't matter).
434
+ */
435
+ if (agc->gap && pin >= agc->gap) {
436
+ pin += GPIO_PIN_GAP_SIZE;
437
+ }
438
+
439
+ return pin;
440
+}
441
+
442
+static bool aspeed_gpio_get_pin_level(AspeedGPIOState *s, uint32_t set_idx,
443
+ uint32_t pin)
444
+{
445
+ uint32_t reg_val;
446
+ uint32_t pin_mask = 1 << pin;
447
+
448
+ reg_val = s->sets[set_idx].data_value;
449
+
450
+ return !!(reg_val & pin_mask);
451
+}
452
+
453
+static void aspeed_gpio_set_pin_level(AspeedGPIOState *s, uint32_t set_idx,
454
+ uint32_t pin, bool level)
455
+{
456
+ uint32_t value = s->sets[set_idx].data_value;
457
+ uint32_t pin_mask = 1 << pin;
458
+
459
+ if (level) {
460
+ value |= pin_mask;
461
+ } else {
462
+ value &= !pin_mask;
463
+ }
464
+
465
+ aspeed_gpio_update(s, &s->sets[set_idx], value);
466
+}
467
+
468
+/*
469
+ * | src_1 | src_2 | source |
470
+ * |-----------------------------|
471
+ * | 0 | 0 | ARM |
472
+ * | 0 | 1 | LPC |
473
+ * | 1 | 0 | Coprocessor|
474
+ * | 1 | 1 | Reserved |
475
+ *
476
+ * Once the source of a set is programmed, corresponding bits in the
477
+ * data_value, direction, interrupt [enable, sens[0-2]], reset_tol and
478
+ * debounce registers can only be written by the source.
479
+ *
480
+ * Source is ARM by default
481
+ * only bits 24, 16, 8, and 0 can be set
482
+ *
483
+ * we don't currently have a model for the LPC or Coprocessor
484
+ */
485
+static uint32_t update_value_control_source(GPIOSets *regs, uint32_t old_value,
486
+ uint32_t value)
487
+{
488
+ int i;
489
+ int cmd_source;
490
+
491
+ /* assume the source is always ARM for now */
492
+ int source = ASPEED_SOURCE_ARM;
493
+
494
+ uint32_t new_value = 0;
495
+
496
+ /* for each group in set */
497
+ for (i = 0; i < GPIOS_PER_REG; i += GPIOS_PER_GROUP) {
498
+ cmd_source = extract32(regs->cmd_source_0, i, 1)
499
+ | (extract32(regs->cmd_source_1, i, 1) << 1);
500
+
501
+ if (source == cmd_source) {
502
+ new_value |= (0xff << i) & value;
503
+ } else {
504
+ new_value |= (0xff << i) & old_value;
505
+ }
506
+ }
507
+ return new_value;
508
+}
509
+
510
+static const AspeedGPIOReg aspeed_3_6v_gpios[GPIO_3_6V_REG_ARRAY_SIZE] = {
511
+ /* Set ABCD */
512
+ [GPIO_ABCD_DATA_VALUE] = { 0, gpio_reg_data_value },
513
+ [GPIO_ABCD_DIRECTION] = { 0, gpio_reg_direction },
514
+ [GPIO_ABCD_INT_ENABLE] = { 0, gpio_reg_int_enable },
515
+ [GPIO_ABCD_INT_SENS_0] = { 0, gpio_reg_int_sens_0 },
516
+ [GPIO_ABCD_INT_SENS_1] = { 0, gpio_reg_int_sens_1 },
517
+ [GPIO_ABCD_INT_SENS_2] = { 0, gpio_reg_int_sens_2 },
518
+ [GPIO_ABCD_INT_STATUS] = { 0, gpio_reg_int_status },
519
+ [GPIO_ABCD_RESET_TOLERANT] = { 0, gpio_reg_reset_tolerant },
520
+ [GPIO_ABCD_DEBOUNCE_1] = { 0, gpio_reg_debounce_1 },
521
+ [GPIO_ABCD_DEBOUNCE_2] = { 0, gpio_reg_debounce_2 },
522
+ [GPIO_ABCD_COMMAND_SRC_0] = { 0, gpio_reg_cmd_source_0 },
523
+ [GPIO_ABCD_COMMAND_SRC_1] = { 0, gpio_reg_cmd_source_1 },
524
+ [GPIO_ABCD_DATA_READ] = { 0, gpio_reg_data_read },
525
+ [GPIO_ABCD_INPUT_MASK] = { 0, gpio_reg_input_mask },
526
+ /* Set EFGH */
527
+ [GPIO_EFGH_DATA_VALUE] = { 1, gpio_reg_data_value },
528
+ [GPIO_EFGH_DIRECTION] = { 1, gpio_reg_direction },
529
+ [GPIO_EFGH_INT_ENABLE] = { 1, gpio_reg_int_enable },
530
+ [GPIO_EFGH_INT_SENS_0] = { 1, gpio_reg_int_sens_0 },
531
+ [GPIO_EFGH_INT_SENS_1] = { 1, gpio_reg_int_sens_1 },
532
+ [GPIO_EFGH_INT_SENS_2] = { 1, gpio_reg_int_sens_2 },
533
+ [GPIO_EFGH_INT_STATUS] = { 1, gpio_reg_int_status },
534
+ [GPIO_EFGH_RESET_TOLERANT] = { 1, gpio_reg_reset_tolerant },
535
+ [GPIO_EFGH_DEBOUNCE_1] = { 1, gpio_reg_debounce_1 },
536
+ [GPIO_EFGH_DEBOUNCE_2] = { 1, gpio_reg_debounce_2 },
537
+ [GPIO_EFGH_COMMAND_SRC_0] = { 1, gpio_reg_cmd_source_0 },
538
+ [GPIO_EFGH_COMMAND_SRC_1] = { 1, gpio_reg_cmd_source_1 },
539
+ [GPIO_EFGH_DATA_READ] = { 1, gpio_reg_data_read },
540
+ [GPIO_EFGH_INPUT_MASK] = { 1, gpio_reg_input_mask },
541
+ /* Set IJKL */
542
+ [GPIO_IJKL_DATA_VALUE] = { 2, gpio_reg_data_value },
543
+ [GPIO_IJKL_DIRECTION] = { 2, gpio_reg_direction },
544
+ [GPIO_IJKL_INT_ENABLE] = { 2, gpio_reg_int_enable },
545
+ [GPIO_IJKL_INT_SENS_0] = { 2, gpio_reg_int_sens_0 },
546
+ [GPIO_IJKL_INT_SENS_1] = { 2, gpio_reg_int_sens_1 },
547
+ [GPIO_IJKL_INT_SENS_2] = { 2, gpio_reg_int_sens_2 },
548
+ [GPIO_IJKL_INT_STATUS] = { 2, gpio_reg_int_status },
549
+ [GPIO_IJKL_RESET_TOLERANT] = { 2, gpio_reg_reset_tolerant },
550
+ [GPIO_IJKL_DEBOUNCE_1] = { 2, gpio_reg_debounce_1 },
551
+ [GPIO_IJKL_DEBOUNCE_2] = { 2, gpio_reg_debounce_2 },
552
+ [GPIO_IJKL_COMMAND_SRC_0] = { 2, gpio_reg_cmd_source_0 },
553
+ [GPIO_IJKL_COMMAND_SRC_1] = { 2, gpio_reg_cmd_source_1 },
554
+ [GPIO_IJKL_DATA_READ] = { 2, gpio_reg_data_read },
555
+ [GPIO_IJKL_INPUT_MASK] = { 2, gpio_reg_input_mask },
556
+ /* Set MNOP */
557
+ [GPIO_MNOP_DATA_VALUE] = { 3, gpio_reg_data_value },
558
+ [GPIO_MNOP_DIRECTION] = { 3, gpio_reg_direction },
559
+ [GPIO_MNOP_INT_ENABLE] = { 3, gpio_reg_int_enable },
560
+ [GPIO_MNOP_INT_SENS_0] = { 3, gpio_reg_int_sens_0 },
561
+ [GPIO_MNOP_INT_SENS_1] = { 3, gpio_reg_int_sens_1 },
562
+ [GPIO_MNOP_INT_SENS_2] = { 3, gpio_reg_int_sens_2 },
563
+ [GPIO_MNOP_INT_STATUS] = { 3, gpio_reg_int_status },
564
+ [GPIO_MNOP_RESET_TOLERANT] = { 3, gpio_reg_reset_tolerant },
565
+ [GPIO_MNOP_DEBOUNCE_1] = { 3, gpio_reg_debounce_1 },
566
+ [GPIO_MNOP_DEBOUNCE_2] = { 3, gpio_reg_debounce_2 },
567
+ [GPIO_MNOP_COMMAND_SRC_0] = { 3, gpio_reg_cmd_source_0 },
568
+ [GPIO_MNOP_COMMAND_SRC_1] = { 3, gpio_reg_cmd_source_1 },
569
+ [GPIO_MNOP_DATA_READ] = { 3, gpio_reg_data_read },
570
+ [GPIO_MNOP_INPUT_MASK] = { 3, gpio_reg_input_mask },
571
+ /* Set QRST */
572
+ [GPIO_QRST_DATA_VALUE] = { 4, gpio_reg_data_value },
573
+ [GPIO_QRST_DIRECTION] = { 4, gpio_reg_direction },
574
+ [GPIO_QRST_INT_ENABLE] = { 4, gpio_reg_int_enable },
575
+ [GPIO_QRST_INT_SENS_0] = { 4, gpio_reg_int_sens_0 },
576
+ [GPIO_QRST_INT_SENS_1] = { 4, gpio_reg_int_sens_1 },
577
+ [GPIO_QRST_INT_SENS_2] = { 4, gpio_reg_int_sens_2 },
578
+ [GPIO_QRST_INT_STATUS] = { 4, gpio_reg_int_status },
579
+ [GPIO_QRST_RESET_TOLERANT] = { 4, gpio_reg_reset_tolerant },
580
+ [GPIO_QRST_DEBOUNCE_1] = { 4, gpio_reg_debounce_1 },
581
+ [GPIO_QRST_DEBOUNCE_2] = { 4, gpio_reg_debounce_2 },
582
+ [GPIO_QRST_COMMAND_SRC_0] = { 4, gpio_reg_cmd_source_0 },
583
+ [GPIO_QRST_COMMAND_SRC_1] = { 4, gpio_reg_cmd_source_1 },
584
+ [GPIO_QRST_DATA_READ] = { 4, gpio_reg_data_read },
585
+ [GPIO_QRST_INPUT_MASK] = { 4, gpio_reg_input_mask },
586
+ /* Set UVWX */
587
+ [GPIO_UVWX_DATA_VALUE] = { 5, gpio_reg_data_value },
588
+ [GPIO_UVWX_DIRECTION] = { 5, gpio_reg_direction },
589
+ [GPIO_UVWX_INT_ENABLE] = { 5, gpio_reg_int_enable },
590
+ [GPIO_UVWX_INT_SENS_0] = { 5, gpio_reg_int_sens_0 },
591
+ [GPIO_UVWX_INT_SENS_1] = { 5, gpio_reg_int_sens_1 },
592
+ [GPIO_UVWX_INT_SENS_2] = { 5, gpio_reg_int_sens_2 },
593
+ [GPIO_UVWX_INT_STATUS] = { 5, gpio_reg_int_status },
594
+ [GPIO_UVWX_RESET_TOLERANT] = { 5, gpio_reg_reset_tolerant },
595
+ [GPIO_UVWX_DEBOUNCE_1] = { 5, gpio_reg_debounce_1 },
596
+ [GPIO_UVWX_DEBOUNCE_2] = { 5, gpio_reg_debounce_2 },
597
+ [GPIO_UVWX_COMMAND_SRC_0] = { 5, gpio_reg_cmd_source_0 },
598
+ [GPIO_UVWX_COMMAND_SRC_1] = { 5, gpio_reg_cmd_source_1 },
599
+ [GPIO_UVWX_DATA_READ] = { 5, gpio_reg_data_read },
600
+ [GPIO_UVWX_INPUT_MASK] = { 5, gpio_reg_input_mask },
601
+ /* Set YZAAAB */
602
+ [GPIO_YZAAAB_DATA_VALUE] = { 6, gpio_reg_data_value },
603
+ [GPIO_YZAAAB_DIRECTION] = { 6, gpio_reg_direction },
604
+ [GPIO_YZAAAB_INT_ENABLE] = { 6, gpio_reg_int_enable },
605
+ [GPIO_YZAAAB_INT_SENS_0] = { 6, gpio_reg_int_sens_0 },
606
+ [GPIO_YZAAAB_INT_SENS_1] = { 6, gpio_reg_int_sens_1 },
607
+ [GPIO_YZAAAB_INT_SENS_2] = { 6, gpio_reg_int_sens_2 },
608
+ [GPIO_YZAAAB_INT_STATUS] = { 6, gpio_reg_int_status },
609
+ [GPIO_YZAAAB_RESET_TOLERANT] = { 6, gpio_reg_reset_tolerant },
610
+ [GPIO_YZAAAB_DEBOUNCE_1] = { 6, gpio_reg_debounce_1 },
611
+ [GPIO_YZAAAB_DEBOUNCE_2] = { 6, gpio_reg_debounce_2 },
612
+ [GPIO_YZAAAB_COMMAND_SRC_0] = { 6, gpio_reg_cmd_source_0 },
613
+ [GPIO_YZAAAB_COMMAND_SRC_1] = { 6, gpio_reg_cmd_source_1 },
614
+ [GPIO_YZAAAB_DATA_READ] = { 6, gpio_reg_data_read },
615
+ [GPIO_YZAAAB_INPUT_MASK] = { 6, gpio_reg_input_mask },
616
+ /* Set AC (ast2500 only) */
617
+ [GPIO_AC_DATA_VALUE] = { 7, gpio_reg_data_value },
618
+ [GPIO_AC_DIRECTION] = { 7, gpio_reg_direction },
619
+ [GPIO_AC_INT_ENABLE] = { 7, gpio_reg_int_enable },
620
+ [GPIO_AC_INT_SENS_0] = { 7, gpio_reg_int_sens_0 },
621
+ [GPIO_AC_INT_SENS_1] = { 7, gpio_reg_int_sens_1 },
622
+ [GPIO_AC_INT_SENS_2] = { 7, gpio_reg_int_sens_2 },
623
+ [GPIO_AC_INT_STATUS] = { 7, gpio_reg_int_status },
624
+ [GPIO_AC_RESET_TOLERANT] = { 7, gpio_reg_reset_tolerant },
625
+ [GPIO_AC_DEBOUNCE_1] = { 7, gpio_reg_debounce_1 },
626
+ [GPIO_AC_DEBOUNCE_2] = { 7, gpio_reg_debounce_2 },
627
+ [GPIO_AC_COMMAND_SRC_0] = { 7, gpio_reg_cmd_source_0 },
628
+ [GPIO_AC_COMMAND_SRC_1] = { 7, gpio_reg_cmd_source_1 },
629
+ [GPIO_AC_DATA_READ] = { 7, gpio_reg_data_read },
630
+ [GPIO_AC_INPUT_MASK] = { 7, gpio_reg_input_mask },
631
+};
632
+
633
+static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size)
634
+{
635
+ AspeedGPIOState *s = ASPEED_GPIO(opaque);
636
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
637
+ uint64_t idx = -1;
638
+ const AspeedGPIOReg *reg;
639
+ GPIOSets *set;
640
+
641
+ idx = offset >> 2;
642
+ if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) {
643
+ idx -= GPIO_DEBOUNCE_TIME_1;
644
+ return (uint64_t) s->debounce_regs[idx];
645
+ }
646
+
647
+ reg = &agc->reg_table[idx];
648
+ if (reg->set_idx >= agc->nr_gpio_sets) {
649
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%"
650
+ HWADDR_PRIx"\n", __func__, offset);
651
+ return 0;
652
+ }
653
+
654
+ set = &s->sets[reg->set_idx];
655
+ switch (reg->type) {
656
+ case gpio_reg_data_value:
657
+ return set->data_value;
658
+ case gpio_reg_direction:
659
+ return set->direction;
660
+ case gpio_reg_int_enable:
661
+ return set->int_enable;
662
+ case gpio_reg_int_sens_0:
663
+ return set->int_sens_0;
664
+ case gpio_reg_int_sens_1:
665
+ return set->int_sens_1;
666
+ case gpio_reg_int_sens_2:
667
+ return set->int_sens_2;
668
+ case gpio_reg_int_status:
669
+ return set->int_status;
670
+ case gpio_reg_reset_tolerant:
671
+ return set->reset_tol;
672
+ case gpio_reg_debounce_1:
673
+ return set->debounce_1;
674
+ case gpio_reg_debounce_2:
675
+ return set->debounce_2;
676
+ case gpio_reg_cmd_source_0:
677
+ return set->cmd_source_0;
678
+ case gpio_reg_cmd_source_1:
679
+ return set->cmd_source_1;
680
+ case gpio_reg_data_read:
681
+ return set->data_read;
682
+ case gpio_reg_input_mask:
683
+ return set->input_mask;
684
+ default:
685
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%"
686
+ HWADDR_PRIx"\n", __func__, offset);
687
+ return 0;
688
+ };
689
+}
690
+
691
+static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data,
692
+ uint32_t size)
693
+{
694
+ AspeedGPIOState *s = ASPEED_GPIO(opaque);
695
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
696
+ const GPIOSetProperties *props;
697
+ uint64_t idx = -1;
698
+ const AspeedGPIOReg *reg;
699
+ GPIOSets *set;
700
+ uint32_t cleared;
701
+
702
+ idx = offset >> 2;
703
+ if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) {
704
+ idx -= GPIO_DEBOUNCE_TIME_1;
705
+ s->debounce_regs[idx] = (uint32_t) data;
706
+ return;
707
+ }
708
+
709
+ reg = &agc->reg_table[idx];
710
+ if (reg->set_idx >= agc->nr_gpio_sets) {
711
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%"
712
+ HWADDR_PRIx"\n", __func__, offset);
713
+ return;
714
+ }
715
+
716
+ set = &s->sets[reg->set_idx];
717
+ props = &agc->props[reg->set_idx];
718
+
719
+ switch (reg->type) {
720
+ case gpio_reg_data_value:
721
+ data &= props->output;
722
+ data = update_value_control_source(set, set->data_value, data);
723
+ set->data_read = data;
724
+ aspeed_gpio_update(s, set, data);
725
+ return;
726
+ case gpio_reg_direction:
727
+ /*
728
+ * where data is the value attempted to be written to the pin:
729
+ * pin type | input mask | output mask | expected value
730
+ * ------------------------------------------------------------
731
+ * bidirectional | 1 | 1 | data
732
+ * input only | 1 | 0 | 0
733
+ * output only | 0 | 1 | 1
734
+ * no pin / gap | 0 | 0 | 0
735
+ *
736
+ * which is captured by:
737
+ * data = ( data | ~input) & output;
738
+ */
739
+ data = (data | ~props->input) & props->output;
740
+ set->direction = update_value_control_source(set, set->direction, data);
741
+ break;
742
+ case gpio_reg_int_enable:
743
+ set->int_enable = update_value_control_source(set, set->int_enable,
744
+ data);
745
+ break;
746
+ case gpio_reg_int_sens_0:
747
+ set->int_sens_0 = update_value_control_source(set, set->int_sens_0,
748
+ data);
749
+ break;
750
+ case gpio_reg_int_sens_1:
751
+ set->int_sens_1 = update_value_control_source(set, set->int_sens_1,
752
+ data);
753
+ break;
754
+ case gpio_reg_int_sens_2:
755
+ set->int_sens_2 = update_value_control_source(set, set->int_sens_2,
756
+ data);
757
+ break;
758
+ case gpio_reg_int_status:
759
+ cleared = ctpop32(data & set->int_status);
760
+ if (s->pending && cleared) {
761
+ assert(s->pending >= cleared);
762
+ s->pending -= cleared;
763
+ }
764
+ set->int_status &= ~data;
765
+ break;
766
+ case gpio_reg_reset_tolerant:
767
+ set->reset_tol = update_value_control_source(set, set->reset_tol,
768
+ data);
769
+ return;
770
+ case gpio_reg_debounce_1:
771
+ set->debounce_1 = update_value_control_source(set, set->debounce_1,
772
+ data);
773
+ return;
774
+ case gpio_reg_debounce_2:
775
+ set->debounce_2 = update_value_control_source(set, set->debounce_2,
776
+ data);
777
+ return;
778
+ case gpio_reg_cmd_source_0:
779
+ set->cmd_source_0 = data & ASPEED_CMD_SRC_MASK;
780
+ return;
781
+ case gpio_reg_cmd_source_1:
782
+ set->cmd_source_1 = data & ASPEED_CMD_SRC_MASK;
783
+ return;
784
+ case gpio_reg_data_read:
785
+ /* Read only register */
786
+ return;
787
+ case gpio_reg_input_mask:
788
+ /*
789
+ * feeds into interrupt generation
790
+ * 0: read from data value reg will be updated
791
+ * 1: read from data value reg will not be updated
792
+ */
793
+ set->input_mask = data & props->input;
794
+ break;
795
+ default:
796
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%"
797
+ HWADDR_PRIx"\n", __func__, offset);
798
+ return;
799
+ }
800
+ aspeed_gpio_update(s, set, set->data_value);
801
+ return;
802
+}
803
+
804
+static int get_set_idx(AspeedGPIOState *s, const char *group, int *group_idx)
805
+{
806
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
807
+ int set_idx, g_idx = *group_idx;
808
+
809
+ for (set_idx = 0; set_idx < agc->nr_gpio_sets; set_idx++) {
810
+ const GPIOSetProperties *set_props = &agc->props[set_idx];
811
+ for (g_idx = 0; g_idx < ASPEED_GROUPS_PER_SET; g_idx++) {
812
+ if (!strncmp(group, set_props->group_label[g_idx], strlen(group))) {
813
+ *group_idx = g_idx;
814
+ return set_idx;
815
+ }
816
+ }
817
+ }
818
+ return -1;
819
+}
820
+
821
+static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name,
822
+ void *opaque, Error **errp)
823
+{
824
+ int pin = 0xfff;
825
+ bool level = true;
826
+ char group[3];
827
+ AspeedGPIOState *s = ASPEED_GPIO(obj);
828
+ int set_idx, group_idx = 0;
829
+
830
+ if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
831
+ error_setg(errp, "%s: error reading %s", __func__, name);
832
+ return;
833
+ }
834
+ set_idx = get_set_idx(s, group, &group_idx);
835
+ if (set_idx == -1) {
836
+ error_setg(errp, "%s: invalid group %s", __func__, group);
837
+ return;
838
+ }
839
+ pin = pin + group_idx * GPIOS_PER_GROUP;
840
+ level = aspeed_gpio_get_pin_level(s, set_idx, pin);
841
+ visit_type_bool(v, name, &level, errp);
842
+}
843
+
844
+static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
845
+ void *opaque, Error **errp)
846
+{
847
+ Error *local_err = NULL;
848
+ bool level;
849
+ int pin = 0xfff;
850
+ char group[3];
851
+ AspeedGPIOState *s = ASPEED_GPIO(obj);
852
+ int set_idx, group_idx = 0;
853
+
854
+ visit_type_bool(v, name, &level, &local_err);
855
+ if (local_err) {
856
+ error_propagate(errp, local_err);
857
+ return;
858
+ }
859
+ if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
860
+ error_setg(errp, "%s: error reading %s", __func__, name);
861
+ return;
862
+ }
863
+ set_idx = get_set_idx(s, group, &group_idx);
864
+ if (set_idx == -1) {
865
+ error_setg(errp, "%s: invalid group %s", __func__, group);
866
+ return;
867
+ }
868
+ pin = pin + group_idx * GPIOS_PER_GROUP;
869
+ aspeed_gpio_set_pin_level(s, set_idx, pin, level);
870
+}
871
+
872
+/****************** Setup functions ******************/
873
+static const GPIOSetProperties ast2400_set_props[] = {
874
+ [0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} },
875
+ [1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} },
876
+ [2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} },
877
+ [3] = {0xffffffff, 0xffffffff, {"M", "N", "O", "P"} },
878
+ [4] = {0xffffffff, 0xffffffff, {"Q", "R", "S", "T"} },
879
+ [5] = {0xffffffff, 0x0000ffff, {"U", "V", "W", "X"} },
880
+ [6] = {0x0000000f, 0x0fffff0f, {"Y", "Z", "AA", "AB"} },
881
+};
882
+
883
+static const GPIOSetProperties ast2500_set_props[] = {
884
+ [0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} },
885
+ [1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} },
886
+ [2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} },
887
+ [3] = {0xffffffff, 0xffffffff, {"M", "N", "O", "P"} },
888
+ [4] = {0xffffffff, 0xffffffff, {"Q", "R", "S", "T"} },
889
+ [5] = {0xffffffff, 0x0000ffff, {"U", "V", "W", "X"} },
890
+ [6] = {0xffffff0f, 0x0fffff0f, {"Y", "Z", "AA", "AB"} },
891
+ [7] = {0x000000ff, 0x000000ff, {"AC"} },
892
+};
893
+
894
+static const MemoryRegionOps aspeed_gpio_ops = {
895
+ .read = aspeed_gpio_read,
896
+ .write = aspeed_gpio_write,
897
+ .endianness = DEVICE_LITTLE_ENDIAN,
898
+ .valid.min_access_size = 4,
899
+ .valid.max_access_size = 4,
900
+};
901
+
902
+static void aspeed_gpio_reset(DeviceState *dev)
903
+{
904
+ AspeedGPIOState *s = ASPEED_GPIO(dev);
905
+
906
+ /* TODO: respect the reset tolerance registers */
907
+ memset(s->sets, 0, sizeof(s->sets));
908
+}
909
+
910
+static void aspeed_gpio_realize(DeviceState *dev, Error **errp)
911
+{
912
+ AspeedGPIOState *s = ASPEED_GPIO(dev);
913
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
914
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
915
+ int pin;
916
+
917
+ /* Interrupt parent line */
918
+ sysbus_init_irq(sbd, &s->irq);
919
+
920
+ /* Individual GPIOs */
921
+ for (pin = 0; pin < agc->nr_gpio_pins; pin++) {
922
+ sysbus_init_irq(sbd, &s->gpios[pin]);
923
+ }
924
+
925
+ memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s,
926
+ TYPE_ASPEED_GPIO, GPIO_3_6V_MEM_SIZE);
927
+
928
+ sysbus_init_mmio(sbd, &s->iomem);
929
+}
930
+
931
+static void aspeed_gpio_init(Object *obj)
932
+{
933
+ AspeedGPIOState *s = ASPEED_GPIO(obj);
934
+ AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
935
+ int pin;
936
+
937
+ for (pin = 0; pin < agc->nr_gpio_pins; pin++) {
938
+ char *name;
939
+ int set_idx = pin / GPIOS_PER_SET;
940
+ int pin_idx = aspeed_adjust_pin(s, pin) - (set_idx * GPIOS_PER_SET);
941
+ int group_idx = pin_idx >> GPIO_GROUP_SHIFT;
942
+ const GPIOSetProperties *props = &agc->props[set_idx];
943
+
944
+ name = g_strdup_printf("gpio%s%d", props->group_label[group_idx],
945
+ pin_idx % GPIOS_PER_GROUP);
946
+ object_property_add(obj, name, "bool", aspeed_gpio_get_pin,
947
+ aspeed_gpio_set_pin, NULL, NULL, NULL);
948
+ }
949
+}
950
+
951
+static const VMStateDescription vmstate_gpio_regs = {
952
+ .name = TYPE_ASPEED_GPIO"/regs",
953
+ .version_id = 1,
954
+ .minimum_version_id = 1,
955
+ .fields = (VMStateField[]) {
956
+ VMSTATE_UINT32(data_value, GPIOSets),
957
+ VMSTATE_UINT32(data_read, GPIOSets),
958
+ VMSTATE_UINT32(direction, GPIOSets),
959
+ VMSTATE_UINT32(int_enable, GPIOSets),
960
+ VMSTATE_UINT32(int_sens_0, GPIOSets),
961
+ VMSTATE_UINT32(int_sens_1, GPIOSets),
962
+ VMSTATE_UINT32(int_sens_2, GPIOSets),
963
+ VMSTATE_UINT32(int_status, GPIOSets),
964
+ VMSTATE_UINT32(reset_tol, GPIOSets),
965
+ VMSTATE_UINT32(cmd_source_0, GPIOSets),
966
+ VMSTATE_UINT32(cmd_source_1, GPIOSets),
967
+ VMSTATE_UINT32(debounce_1, GPIOSets),
968
+ VMSTATE_UINT32(debounce_2, GPIOSets),
969
+ VMSTATE_UINT32(input_mask, GPIOSets),
970
+ VMSTATE_END_OF_LIST(),
971
+ }
972
+};
973
+
974
+static const VMStateDescription vmstate_aspeed_gpio = {
975
+ .name = TYPE_ASPEED_GPIO,
976
+ .version_id = 1,
977
+ .minimum_version_id = 1,
978
+ .fields = (VMStateField[]) {
979
+ VMSTATE_STRUCT_ARRAY(sets, AspeedGPIOState, ASPEED_GPIO_MAX_NR_SETS,
980
+ 1, vmstate_gpio_regs, GPIOSets),
981
+ VMSTATE_UINT32_ARRAY(debounce_regs, AspeedGPIOState,
982
+ ASPEED_GPIO_NR_DEBOUNCE_REGS),
983
+ VMSTATE_END_OF_LIST(),
984
+ }
985
+};
986
+
987
+static void aspeed_gpio_class_init(ObjectClass *klass, void *data)
988
+{
989
+ DeviceClass *dc = DEVICE_CLASS(klass);
990
+
991
+ dc->realize = aspeed_gpio_realize;
992
+ dc->reset = aspeed_gpio_reset;
993
+ dc->desc = "Aspeed GPIO Controller";
994
+ dc->vmsd = &vmstate_aspeed_gpio;
995
+}
996
+
997
+static void aspeed_gpio_ast2400_class_init(ObjectClass *klass, void *data)
998
+{
999
+ AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
1000
+
1001
+ agc->props = ast2400_set_props;
1002
+ agc->nr_gpio_pins = 216;
1003
+ agc->nr_gpio_sets = 7;
1004
+ agc->gap = 196;
1005
+ agc->reg_table = aspeed_3_6v_gpios;
1006
+}
1007
+
1008
+static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data)
1009
+{
1010
+ AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
1011
+
1012
+ agc->props = ast2500_set_props;
1013
+ agc->nr_gpio_pins = 228;
1014
+ agc->nr_gpio_sets = 8;
1015
+ agc->gap = 220;
1016
+ agc->reg_table = aspeed_3_6v_gpios;
1017
+}
1018
+
1019
+static const TypeInfo aspeed_gpio_info = {
1020
+ .name = TYPE_ASPEED_GPIO,
1021
+ .parent = TYPE_SYS_BUS_DEVICE,
1022
+ .instance_size = sizeof(AspeedGPIOState),
1023
+ .class_size = sizeof(AspeedGPIOClass),
1024
+ .class_init = aspeed_gpio_class_init,
1025
+ .abstract = true,
1026
+};
1027
+
1028
+static const TypeInfo aspeed_gpio_ast2400_info = {
1029
+ .name = TYPE_ASPEED_GPIO "-ast2400",
1030
+ .parent = TYPE_ASPEED_GPIO,
1031
+ .class_init = aspeed_gpio_ast2400_class_init,
1032
+ .instance_init = aspeed_gpio_init,
1033
+};
1034
+
1035
+static const TypeInfo aspeed_gpio_ast2500_info = {
1036
+ .name = TYPE_ASPEED_GPIO "-ast2500",
1037
+ .parent = TYPE_ASPEED_GPIO,
1038
+ .class_init = aspeed_gpio_2500_class_init,
1039
+ .instance_init = aspeed_gpio_init,
1040
+};
1041
+
1042
+static void aspeed_gpio_register_types(void)
1043
+{
1044
+ type_register_static(&aspeed_gpio_info);
1045
+ type_register_static(&aspeed_gpio_ast2400_info);
1046
+ type_register_static(&aspeed_gpio_ast2500_info);
1047
+}
1048
+
1049
+type_init(aspeed_gpio_register_types);
47
--
1050
--
48
2.7.4
1051
2.20.1
49
1052
50
1053
diff view generated by jsdifflib
Deleted patch
1
From: Michael Weiser <michael.weiser@gmx.de>
2
1
3
As we now have a linux-user aarch64_be target, we can add it to the list
4
of supported targets in qemu-binfmt-conf.sh
5
6
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
7
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
8
Message-id: 20171220212308.12614-6-michael.weiser@gmx.de
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
scripts/qemu-binfmt-conf.sh | 6 +++++-
12
1 file changed, 5 insertions(+), 1 deletion(-)
13
14
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
15
index XXXXXXX..XXXXXXX 100755
16
--- a/scripts/qemu-binfmt-conf.sh
17
+++ b/scripts/qemu-binfmt-conf.sh
18
@@ -XXX,XX +XXX,XX @@
19
20
qemu_target_list="i386 i486 alpha arm sparc32plus ppc ppc64 ppc64le m68k \
21
mips mipsel mipsn32 mipsn32el mips64 mips64el \
22
-sh4 sh4eb s390x aarch64 hppa"
23
+sh4 sh4eb s390x aarch64 aarch64_be hppa"
24
25
i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
26
i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
27
@@ -XXX,XX +XXX,XX @@ aarch64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x
28
aarch64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
29
aarch64_family=arm
30
31
+aarch64_be_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7'
32
+aarch64_be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
33
+aarch64_be_family=arm
34
+
35
hppa_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0f'
36
hppa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
37
hppa_family=hppa
38
--
39
2.7.4
40
41
diff view generated by jsdifflib
Deleted patch
1
From: Michael Weiser <michael.weiser@gmx.de>
2
1
3
Give big-endian arm and aarch64 CPUs their own family in
4
qemu-binfmt-conf.sh to make sure we register qemu-user for binaries of
5
the opposite endianness on arm and aarch64. Apart from the family
6
assignments of the magic values, qemu_get_family() needs to be able to
7
distinguish the two and recognise aarch64{,_be} as well.
8
9
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
10
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
11
Message-id: 20171220212308.12614-7-michael.weiser@gmx.de
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
scripts/qemu-binfmt-conf.sh | 9 ++++++---
15
1 file changed, 6 insertions(+), 3 deletions(-)
16
17
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
18
index XXXXXXX..XXXXXXX 100755
19
--- a/scripts/qemu-binfmt-conf.sh
20
+++ b/scripts/qemu-binfmt-conf.sh
21
@@ -XXX,XX +XXX,XX @@ arm_family=arm
22
23
armeb_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28'
24
armeb_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
25
-armeb_family=arm
26
+armeb_family=armeb
27
28
sparc_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02'
29
sparc_mask='\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
30
@@ -XXX,XX +XXX,XX @@ aarch64_family=arm
31
32
aarch64_be_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7'
33
aarch64_be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
34
-aarch64_be_family=arm
35
+aarch64_be_family=armeb
36
37
hppa_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0f'
38
hppa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
39
@@ -XXX,XX +XXX,XX @@ qemu_get_family() {
40
ppc64el|ppc64le)
41
echo "ppcle"
42
;;
43
- arm|armel|armhf|arm64|armv[4-9]*)
44
+ arm|armel|armhf|arm64|armv[4-9]*l|aarch64)
45
echo "arm"
46
;;
47
+ armeb|armv[4-9]*b|aarch64_be)
48
+ echo "armeb"
49
+ ;;
50
sparc*)
51
echo "sparc"
52
;;
53
--
54
2.7.4
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Michael Weiser <michael.weiser@gmx.de>
2
1
3
armeb is missing from the target list in qemu-binfmt-conf.sh. Add it so
4
the handler for those binaries gets registered by the script.
5
6
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
7
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
8
Message-id: 20171220212308.12614-8-michael.weiser@gmx.de
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
scripts/qemu-binfmt-conf.sh | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
15
index XXXXXXX..XXXXXXX 100755
16
--- a/scripts/qemu-binfmt-conf.sh
17
+++ b/scripts/qemu-binfmt-conf.sh
18
@@ -XXX,XX +XXX,XX @@
19
# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC/s390/HPPA
20
# program execution by the kernel
21
22
-qemu_target_list="i386 i486 alpha arm sparc32plus ppc ppc64 ppc64le m68k \
23
+qemu_target_list="i386 i486 alpha arm armeb sparc32plus ppc ppc64 ppc64le m68k \
24
mips mipsel mipsn32 mipsn32el mips64 mips64el \
25
sh4 sh4eb s390x aarch64 aarch64_be hppa"
26
27
--
28
2.7.4
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Michael Weiser <michael.weiser@gmx.de>
2
1
3
ldxp loads two consecutive doublewords from memory regardless of CPU
4
endianness. On store, stlxp currently assumes to work with a 128bit
5
value and consequently switches order in big-endian mode. With this
6
change it packs the doublewords in reverse order in anticipation of the
7
128bit big-endian store operation interposing them so they end up in
8
memory in the right order. This makes it work for both MTTCG and !MTTCG.
9
It effectively implements the ARM ARM STLXP operation pseudo-code:
10
11
data = if BigEndian() then el1:el2 else el2:el1;
12
13
With this change an aarch64_be Linux 4.14.4 kernel succeeds to boot up
14
in system emulation mode.
15
16
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
target/arm/helper-a64.c | 7 +++++--
21
1 file changed, 5 insertions(+), 2 deletions(-)
22
23
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/helper-a64.c
26
+++ b/target/arm/helper-a64.c
27
@@ -XXX,XX +XXX,XX @@ static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
28
Int128 oldv, cmpv, newv;
29
bool success;
30
31
- cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
32
- newv = int128_make128(new_lo, new_hi);
33
+ /* high and low need to be switched here because this is not actually a
34
+ * 128bit store but two doublewords stored consecutively
35
+ */
36
+ cmpv = int128_make128(env->exclusive_high, env->exclusive_val);
37
+ newv = int128_make128(new_hi, new_lo);
38
39
if (parallel) {
40
#ifndef CONFIG_ATOMIC128
41
--
42
2.7.4
43
44
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Rashmica Gupta <rashmica.g@gmail.com>
2
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
4
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
4
Reviewed-by: Cédric Le Goater <clg@kaod.org>
5
Message-id: 20180104000156.30932-1-f4bug@amsat.org
5
Signed-off-by: Cédric Le Goater <clg@kaod.org>
6
[PMM: add missing include]
6
Message-id: 20190904070506.1052-3-clg@kaod.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
8
---
9
hw/sd/pxa2xx_mmci.c | 78 ++++++++++++++++++++++++++++++++++-------------------
9
include/hw/arm/aspeed_soc.h | 3 +++
10
hw/sd/trace-events | 4 +++
10
hw/arm/aspeed_soc.c | 17 +++++++++++++++++
11
2 files changed, 54 insertions(+), 28 deletions(-)
11
2 files changed, 20 insertions(+)
12
12
13
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
13
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/sd/pxa2xx_mmci.c
15
--- a/include/hw/arm/aspeed_soc.h
16
+++ b/hw/sd/pxa2xx_mmci.c
16
+++ b/include/hw/arm/aspeed_soc.h
17
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/qdev.h"
18
#include "hw/watchdog/wdt_aspeed.h"
19
#include "hw/qdev-properties.h"
19
#include "hw/net/ftgmac100.h"
20
#include "qemu/error-report.h"
20
#include "target/arm/cpu.h"
21
+#include "qemu/log.h"
21
+#include "hw/gpio/aspeed_gpio.h"
22
+#include "trace.h"
22
23
23
#define ASPEED_SPIS_NUM 2
24
#define TYPE_PXA2XX_MMCI "pxa2xx-mmci"
24
#define ASPEED_WDTS_NUM 3
25
#define PXA2XX_MMCI(obj) OBJECT_CHECK(PXA2xxMMCIState, (obj), TYPE_PXA2XX_MMCI)
25
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState {
26
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_wakequeues(PXA2xxMMCIState *s)
26
AspeedSDMCState sdmc;
27
static uint64_t pxa2xx_mmci_read(void *opaque, hwaddr offset, unsigned size)
27
AspeedWDTState wdt[ASPEED_WDTS_NUM];
28
{
28
FTGMAC100State ftgmac100[ASPEED_MACS_NUM];
29
PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
29
+ AspeedGPIOState gpio;
30
- uint32_t ret;
30
} AspeedSoCState;
31
+ uint32_t ret = 0;
31
32
32
#define TYPE_ASPEED_SOC "aspeed-soc"
33
switch (offset) {
33
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCInfo {
34
case MMC_STRPCL:
34
int spis_num;
35
- return 0;
35
const char *fmc_typename;
36
+ break;
36
const char **spi_typename;
37
case MMC_STAT:
37
+ const char *gpio_typename;
38
- return s->status;
38
int wdts_num;
39
+ ret = s->status;
39
const int *irqmap;
40
+ break;
40
const hwaddr *memmap;
41
case MMC_CLKRT:
41
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
42
- return s->clkrt;
42
index XXXXXXX..XXXXXXX 100644
43
+ ret = s->clkrt;
43
--- a/hw/arm/aspeed_soc.c
44
+ break;
44
+++ b/hw/arm/aspeed_soc.c
45
case MMC_SPI:
45
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
46
- return s->spi;
46
.spis_num = 1,
47
+ ret = s->spi;
47
.fmc_typename = "aspeed.smc.fmc",
48
+ break;
48
.spi_typename = aspeed_soc_ast2400_typenames,
49
case MMC_CMDAT:
49
+ .gpio_typename = "aspeed.gpio-ast2400",
50
- return s->cmdat;
50
.wdts_num = 2,
51
+ ret = s->cmdat;
51
.irqmap = aspeed_soc_ast2400_irqmap,
52
+ break;
52
.memmap = aspeed_soc_ast2400_memmap,
53
case MMC_RESTO:
53
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
54
- return s->resp_tout;
54
.spis_num = 1,
55
+ ret = s->resp_tout;
55
.fmc_typename = "aspeed.smc.fmc",
56
+ break;
56
.spi_typename = aspeed_soc_ast2400_typenames,
57
case MMC_RDTO:
57
+ .gpio_typename = "aspeed.gpio-ast2400",
58
- return s->read_tout;
58
.wdts_num = 2,
59
+ ret = s->read_tout;
59
.irqmap = aspeed_soc_ast2400_irqmap,
60
+ break;
60
.memmap = aspeed_soc_ast2400_memmap,
61
case MMC_BLKLEN:
61
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
62
- return s->blklen;
62
.spis_num = 1,
63
+ ret = s->blklen;
63
.fmc_typename = "aspeed.smc.fmc",
64
+ break;
64
.spi_typename = aspeed_soc_ast2400_typenames,
65
case MMC_NUMBLK:
65
+ .gpio_typename = "aspeed.gpio-ast2400",
66
- return s->numblk;
66
.wdts_num = 2,
67
+ ret = s->numblk;
67
.irqmap = aspeed_soc_ast2400_irqmap,
68
+ break;
68
.memmap = aspeed_soc_ast2400_memmap,
69
case MMC_PRTBUF:
69
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
70
- return 0;
70
.spis_num = 2,
71
+ break;
71
.fmc_typename = "aspeed.smc.ast2500-fmc",
72
case MMC_I_MASK:
72
.spi_typename = aspeed_soc_ast2500_typenames,
73
- return s->intmask;
73
+ .gpio_typename = "aspeed.gpio-ast2500",
74
+ ret = s->intmask;
74
.wdts_num = 3,
75
+ break;
75
.irqmap = aspeed_soc_ast2500_irqmap,
76
case MMC_I_REG:
76
.memmap = aspeed_soc_ast2500_memmap,
77
- return s->intreq;
77
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
78
+ ret = s->intreq;
78
79
+ break;
79
sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma),
80
case MMC_CMD:
80
TYPE_ASPEED_XDMA);
81
- return s->cmd | 0x40;
81
+
82
+ ret = s->cmd | 0x40;
82
+ sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio),
83
+ break;
83
+ sc->info->gpio_typename);
84
case MMC_ARGH:
85
- return s->arg >> 16;
86
+ ret = s->arg >> 16;
87
+ break;
88
case MMC_ARGL:
89
- return s->arg & 0xffff;
90
+ ret = s->arg & 0xffff;
91
+ break;
92
case MMC_RES:
93
- if (s->resp_len < 9)
94
- return s->resp_fifo[s->resp_len ++];
95
- return 0;
96
+ ret = (s->resp_len < 9) ? s->resp_fifo[s->resp_len++] : 0;
97
+ break;
98
case MMC_RXFIFO:
99
- ret = 0;
100
while (size-- && s->rx_len) {
101
ret |= s->rx_fifo[s->rx_start++] << (size << 3);
102
s->rx_start &= 0x1f;
103
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_mmci_read(void *opaque, hwaddr offset, unsigned size)
104
}
105
s->intreq &= ~INT_RXFIFO_REQ;
106
pxa2xx_mmci_fifo_update(s);
107
- return ret;
108
+ break;
109
case MMC_RDWAIT:
110
- return 0;
111
+ break;
112
case MMC_BLKS_REM:
113
- return s->numblk;
114
+ ret = s->numblk;
115
+ break;
116
default:
117
- hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
118
+ qemu_log_mask(LOG_GUEST_ERROR,
119
+ "%s: incorrect register 0x%02" HWADDR_PRIx "\n",
120
+ __func__, offset);
121
}
122
+ trace_pxa2xx_mmci_read(size, offset, ret);
123
124
- return 0;
125
+ return ret;
126
}
84
}
127
85
128
static void pxa2xx_mmci_write(void *opaque,
86
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
129
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_write(void *opaque,
87
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
130
{
88
sc->info->memmap[ASPEED_XDMA]);
131
PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
89
sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0,
132
90
aspeed_soc_get_irq(s, ASPEED_XDMA));
133
+ trace_pxa2xx_mmci_write(size, offset, value);
91
+
134
switch (offset) {
92
+ /* GPIO */
135
case MMC_STRPCL:
93
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
136
if (value & STRPCL_STRT_CLK) {
94
+ if (err) {
137
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_write(void *opaque,
95
+ error_propagate(errp, err);
138
96
+ return;
139
case MMC_SPI:
97
+ }
140
s->spi = value & 0xf;
98
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->info->memmap[ASPEED_GPIO]);
141
- if (value & SPI_SPI_MODE)
99
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
142
- printf("%s: attempted to use card in SPI mode\n", __FUNCTION__);
100
+ aspeed_soc_get_irq(s, ASPEED_GPIO));
143
+ if (value & SPI_SPI_MODE) {
144
+ qemu_log_mask(LOG_GUEST_ERROR,
145
+ "%s: attempted to use card in SPI mode\n", __func__);
146
+ }
147
break;
148
149
case MMC_CMDAT:
150
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_write(void *opaque,
151
break;
152
153
default:
154
- hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
155
+ qemu_log_mask(LOG_GUEST_ERROR,
156
+ "%s: incorrect reg 0x%02" HWADDR_PRIx " "
157
+ "(value 0x%08" PRIx64 ")\n", __func__, offset, value);
158
}
159
}
101
}
160
102
static Property aspeed_soc_properties[] = {
161
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
103
DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0),
162
index XXXXXXX..XXXXXXX 100644
163
--- a/hw/sd/trace-events
164
+++ b/hw/sd/trace-events
165
@@ -XXX,XX +XXX,XX @@
166
# hw/sd/milkymist-memcard.c
167
milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
168
milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
169
+
170
+# hw/sd/pxa2xx_mmci.c
171
+pxa2xx_mmci_read(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x"
172
+pxa2xx_mmci_write(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x"
173
--
104
--
174
2.7.4
105
2.20.1
175
106
176
107
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
Make Tx frame assembly buffer to be a paort of IMXFECState structure
3
There are no QEMU Aspeed machines using the SoCs "ast2400-a0" or
4
to avoid a concern about having large data buffer on the stack.
4
"ast2400".
5
5
6
Cc: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Cédric Le Goater <clg@kaod.org>
7
Cc: Jason Wang <jasowang@redhat.com>
7
Message-id: 20190904070506.1052-4-clg@kaod.org
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Cc: qemu-devel@nongnu.org
10
Cc: qemu-arm@nongnu.org
11
Cc: yurovsky@gmail.com
12
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
include/hw/net/imx_fec.h | 3 +++
11
hw/arm/aspeed_soc.c | 26 --------------------------
17
hw/net/imx_fec.c | 22 +++++++++++-----------
12
1 file changed, 26 deletions(-)
18
2 files changed, 14 insertions(+), 11 deletions(-)
19
13
20
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
14
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/net/imx_fec.h
16
--- a/hw/arm/aspeed_soc.c
23
+++ b/include/hw/net/imx_fec.h
17
+++ b/hw/arm/aspeed_soc.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct IMXFECState {
18
@@ -XXX,XX +XXX,XX @@ static const char *aspeed_soc_ast2500_typenames[] = {
25
uint32_t phy_int_mask;
19
26
20
static const AspeedSoCInfo aspeed_socs[] = {
27
bool is_fec;
21
{
28
+
22
- .name = "ast2400-a0",
29
+ /* Buffer used to assemble a Tx frame */
23
- .cpu_type = ARM_CPU_TYPE_NAME("arm926"),
30
+ uint8_t frame[ENET_MAX_FRAME_SIZE];
24
- .silicon_rev = AST2400_A0_SILICON_REV,
31
} IMXFECState;
25
- .sram_size = 0x8000,
32
26
- .spis_num = 1,
33
#endif
27
- .fmc_typename = "aspeed.smc.fmc",
34
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
28
- .spi_typename = aspeed_soc_ast2400_typenames,
35
index XXXXXXX..XXXXXXX 100644
29
- .gpio_typename = "aspeed.gpio-ast2400",
36
--- a/hw/net/imx_fec.c
30
- .wdts_num = 2,
37
+++ b/hw/net/imx_fec.c
31
- .irqmap = aspeed_soc_ast2400_irqmap,
38
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s)
32
- .memmap = aspeed_soc_ast2400_memmap,
39
static void imx_fec_do_tx(IMXFECState *s)
33
- .num_cpus = 1,
40
{
34
- }, {
41
int frame_size = 0, descnt = 0;
35
.name = "ast2400-a1",
42
- uint8_t frame[ENET_MAX_FRAME_SIZE];
36
.cpu_type = ARM_CPU_TYPE_NAME("arm926"),
43
- uint8_t *ptr = frame;
37
.silicon_rev = AST2400_A1_SILICON_REV,
44
+ uint8_t *ptr = s->frame;
38
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
45
uint32_t addr = s->tx_descriptor;
39
.irqmap = aspeed_soc_ast2400_irqmap,
46
40
.memmap = aspeed_soc_ast2400_memmap,
47
while (descnt++ < IMX_MAX_DESC) {
41
.num_cpus = 1,
48
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
42
- }, {
49
frame_size += len;
43
- .name = "ast2400",
50
if (bd.flags & ENET_BD_L) {
44
- .cpu_type = ARM_CPU_TYPE_NAME("arm926"),
51
/* Last buffer in frame. */
45
- .silicon_rev = AST2400_A0_SILICON_REV,
52
- qemu_send_packet(qemu_get_queue(s->nic), frame, frame_size);
46
- .sram_size = 0x8000,
53
- ptr = frame;
47
- .spis_num = 1,
54
+ qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
48
- .fmc_typename = "aspeed.smc.fmc",
55
+ ptr = s->frame;
49
- .spi_typename = aspeed_soc_ast2400_typenames,
56
frame_size = 0;
50
- .gpio_typename = "aspeed.gpio-ast2400",
57
s->regs[ENET_EIR] |= ENET_INT_TXF;
51
- .wdts_num = 2,
58
}
52
- .irqmap = aspeed_soc_ast2400_irqmap,
59
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
53
- .memmap = aspeed_soc_ast2400_memmap,
60
static void imx_enet_do_tx(IMXFECState *s)
54
- .num_cpus = 1,
61
{
55
}, {
62
int frame_size = 0, descnt = 0;
56
.name = "ast2500-a1",
63
- uint8_t frame[ENET_MAX_FRAME_SIZE];
57
.cpu_type = ARM_CPU_TYPE_NAME("arm1176"),
64
- uint8_t *ptr = frame;
65
+ uint8_t *ptr = s->frame;
66
uint32_t addr = s->tx_descriptor;
67
68
while (descnt++ < IMX_MAX_DESC) {
69
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s)
70
frame_size += len;
71
if (bd.flags & ENET_BD_L) {
72
if (bd.option & ENET_BD_PINS) {
73
- struct ip_header *ip_hd = PKT_GET_IP_HDR(frame);
74
+ struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
75
if (IP_HEADER_VERSION(ip_hd) == 4) {
76
- net_checksum_calculate(frame, frame_size);
77
+ net_checksum_calculate(s->frame, frame_size);
78
}
79
}
80
if (bd.option & ENET_BD_IINS) {
81
- struct ip_header *ip_hd = PKT_GET_IP_HDR(frame);
82
+ struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
83
/* We compute checksum only for IPv4 frames */
84
if (IP_HEADER_VERSION(ip_hd) == 4) {
85
uint16_t csum;
86
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s)
87
}
88
}
89
/* Last buffer in frame. */
90
- qemu_send_packet(qemu_get_queue(s->nic), frame, len);
91
- ptr = frame;
92
+
93
+ qemu_send_packet(qemu_get_queue(s->nic), s->frame, len);
94
+ ptr = s->frame;
95
+
96
frame_size = 0;
97
if (bd.option & ENET_BD_TX_INT) {
98
s->regs[ENET_EIR] |= ENET_INT_TXF;
99
--
58
--
100
2.7.4
59
2.20.1
101
60
102
61
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
Refactor imx_eth_enable_rx() to have more meaningfull variable name
3
Improve the naming of the different controller models to ease their
4
than 'tmp' and to reduce number of logical negations done.
4
generation when initializing the SoC. The rename of the SMC types is
5
breaking migration compatibility.
5
6
6
Cc: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
7
Cc: Jason Wang <jasowang@redhat.com>
8
Message-id: 20190904070506.1052-5-clg@kaod.org
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Cc: qemu-devel@nongnu.org
10
Cc: qemu-arm@nongnu.org
11
Cc: yurovsky@gmail.com
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
11
---
17
hw/net/imx_fec.c | 8 ++++----
12
include/hw/arm/aspeed_soc.h | 3 ---
18
1 file changed, 4 insertions(+), 4 deletions(-)
13
hw/arm/aspeed_soc.c | 25 ++++++++++++-------------
14
hw/ssi/aspeed_smc.c | 12 ++++++------
15
3 files changed, 18 insertions(+), 22 deletions(-)
19
16
20
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
17
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/net/imx_fec.c
19
--- a/include/hw/arm/aspeed_soc.h
23
+++ b/hw/net/imx_fec.c
20
+++ b/include/hw/arm/aspeed_soc.h
24
@@ -XXX,XX +XXX,XX @@ static void imx_eth_do_tx(IMXFECState *s)
21
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCInfo {
25
static void imx_eth_enable_rx(IMXFECState *s)
22
uint32_t silicon_rev;
26
{
23
uint64_t sram_size;
27
IMXFECBufDesc bd;
24
int spis_num;
28
- bool tmp;
25
- const char *fmc_typename;
29
+ bool rx_ring_full;
26
- const char **spi_typename;
30
27
- const char *gpio_typename;
31
imx_fec_read_bd(&bd, s->rx_descriptor);
28
int wdts_num;
32
29
const int *irqmap;
33
- tmp = ((bd.flags & ENET_BD_E) != 0);
30
const hwaddr *memmap;
34
+ rx_ring_full = !(bd.flags & ENET_BD_E);
31
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
35
32
index XXXXXXX..XXXXXXX 100644
36
- if (!tmp) {
33
--- a/hw/arm/aspeed_soc.c
37
+ if (rx_ring_full) {
34
+++ b/hw/arm/aspeed_soc.c
38
FEC_PRINTF("RX buffer full\n");
35
@@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2400_irqmap[] = {
39
} else if (!s->regs[ENET_RDAR]) {
36
40
qemu_flush_queued_packets(qemu_get_queue(s->nic));
37
#define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap
38
39
-static const char *aspeed_soc_ast2400_typenames[] = { "aspeed.smc.spi" };
40
-static const char *aspeed_soc_ast2500_typenames[] = {
41
- "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
42
-
43
static const AspeedSoCInfo aspeed_socs[] = {
44
{
45
.name = "ast2400-a1",
46
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
47
.silicon_rev = AST2400_A1_SILICON_REV,
48
.sram_size = 0x8000,
49
.spis_num = 1,
50
- .fmc_typename = "aspeed.smc.fmc",
51
- .spi_typename = aspeed_soc_ast2400_typenames,
52
- .gpio_typename = "aspeed.gpio-ast2400",
53
.wdts_num = 2,
54
.irqmap = aspeed_soc_ast2400_irqmap,
55
.memmap = aspeed_soc_ast2400_memmap,
56
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
57
.silicon_rev = AST2500_A1_SILICON_REV,
58
.sram_size = 0x9000,
59
.spis_num = 2,
60
- .fmc_typename = "aspeed.smc.ast2500-fmc",
61
- .spi_typename = aspeed_soc_ast2500_typenames,
62
- .gpio_typename = "aspeed.gpio-ast2500",
63
.wdts_num = 3,
64
.irqmap = aspeed_soc_ast2500_irqmap,
65
.memmap = aspeed_soc_ast2500_memmap,
66
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
67
AspeedSoCState *s = ASPEED_SOC(obj);
68
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
69
int i;
70
+ char socname[8];
71
+ char typename[64];
72
+
73
+ if (sscanf(sc->info->name, "%7s", socname) != 1) {
74
+ g_assert_not_reached();
75
+ }
76
77
for (i = 0; i < sc->info->num_cpus; i++) {
78
object_initialize_child(obj, "cpu[*]", OBJECT(&s->cpu[i]),
79
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
80
sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c),
81
TYPE_ASPEED_I2C);
82
83
+ snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
84
sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc),
85
- sc->info->fmc_typename);
86
+ typename);
87
object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
88
&error_abort);
89
90
for (i = 0; i < sc->info->spis_num; i++) {
91
+ snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
92
sysbus_init_child_obj(obj, "spi[*]", OBJECT(&s->spi[i]),
93
- sizeof(s->spi[i]), sc->info->spi_typename[i]);
94
+ sizeof(s->spi[i]), typename);
41
}
95
}
42
96
43
- s->regs[ENET_RDAR] = tmp ? ENET_RDAR_RDAR : 0;
97
sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc),
44
+ s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
98
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
99
sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma),
100
TYPE_ASPEED_XDMA);
101
102
+ snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname);
103
sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio),
104
- sc->info->gpio_typename);
105
+ typename);
45
}
106
}
46
107
47
static void imx_eth_reset(DeviceState *d)
108
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
109
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/hw/ssi/aspeed_smc.c
112
+++ b/hw/ssi/aspeed_smc.c
113
@@ -XXX,XX +XXX,XX @@ static const AspeedSegments aspeed_segments_ast2500_spi2[] = {
114
115
static const AspeedSMCController controllers[] = {
116
{
117
- .name = "aspeed.smc.smc",
118
+ .name = "aspeed.smc-ast2400",
119
.r_conf = R_CONF,
120
.r_ce_ctrl = R_CE_CTRL,
121
.r_ctrl0 = R_CTRL0,
122
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
123
.has_dma = false,
124
.nregs = ASPEED_SMC_R_SMC_MAX,
125
}, {
126
- .name = "aspeed.smc.fmc",
127
+ .name = "aspeed.fmc-ast2400",
128
.r_conf = R_CONF,
129
.r_ce_ctrl = R_CE_CTRL,
130
.r_ctrl0 = R_CTRL0,
131
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
132
.has_dma = true,
133
.nregs = ASPEED_SMC_R_MAX,
134
}, {
135
- .name = "aspeed.smc.spi",
136
+ .name = "aspeed.spi1-ast2400",
137
.r_conf = R_SPI_CONF,
138
.r_ce_ctrl = 0xff,
139
.r_ctrl0 = R_SPI_CTRL0,
140
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
141
.has_dma = false,
142
.nregs = ASPEED_SMC_R_SPI_MAX,
143
}, {
144
- .name = "aspeed.smc.ast2500-fmc",
145
+ .name = "aspeed.fmc-ast2500",
146
.r_conf = R_CONF,
147
.r_ce_ctrl = R_CE_CTRL,
148
.r_ctrl0 = R_CTRL0,
149
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
150
.has_dma = true,
151
.nregs = ASPEED_SMC_R_MAX,
152
}, {
153
- .name = "aspeed.smc.ast2500-spi1",
154
+ .name = "aspeed.spi1-ast2500",
155
.r_conf = R_CONF,
156
.r_ce_ctrl = R_CE_CTRL,
157
.r_ctrl0 = R_CTRL0,
158
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
159
.has_dma = false,
160
.nregs = ASPEED_SMC_R_MAX,
161
}, {
162
- .name = "aspeed.smc.ast2500-spi2",
163
+ .name = "aspeed.spi2-ast2500",
164
.r_conf = R_CONF,
165
.r_ce_ctrl = R_CE_CTRL,
166
.r_ctrl0 = R_CTRL0,
48
--
167
--
49
2.7.4
168
2.20.1
50
169
51
170
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
More recent version of the IP block support more than one Tx DMA ring,
3
The FMC controller on the Aspeed SoCs support DMA to access the flash
4
so add the code implementing that feature.
4
modules. It can operate in a normal mode, to copy to or from the flash
5
5
module mapping window, or in a checksum calculation mode, to evaluate
6
Cc: Peter Maydell <peter.maydell@linaro.org>
6
the best clock settings for reads.
7
Cc: Jason Wang <jasowang@redhat.com>
7
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
The model introduces two custom address spaces for DMAs: one for the
9
Cc: qemu-devel@nongnu.org
9
AHB window of the FMC flash devices and one for the DRAM. The latter
10
Cc: qemu-arm@nongnu.org
10
is populated using a "dram" link set from the machine with the RAM
11
Cc: yurovsky@gmail.com
11
container region.
12
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Acked-by: Joel Stanley <joel@jms.id.au>
15
Message-id: 20190904070506.1052-6-clg@kaod.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
18
---
16
include/hw/net/imx_fec.h | 18 ++++++-
19
include/hw/ssi/aspeed_smc.h | 6 +
17
hw/net/imx_fec.c | 133 ++++++++++++++++++++++++++++++++++++++++-------
20
hw/arm/aspeed.c | 2 +
18
2 files changed, 130 insertions(+), 21 deletions(-)
21
hw/arm/aspeed_soc.c | 2 +
19
22
hw/ssi/aspeed_smc.c | 222 +++++++++++++++++++++++++++++++++++-
20
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
23
4 files changed, 226 insertions(+), 6 deletions(-)
24
25
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
21
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/net/imx_fec.h
27
--- a/include/hw/ssi/aspeed_smc.h
23
+++ b/include/hw/net/imx_fec.h
28
+++ b/include/hw/ssi/aspeed_smc.h
29
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCController {
30
hwaddr flash_window_base;
31
uint32_t flash_window_size;
32
bool has_dma;
33
+ hwaddr dma_flash_mask;
34
+ hwaddr dma_dram_mask;
35
uint32_t nregs;
36
} AspeedSMCController;
37
38
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCState {
39
/* for DMA support */
40
uint64_t sdram_base;
41
42
+ AddressSpace flash_as;
43
+ MemoryRegion *dram_mr;
44
+ AddressSpace dram_as;
45
+
46
AspeedSMCFlash *flashes;
47
48
uint8_t snoop_index;
49
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/aspeed.c
52
+++ b/hw/arm/aspeed.c
53
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
54
&error_abort);
55
object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus",
56
&error_abort);
57
+ object_property_set_link(OBJECT(&bmc->soc), OBJECT(&bmc->ram_container),
58
+ "dram", &error_abort);
59
if (machine->kernel_filename) {
60
/*
61
* When booting with a -kernel command line there is no u-boot
62
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/hw/arm/aspeed_soc.c
65
+++ b/hw/arm/aspeed_soc.c
66
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
67
typename);
68
object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
69
&error_abort);
70
+ object_property_add_alias(obj, "dram", OBJECT(&s->fmc), "dram",
71
+ &error_abort);
72
73
for (i = 0; i < sc->info->spis_num; i++) {
74
snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
75
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/ssi/aspeed_smc.c
78
+++ b/hw/ssi/aspeed_smc.c
24
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
25
#define ENET_TFWR 81
80
#include "qemu/log.h"
26
#define ENET_FRBR 83
81
#include "qemu/module.h"
27
#define ENET_FRSR 84
82
#include "qemu/error-report.h"
28
+#define ENET_TDSR1 89
83
+#include "qapi/error.h"
29
+#define ENET_TDSR2 92
84
+#include "exec/address-spaces.h"
30
#define ENET_RDSR 96
85
31
#define ENET_TDSR 97
86
#include "hw/irq.h"
32
#define ENET_MRBR 98
87
#include "hw/qdev-properties.h"
33
@@ -XXX,XX +XXX,XX @@
88
@@ -XXX,XX +XXX,XX @@
34
#define ENET_FTRL 108
89
#define DMA_CTRL_FREQ_SHIFT 4
35
#define ENET_TACC 112
90
#define DMA_CTRL_MODE (1 << 3)
36
#define ENET_RACC 113
91
#define DMA_CTRL_CKSUM (1 << 2)
37
+#define ENET_TDAR1 121
92
-#define DMA_CTRL_DIR (1 << 1)
38
+#define ENET_TDAR2 123
93
-#define DMA_CTRL_EN (1 << 0)
39
#define ENET_MIIGSK_CFGR 192
94
+#define DMA_CTRL_WRITE (1 << 1)
40
#define ENET_MIIGSK_ENR 194
95
+#define DMA_CTRL_ENABLE (1 << 0)
41
#define ENET_ATCR 256
96
97
/* DMA Flash Side Address */
98
#define R_DMA_FLASH_ADDR (0x84 / 4)
42
@@ -XXX,XX +XXX,XX @@
99
@@ -XXX,XX +XXX,XX @@
43
#define ENET_INT_WAKEUP (1 << 17)
100
#define ASPEED_SOC_SPI_FLASH_BASE 0x30000000
44
#define ENET_INT_TS_AVAIL (1 << 16)
101
#define ASPEED_SOC_SPI2_FLASH_BASE 0x38000000
45
#define ENET_INT_TS_TIMER (1 << 15)
102
46
+#define ENET_INT_TXF2 (1 << 7)
103
+/*
47
+#define ENET_INT_TXB2 (1 << 6)
104
+ * DMA DRAM addresses should be 4 bytes aligned and the valid address
48
+#define ENET_INT_TXF1 (1 << 3)
105
+ * range is 0x40000000 - 0x5FFFFFFF (AST2400)
49
+#define ENET_INT_TXB1 (1 << 2)
106
+ * 0x80000000 - 0xBFFFFFFF (AST2500)
50
107
+ *
51
#define ENET_INT_MAC (ENET_INT_HB | ENET_INT_BABR | ENET_INT_BABT | \
108
+ * DMA flash addresses should be 4 bytes aligned and the valid address
52
ENET_INT_GRA | ENET_INT_TXF | ENET_INT_TXB | \
109
+ * range is 0x20000000 - 0x2FFFFFFF.
53
ENET_INT_RXF | ENET_INT_RXB | ENET_INT_MII | \
110
+ *
54
ENET_INT_EBERR | ENET_INT_LC | ENET_INT_RL | \
111
+ * DMA length is from 4 bytes to 32MB
55
ENET_INT_UN | ENET_INT_PLR | ENET_INT_WAKEUP | \
112
+ * 0: 4 bytes
56
- ENET_INT_TS_AVAIL)
113
+ * 0x7FFFFF: 32M bytes
57
+ ENET_INT_TS_AVAIL | ENET_INT_TXF1 | \
114
+ */
58
+ ENET_INT_TXB1 | ENET_INT_TXF2 | ENET_INT_TXB2)
115
+#define DMA_DRAM_ADDR(s, val) ((s)->sdram_base | \
59
116
+ ((val) & (s)->ctrl->dma_dram_mask))
60
/* RDAR */
117
+#define DMA_FLASH_ADDR(s, val) ((s)->ctrl->flash_window_base | \
61
#define ENET_RDAR_RDAR (1 << 24)
118
+ ((val) & (s)->ctrl->dma_flash_mask))
62
@@ -XXX,XX +XXX,XX @@ typedef struct {
119
+#define DMA_LENGTH(val) ((val) & 0x01FFFFFC)
63
120
+
64
#define ENET_BD_BDU (1 << 31)
121
/* Flash opcodes. */
65
122
#define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
66
+#define ENET_TX_RING_NUM 3
123
67
+
124
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
68
+
125
.flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
69
typedef struct IMXFECState {
126
.flash_window_size = 0x10000000,
70
/*< private >*/
127
.has_dma = true,
71
SysBusDevice parent_obj;
128
+ .dma_flash_mask = 0x0FFFFFFC,
72
@@ -XXX,XX +XXX,XX @@ typedef struct IMXFECState {
129
+ .dma_dram_mask = 0x1FFFFFFC,
73
130
.nregs = ASPEED_SMC_R_MAX,
74
uint32_t regs[ENET_MAX];
131
}, {
75
uint32_t rx_descriptor;
132
.name = "aspeed.spi1-ast2400",
76
- uint32_t tx_descriptor;
133
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
77
+
134
.flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
78
+ uint32_t tx_descriptor[ENET_TX_RING_NUM];
135
.flash_window_size = 0x10000000,
79
+ uint32_t tx_ring_num;
136
.has_dma = true,
80
137
+ .dma_flash_mask = 0x0FFFFFFC,
81
uint32_t phy_status;
138
+ .dma_dram_mask = 0x3FFFFFFC,
82
uint32_t phy_control;
139
.nregs = ASPEED_SMC_R_MAX,
83
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
140
}, {
84
index XXXXXXX..XXXXXXX 100644
141
.name = "aspeed.spi1-ast2500",
85
--- a/hw/net/imx_fec.c
142
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_reset(DeviceState *d)
86
+++ b/hw/net/imx_fec.c
143
87
@@ -XXX,XX +XXX,XX @@ static const char *imx_eth_reg_name(IMXFECState *s, uint32_t index)
144
memset(s->regs, 0, sizeof s->regs);
145
146
- /* Pretend DMA is done (u-boot initialization) */
147
- s->regs[R_INTR_CTRL] = INTR_CTRL_DMA_STATUS;
148
-
149
/* Unselect all slaves */
150
for (i = 0; i < s->num_cs; ++i) {
151
s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
152
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
153
addr == s->r_ce_ctrl ||
154
addr == R_INTR_CTRL ||
155
addr == R_DUMMY_DATA ||
156
+ (s->ctrl->has_dma && addr == R_DMA_CTRL) ||
157
+ (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) ||
158
+ (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) ||
159
+ (s->ctrl->has_dma && addr == R_DMA_LEN) ||
160
+ (s->ctrl->has_dma && addr == R_DMA_CHECKSUM) ||
161
(addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) ||
162
(addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_slaves)) {
163
return s->regs[addr];
164
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
88
}
165
}
89
}
166
}
90
167
91
+/*
168
+/*
92
+ * Versions of this device with more than one TX descriptor save the
169
+ * Accumulate the result of the reads to provide a checksum that will
93
+ * 2nd and 3rd descriptors in a subsection, to maintain migration
170
+ * be used to validate the read timing settings.
94
+ * compatibility with previous versions of the device that only
95
+ * supported a single descriptor.
96
+ */
171
+ */
97
+static bool imx_eth_is_multi_tx_ring(void *opaque)
172
+static void aspeed_smc_dma_checksum(AspeedSMCState *s)
98
+{
173
+{
99
+ IMXFECState *s = IMX_FEC(opaque);
174
+ MemTxResult result;
100
+
175
+ uint32_t data;
101
+ return s->tx_ring_num > 1;
176
+
102
+}
177
+ if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
103
+
104
+static const VMStateDescription vmstate_imx_eth_txdescs = {
105
+ .name = "imx.fec/txdescs",
106
+ .version_id = 1,
107
+ .minimum_version_id = 1,
108
+ .needed = imx_eth_is_multi_tx_ring,
109
+ .fields = (VMStateField[]) {
110
+ VMSTATE_UINT32(tx_descriptor[1], IMXFECState),
111
+ VMSTATE_UINT32(tx_descriptor[2], IMXFECState),
112
+ VMSTATE_END_OF_LIST()
113
+ }
114
+};
115
+
116
static const VMStateDescription vmstate_imx_eth = {
117
.name = TYPE_IMX_FEC,
118
.version_id = 2,
119
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth = {
120
.fields = (VMStateField[]) {
121
VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
122
VMSTATE_UINT32(rx_descriptor, IMXFECState),
123
- VMSTATE_UINT32(tx_descriptor, IMXFECState),
124
-
125
+ VMSTATE_UINT32(tx_descriptor[0], IMXFECState),
126
VMSTATE_UINT32(phy_status, IMXFECState),
127
VMSTATE_UINT32(phy_control, IMXFECState),
128
VMSTATE_UINT32(phy_advertise, IMXFECState),
129
VMSTATE_UINT32(phy_int, IMXFECState),
130
VMSTATE_UINT32(phy_int_mask, IMXFECState),
131
VMSTATE_END_OF_LIST()
132
- }
133
+ },
134
+ .subsections = (const VMStateDescription * []) {
135
+ &vmstate_imx_eth_txdescs,
136
+ NULL
137
+ },
138
};
139
140
#define PHY_INT_ENERGYON (1 << 7)
141
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
142
{
143
int frame_size = 0, descnt = 0;
144
uint8_t *ptr = s->frame;
145
- uint32_t addr = s->tx_descriptor;
146
+ uint32_t addr = s->tx_descriptor[0];
147
148
while (descnt++ < IMX_MAX_DESC) {
149
IMXFECBufDesc bd;
150
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
151
}
152
}
153
154
- s->tx_descriptor = addr;
155
+ s->tx_descriptor[0] = addr;
156
157
imx_eth_update(s);
158
}
159
160
-static void imx_enet_do_tx(IMXFECState *s)
161
+static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
162
{
163
int frame_size = 0, descnt = 0;
164
+
165
uint8_t *ptr = s->frame;
166
- uint32_t addr = s->tx_descriptor;
167
+ uint32_t addr, int_txb, int_txf, tdsr;
168
+ size_t ring;
169
+
170
+ switch (index) {
171
+ case ENET_TDAR:
172
+ ring = 0;
173
+ int_txb = ENET_INT_TXB;
174
+ int_txf = ENET_INT_TXF;
175
+ tdsr = ENET_TDSR;
176
+ break;
177
+ case ENET_TDAR1:
178
+ ring = 1;
179
+ int_txb = ENET_INT_TXB1;
180
+ int_txf = ENET_INT_TXF1;
181
+ tdsr = ENET_TDSR1;
182
+ break;
183
+ case ENET_TDAR2:
184
+ ring = 2;
185
+ int_txb = ENET_INT_TXB2;
186
+ int_txf = ENET_INT_TXF2;
187
+ tdsr = ENET_TDSR2;
188
+ break;
189
+ default:
190
+ qemu_log_mask(LOG_GUEST_ERROR,
178
+ qemu_log_mask(LOG_GUEST_ERROR,
191
+ "%s: bogus value for index %x\n",
179
+ "%s: invalid direction for DMA checksum\n", __func__);
192
+ __func__, index);
180
+ return;
193
+ abort();
181
+ }
194
+ break;
182
+
195
+ }
183
+ while (s->regs[R_DMA_LEN]) {
196
+
184
+ data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
197
+ addr = s->tx_descriptor[ring];
185
+ MEMTXATTRS_UNSPECIFIED, &result);
198
186
+ if (result != MEMTX_OK) {
199
while (descnt++ < IMX_MAX_DESC) {
187
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash read failed @%08x\n",
200
IMXENETBufDesc bd;
188
+ __func__, s->regs[R_DMA_FLASH_ADDR]);
201
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s)
202
203
frame_size = 0;
204
if (bd.option & ENET_BD_TX_INT) {
205
- s->regs[ENET_EIR] |= ENET_INT_TXF;
206
+ s->regs[ENET_EIR] |= int_txf;
207
}
208
}
209
if (bd.option & ENET_BD_TX_INT) {
210
- s->regs[ENET_EIR] |= ENET_INT_TXB;
211
+ s->regs[ENET_EIR] |= int_txb;
212
}
213
bd.flags &= ~ENET_BD_R;
214
/* Write back the modified descriptor. */
215
imx_enet_write_bd(&bd, addr);
216
/* Advance to the next descriptor. */
217
if ((bd.flags & ENET_BD_W) != 0) {
218
- addr = s->regs[ENET_TDSR];
219
+ addr = s->regs[tdsr];
220
} else {
221
addr += sizeof(bd);
222
}
223
}
224
225
- s->tx_descriptor = addr;
226
+ s->tx_descriptor[ring] = addr;
227
228
imx_eth_update(s);
229
}
230
231
-static void imx_eth_do_tx(IMXFECState *s)
232
+static void imx_eth_do_tx(IMXFECState *s, uint32_t index)
233
{
234
if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) {
235
- imx_enet_do_tx(s);
236
+ imx_enet_do_tx(s, index);
237
} else {
238
imx_fec_do_tx(s);
239
}
240
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
241
}
242
243
s->rx_descriptor = 0;
244
- s->tx_descriptor = 0;
245
+ memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
246
247
/* We also reset the PHY */
248
phy_reset(s);
249
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
250
unsigned size)
251
{
252
IMXFECState *s = IMX_FEC(opaque);
253
+ const bool single_tx_ring = !imx_eth_is_multi_tx_ring(s);
254
uint32_t index = offset >> 2;
255
256
FEC_PRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
257
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
258
s->regs[index] = 0;
259
}
260
break;
261
- case ENET_TDAR:
262
+ case ENET_TDAR1: /* FALLTHROUGH */
263
+ case ENET_TDAR2: /* FALLTHROUGH */
264
+ if (unlikely(single_tx_ring)) {
265
+ qemu_log_mask(LOG_GUEST_ERROR,
266
+ "[%s]%s: trying to access TDAR2 or TDAR1\n",
267
+ TYPE_IMX_FEC, __func__);
268
+ return;
189
+ return;
269
+ }
190
+ }
270
+ case ENET_TDAR: /* FALLTHROUGH */
191
+
271
if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
192
+ /*
272
s->regs[index] = ENET_TDAR_TDAR;
193
+ * When the DMA is on-going, the DMA registers are updated
273
- imx_eth_do_tx(s);
194
+ * with the current working addresses and length.
274
+ imx_eth_do_tx(s, index);
195
+ */
196
+ s->regs[R_DMA_CHECKSUM] += data;
197
+ s->regs[R_DMA_FLASH_ADDR] += 4;
198
+ s->regs[R_DMA_LEN] -= 4;
199
+ }
200
+}
201
+
202
+static void aspeed_smc_dma_rw(AspeedSMCState *s)
203
+{
204
+ MemTxResult result;
205
+ uint32_t data;
206
+
207
+ while (s->regs[R_DMA_LEN]) {
208
+ if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
209
+ data = address_space_ldl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
210
+ MEMTXATTRS_UNSPECIFIED, &result);
211
+ if (result != MEMTX_OK) {
212
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM read failed @%08x\n",
213
+ __func__, s->regs[R_DMA_DRAM_ADDR]);
214
+ return;
215
+ }
216
+
217
+ address_space_stl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
218
+ data, MEMTXATTRS_UNSPECIFIED, &result);
219
+ if (result != MEMTX_OK) {
220
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash write failed @%08x\n",
221
+ __func__, s->regs[R_DMA_FLASH_ADDR]);
222
+ return;
223
+ }
224
+ } else {
225
+ data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
226
+ MEMTXATTRS_UNSPECIFIED, &result);
227
+ if (result != MEMTX_OK) {
228
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash read failed @%08x\n",
229
+ __func__, s->regs[R_DMA_FLASH_ADDR]);
230
+ return;
231
+ }
232
+
233
+ address_space_stl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
234
+ data, MEMTXATTRS_UNSPECIFIED, &result);
235
+ if (result != MEMTX_OK) {
236
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM write failed @%08x\n",
237
+ __func__, s->regs[R_DMA_DRAM_ADDR]);
238
+ return;
239
+ }
240
+ }
241
+
242
+ /*
243
+ * When the DMA is on-going, the DMA registers are updated
244
+ * with the current working addresses and length.
245
+ */
246
+ s->regs[R_DMA_FLASH_ADDR] += 4;
247
+ s->regs[R_DMA_DRAM_ADDR] += 4;
248
+ s->regs[R_DMA_LEN] -= 4;
249
+ }
250
+}
251
+
252
+static void aspeed_smc_dma_stop(AspeedSMCState *s)
253
+{
254
+ /*
255
+ * When the DMA is disabled, INTR_CTRL_DMA_STATUS=0 means the
256
+ * engine is idle
257
+ */
258
+ s->regs[R_INTR_CTRL] &= ~INTR_CTRL_DMA_STATUS;
259
+ s->regs[R_DMA_CHECKSUM] = 0;
260
+
261
+ /*
262
+ * Lower the DMA irq in any case. The IRQ control register could
263
+ * have been cleared before disabling the DMA.
264
+ */
265
+ qemu_irq_lower(s->irq);
266
+}
267
+
268
+/*
269
+ * When INTR_CTRL_DMA_STATUS=1, the DMA has completed and a new DMA
270
+ * can start even if the result of the previous was not collected.
271
+ */
272
+static bool aspeed_smc_dma_in_progress(AspeedSMCState *s)
273
+{
274
+ return s->regs[R_DMA_CTRL] & DMA_CTRL_ENABLE &&
275
+ !(s->regs[R_INTR_CTRL] & INTR_CTRL_DMA_STATUS);
276
+}
277
+
278
+static void aspeed_smc_dma_done(AspeedSMCState *s)
279
+{
280
+ s->regs[R_INTR_CTRL] |= INTR_CTRL_DMA_STATUS;
281
+ if (s->regs[R_INTR_CTRL] & INTR_CTRL_DMA_EN) {
282
+ qemu_irq_raise(s->irq);
283
+ }
284
+}
285
+
286
+static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint64_t dma_ctrl)
287
+{
288
+ if (!(dma_ctrl & DMA_CTRL_ENABLE)) {
289
+ s->regs[R_DMA_CTRL] = dma_ctrl;
290
+
291
+ aspeed_smc_dma_stop(s);
292
+ return;
293
+ }
294
+
295
+ if (aspeed_smc_dma_in_progress(s)) {
296
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA in progress\n", __func__);
297
+ return;
298
+ }
299
+
300
+ s->regs[R_DMA_CTRL] = dma_ctrl;
301
+
302
+ if (s->regs[R_DMA_CTRL] & DMA_CTRL_CKSUM) {
303
+ aspeed_smc_dma_checksum(s);
304
+ } else {
305
+ aspeed_smc_dma_rw(s);
306
+ }
307
+
308
+ aspeed_smc_dma_done(s);
309
+}
310
+
311
static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
312
unsigned int size)
313
{
314
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
275
}
315
}
276
s->regs[index] = 0;
316
} else if (addr == R_DUMMY_DATA) {
277
break;
317
s->regs[addr] = value & 0xff;
278
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
318
+ } else if (addr == R_INTR_CTRL) {
279
if ((s->regs[index] & ENET_ECR_ETHEREN) == 0) {
319
+ s->regs[addr] = value;
280
s->regs[ENET_RDAR] = 0;
320
+ } else if (s->ctrl->has_dma && addr == R_DMA_CTRL) {
281
s->rx_descriptor = s->regs[ENET_RDSR];
321
+ aspeed_smc_dma_ctrl(s, value);
282
- s->regs[ENET_TDAR] = 0;
322
+ } else if (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) {
283
- s->tx_descriptor = s->regs[ENET_TDSR];
323
+ s->regs[addr] = DMA_DRAM_ADDR(s, value);
284
+ s->regs[ENET_TDAR] = 0;
324
+ } else if (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) {
285
+ s->regs[ENET_TDAR1] = 0;
325
+ s->regs[addr] = DMA_FLASH_ADDR(s, value);
286
+ s->regs[ENET_TDAR2] = 0;
326
+ } else if (s->ctrl->has_dma && addr == R_DMA_LEN) {
287
+ s->tx_descriptor[0] = s->regs[ENET_TDSR];
327
+ s->regs[addr] = DMA_LENGTH(value);
288
+ s->tx_descriptor[1] = s->regs[ENET_TDSR1];
328
} else {
289
+ s->tx_descriptor[2] = s->regs[ENET_TDSR2];
329
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
290
}
330
__func__, addr);
291
break;
331
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_smc_ops = {
292
case ENET_MMFR:
332
.valid.unaligned = true,
293
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
333
};
294
} else {
334
295
s->regs[index] = value & ~7;
335
+
296
}
336
+/*
297
- s->tx_descriptor = s->regs[index];
337
+ * Initialize the custom address spaces for DMAs
298
+ s->tx_descriptor[0] = s->regs[index];
338
+ */
299
+ break;
339
+static void aspeed_smc_dma_setup(AspeedSMCState *s, Error **errp)
300
+ case ENET_TDSR1:
340
+{
301
+ if (unlikely(single_tx_ring)) {
341
+ char *name;
302
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+
303
+ "[%s]%s: trying to access TDSR1\n",
343
+ if (!s->dram_mr) {
304
+ TYPE_IMX_FEC, __func__);
344
+ error_setg(errp, TYPE_ASPEED_SMC ": 'dram' link not set");
305
+ return;
345
+ return;
306
+ }
346
+ }
307
+
347
+
308
+ s->regs[index] = value & ~7;
348
+ name = g_strdup_printf("%s-dma-flash", s->ctrl->name);
309
+ s->tx_descriptor[1] = s->regs[index];
349
+ address_space_init(&s->flash_as, &s->mmio_flash, name);
310
+ break;
350
+ g_free(name);
311
+ case ENET_TDSR2:
351
+
312
+ if (unlikely(single_tx_ring)) {
352
+ name = g_strdup_printf("%s-dma-dram", s->ctrl->name);
313
+ qemu_log_mask(LOG_GUEST_ERROR,
353
+ address_space_init(&s->dram_as, s->dram_mr, name);
314
+ "[%s]%s: trying to access TDSR2\n",
354
+ g_free(name);
315
+ TYPE_IMX_FEC, __func__);
355
+}
316
+ return;
356
+
317
+ }
357
static void aspeed_smc_realize(DeviceState *dev, Error **errp)
318
+
358
{
319
+ s->regs[index] = value & ~7;
359
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
320
+ s->tx_descriptor[2] = s->regs[index];
360
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
321
break;
361
s->num_cs = s->ctrl->max_slaves;
322
case ENET_MRBR:
362
}
323
s->regs[index] = value & 0x00003ff0;
363
324
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
364
+ /* DMA irq. Keep it first for the initialization in the SoC */
325
365
+ sysbus_init_irq(sbd, &s->irq);
326
static Property imx_eth_properties[] = {
366
+
327
DEFINE_NIC_PROPERTIES(IMXFECState, conf),
367
s->spi = ssi_create_bus(dev, "spi");
328
+ DEFINE_PROP_UINT32("tx-ring-num", IMXFECState, tx_ring_num, 1),
368
369
/* Setup cs_lines for slaves */
370
- sysbus_init_irq(sbd, &s->irq);
371
s->cs_lines = g_new0(qemu_irq, s->num_cs);
372
ssi_auto_connect_slaves(dev, s->cs_lines, s->spi);
373
374
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
375
memory_region_add_subregion(&s->mmio_flash, offset, &fl->mmio);
376
offset += fl->size;
377
}
378
+
379
+ /* DMA support */
380
+ if (s->ctrl->has_dma) {
381
+ aspeed_smc_dma_setup(s, errp);
382
+ }
383
}
384
385
static const VMStateDescription vmstate_aspeed_smc = {
386
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_smc = {
387
static Property aspeed_smc_properties[] = {
388
DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1),
389
DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0),
390
+ DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr,
391
+ TYPE_MEMORY_REGION, MemoryRegion *),
329
DEFINE_PROP_END_OF_LIST(),
392
DEFINE_PROP_END_OF_LIST(),
330
};
393
};
331
394
332
--
395
--
333
2.7.4
396
2.20.1
334
397
335
398
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
In current implementation, packet queue flushing logic seem to suffer
3
When doing calibration, the SPI clock rate in the CE0 Control Register
4
from a deadlock like scenario if a packet is received by the interface
4
and the read delay cycles in the Read Timing Compensation Register are
5
before before Rx ring is initialized by Guest's driver. Consider the
5
set using bit[11:4] of the DMA Control Register.
6
following sequence of events:
7
6
8
    1. A QEMU instance is started against a TAP device on Linux
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
     host, running Linux guest, e. g., something to the effect
8
Acked-by: Joel Stanley <joel@jms.id.au>
10
     of:
11
12
     qemu-system-arm \
13
     -net nic,model=imx.fec,netdev=lan0 \
14
     netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
15
     ... rest of the arguments ...
16
17
    2. Once QEMU starts, but before guest reaches the point where
18
     FEC deriver is done initializing the HW, Guest, via TAP
19
     interface, receives a number of multicast MDNS packets from
20
     Host (not necessarily true for every OS, but it happens at
21
     least on Fedora 25)
22
23
    3. Recieving a packet in such a state results in
24
     imx_eth_can_receive() returning '0', which in turn causes
25
     tap_send() to disable corresponding event (tap.c:203)
26
27
    4. Once Guest's driver reaches the point where it is ready to
28
     recieve packets it prepares Rx ring descriptors and writes
29
     ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
30
     more descriptors are ready. And at this points emulation
31
     layer does this:
32
33
          s->regs[index] = ENET_RDAR_RDAR;
34
imx_eth_enable_rx(s);
35
36
     which, combined with:
37
38
          if (!s->regs[ENET_RDAR]) {
39
         qemu_flush_queued_packets(qemu_get_queue(s->nic));
40
         }
41
42
     results in Rx queue never being flushed and corresponding
43
     I/O event beign disabled.
44
45
To prevent the problem, change the code to always flush packet queue
46
when ENET_RDAR transitions 0 -> ENET_RDAR_RDAR.
47
48
Cc: Peter Maydell <peter.maydell@linaro.org>
49
Cc: Jason Wang <jasowang@redhat.com>
50
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
51
Cc: qemu-devel@nongnu.org
52
Cc: qemu-arm@nongnu.org
53
Cc: yurovsky@gmail.com
54
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
55
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
10
Message-id: 20190904070506.1052-7-clg@kaod.org
56
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
57
---
12
---
58
hw/net/imx_fec.c | 12 ++++++------
13
hw/ssi/aspeed_smc.c | 64 ++++++++++++++++++++++++++++++++++++++++++++-
59
1 file changed, 6 insertions(+), 6 deletions(-)
14
1 file changed, 63 insertions(+), 1 deletion(-)
60
15
61
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
16
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
62
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/net/imx_fec.c
18
--- a/hw/ssi/aspeed_smc.c
64
+++ b/hw/net/imx_fec.c
19
+++ b/hw/ssi/aspeed_smc.c
65
@@ -XXX,XX +XXX,XX @@ static void imx_eth_do_tx(IMXFECState *s)
20
@@ -XXX,XX +XXX,XX @@
21
#define CTRL_CMD_MASK 0xff
22
#define CTRL_DUMMY_HIGH_SHIFT 14
23
#define CTRL_AST2400_SPI_4BYTE (1 << 13)
24
+#define CE_CTRL_CLOCK_FREQ_SHIFT 8
25
+#define CE_CTRL_CLOCK_FREQ_MASK 0xf
26
+#define CE_CTRL_CLOCK_FREQ(div) \
27
+ (((div) & CE_CTRL_CLOCK_FREQ_MASK) << CE_CTRL_CLOCK_FREQ_SHIFT)
28
#define CTRL_DUMMY_LOW_SHIFT 6 /* 2 bits [7:6] */
29
#define CTRL_CE_STOP_ACTIVE (1 << 2)
30
#define CTRL_CMD_MODE_MASK 0x3
31
@@ -XXX,XX +XXX,XX @@
32
#define DMA_CTRL_DELAY_SHIFT 8
33
#define DMA_CTRL_FREQ_MASK 0xf
34
#define DMA_CTRL_FREQ_SHIFT 4
35
-#define DMA_CTRL_MODE (1 << 3)
36
+#define DMA_CTRL_CALIB (1 << 3)
37
#define DMA_CTRL_CKSUM (1 << 2)
38
#define DMA_CTRL_WRITE (1 << 1)
39
#define DMA_CTRL_ENABLE (1 << 0)
40
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
66
}
41
}
67
}
42
}
68
43
69
-static void imx_eth_enable_rx(IMXFECState *s)
44
+static uint8_t aspeed_smc_hclk_divisor(uint8_t hclk_mask)
70
+static void imx_eth_enable_rx(IMXFECState *s, bool flush)
45
+{
71
{
46
+ /* HCLK/1 .. HCLK/16 */
72
IMXFECBufDesc bd;
47
+ const uint8_t hclk_divisors[] = {
73
bool rx_ring_full;
48
+ 15, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0
74
@@ -XXX,XX +XXX,XX @@ static void imx_eth_enable_rx(IMXFECState *s)
49
+ };
75
50
+ int i;
76
if (rx_ring_full) {
51
+
77
FEC_PRINTF("RX buffer full\n");
52
+ for (i = 0; i < ARRAY_SIZE(hclk_divisors); i++) {
78
- } else if (!s->regs[ENET_RDAR]) {
53
+ if (hclk_mask == hclk_divisors[i]) {
79
+ } else if (flush) {
54
+ return i + 1;
80
qemu_flush_queued_packets(qemu_get_queue(s->nic));
55
+ }
56
+ }
57
+
58
+ qemu_log_mask(LOG_GUEST_ERROR, "invalid HCLK mask %x", hclk_mask);
59
+ return 0;
60
+}
61
+
62
+/*
63
+ * When doing calibration, the SPI clock rate in the CE0 Control
64
+ * Register and the read delay cycles in the Read Timing Compensation
65
+ * Register are set using bit[11:4] of the DMA Control Register.
66
+ */
67
+static void aspeed_smc_dma_calibration(AspeedSMCState *s)
68
+{
69
+ uint8_t delay =
70
+ (s->regs[R_DMA_CTRL] >> DMA_CTRL_DELAY_SHIFT) & DMA_CTRL_DELAY_MASK;
71
+ uint8_t hclk_mask =
72
+ (s->regs[R_DMA_CTRL] >> DMA_CTRL_FREQ_SHIFT) & DMA_CTRL_FREQ_MASK;
73
+ uint8_t hclk_div = aspeed_smc_hclk_divisor(hclk_mask);
74
+ uint32_t hclk_shift = (hclk_div - 1) << 2;
75
+ uint8_t cs;
76
+
77
+ /*
78
+ * The Read Timing Compensation Register values apply to all CS on
79
+ * the SPI bus and only HCLK/1 - HCLK/5 can have tunable delays
80
+ */
81
+ if (hclk_div && hclk_div < 6) {
82
+ s->regs[s->r_timings] &= ~(0xf << hclk_shift);
83
+ s->regs[s->r_timings] |= delay << hclk_shift;
84
+ }
85
+
86
+ /*
87
+ * TODO: compute the CS from the DMA address and the segment
88
+ * registers. This is not really a problem for now because the
89
+ * Timing Register values apply to all CS and software uses CS0 to
90
+ * do calibration.
91
+ */
92
+ cs = 0;
93
+ s->regs[s->r_ctrl0 + cs] &=
94
+ ~(CE_CTRL_CLOCK_FREQ_MASK << CE_CTRL_CLOCK_FREQ_SHIFT);
95
+ s->regs[s->r_ctrl0 + cs] |= CE_CTRL_CLOCK_FREQ(hclk_div);
96
+}
97
+
98
/*
99
* Accumulate the result of the reads to provide a checksum that will
100
* be used to validate the read timing settings.
101
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
102
return;
81
}
103
}
82
104
83
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
105
+ if (s->regs[R_DMA_CTRL] & DMA_CTRL_CALIB) {
84
if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
106
+ aspeed_smc_dma_calibration(s);
85
if (!s->regs[index]) {
107
+ }
86
s->regs[index] = ENET_RDAR_RDAR;
108
+
87
- imx_eth_enable_rx(s);
109
while (s->regs[R_DMA_LEN]) {
88
+ imx_eth_enable_rx(s, true);
110
data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
89
}
111
MEMTXATTRS_UNSPECIFIED, &result);
90
} else {
91
s->regs[index] = 0;
92
@@ -XXX,XX +XXX,XX @@ static int imx_eth_can_receive(NetClientState *nc)
93
94
FEC_PRINTF("\n");
95
96
- return s->regs[ENET_RDAR] ? 1 : 0;
97
+ return !!s->regs[ENET_RDAR];
98
}
99
100
static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
101
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
102
}
103
}
104
s->rx_descriptor = addr;
105
- imx_eth_enable_rx(s);
106
+ imx_eth_enable_rx(s, false);
107
imx_eth_update(s);
108
return len;
109
}
110
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
111
}
112
}
113
s->rx_descriptor = addr;
114
- imx_eth_enable_rx(s);
115
+ imx_eth_enable_rx(s, false);
116
imx_eth_update(s);
117
return len;
118
}
119
--
112
--
120
2.7.4
113
2.20.1
121
114
122
115
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
Needed to support latest Linux kernel driver which relies on that
3
Emulate read errors in the DMA Checksum Register for high frequencies
4
functionality.
4
and optimistic settings of the Read Timing Compensation Register. This
5
will help in tuning the SPI timing calibration algorithm. Errors are
6
only injected when the property "inject_failure" is set to true as
7
suggested by Philippe.
5
8
6
Cc: Peter Maydell <peter.maydell@linaro.org>
9
The values below are those to expect from the first flash device of
7
Cc: Jason Wang <jasowang@redhat.com>
10
the FMC controller of a palmetto-bmc machine.
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
9
Cc: qemu-devel@nongnu.org
12
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Cc: qemu-arm@nongnu.org
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
11
Cc: yurovsky@gmail.com
14
Reviewed-by: Joel Stanley <joel@jms.id.au>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 20190904070506.1052-8-clg@kaod.org
13
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
17
---
16
include/hw/net/imx_fec.h | 2 ++
18
include/hw/ssi/aspeed_smc.h | 1 +
17
hw/net/imx_fec.c | 23 +++++++++++++++++++++++
19
hw/ssi/aspeed_smc.c | 36 ++++++++++++++++++++++++++++++++++++
18
2 files changed, 25 insertions(+)
20
2 files changed, 37 insertions(+)
19
21
20
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
22
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
21
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/net/imx_fec.h
24
--- a/include/hw/ssi/aspeed_smc.h
23
+++ b/include/hw/net/imx_fec.h
25
+++ b/include/hw/ssi/aspeed_smc.h
24
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCState {
25
#define ENET_TWFR_TFWR_LENGTH (6)
27
26
#define ENET_TWFR_STRFWD (1 << 8)
28
uint32_t num_cs;
27
29
qemu_irq *cs_lines;
28
+#define ENET_RACC_SHIFT16 BIT(7)
30
+ bool inject_failure;
31
32
SSIBus *spi;
33
34
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/ssi/aspeed_smc.c
37
+++ b/hw/ssi/aspeed_smc.c
38
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_calibration(AspeedSMCState *s)
39
s->regs[s->r_ctrl0 + cs] |= CE_CTRL_CLOCK_FREQ(hclk_div);
40
}
41
42
+/*
43
+ * Emulate read errors in the DMA Checksum Register for high
44
+ * frequencies and optimistic settings of the Read Timing Compensation
45
+ * Register. This will help in tuning the SPI timing calibration
46
+ * algorithm.
47
+ */
48
+static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
49
+{
50
+ uint8_t delay =
51
+ (s->regs[R_DMA_CTRL] >> DMA_CTRL_DELAY_SHIFT) & DMA_CTRL_DELAY_MASK;
52
+ uint8_t hclk_mask =
53
+ (s->regs[R_DMA_CTRL] >> DMA_CTRL_FREQ_SHIFT) & DMA_CTRL_FREQ_MASK;
29
+
54
+
30
/* Buffer Descriptor. */
55
+ /*
31
typedef struct {
56
+ * Typical values of a palmetto-bmc machine.
32
uint16_t length;
57
+ */
33
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
58
+ switch (aspeed_smc_hclk_divisor(hclk_mask)) {
34
index XXXXXXX..XXXXXXX 100644
59
+ case 4 ... 16:
35
--- a/hw/net/imx_fec.c
60
+ return false;
36
+++ b/hw/net/imx_fec.c
61
+ case 3: /* at least one HCLK cycle delay */
37
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
62
+ return (delay & 0x7) < 1;
38
uint8_t *crc_ptr;
63
+ case 2: /* at least two HCLK cycle delay */
39
unsigned int buf_len;
64
+ return (delay & 0x7) < 2;
40
size_t size = len;
65
+ case 1: /* (> 100MHz) is above the max freq of the controller */
41
+ bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
66
+ return true;
42
67
+ default:
43
FEC_PRINTF("len %d\n", (int)size);
68
+ g_assert_not_reached();
44
69
+ }
45
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
70
+}
46
crc = cpu_to_be32(crc32(~0, buf, size));
71
+
47
crc_ptr = (uint8_t *) &crc;
72
/*
48
73
* Accumulate the result of the reads to provide a checksum that will
49
+ if (shift16) {
74
* be used to validate the read timing settings.
50
+ size += 2;
75
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
76
s->regs[R_DMA_FLASH_ADDR] += 4;
77
s->regs[R_DMA_LEN] -= 4;
78
}
79
+
80
+ if (s->inject_failure && aspeed_smc_inject_read_failure(s)) {
81
+ s->regs[R_DMA_CHECKSUM] = 0xbadc0de;
51
+ }
82
+ }
52
+
83
+
53
/* Huge frames are truncted. */
84
}
54
if (size > s->regs[ENET_FTRL]) {
85
55
size = s->regs[ENET_FTRL];
86
static void aspeed_smc_dma_rw(AspeedSMCState *s)
56
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
87
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_smc = {
57
buf_len += size - 4;
88
58
}
89
static Property aspeed_smc_properties[] = {
59
buf_addr = bd.data;
90
DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1),
60
+
91
+ DEFINE_PROP_BOOL("inject-failure", AspeedSMCState, inject_failure, false),
61
+ if (shift16) {
92
DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0),
62
+ /*
93
DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr,
63
+ * If SHIFT16 bit of ENETx_RACC register is set we need to
94
TYPE_MEMORY_REGION, MemoryRegion *),
64
+ * align the payload to 4-byte boundary.
65
+ */
66
+ const uint8_t zeros[2] = { 0 };
67
+
68
+ dma_memory_write(&address_space_memory, buf_addr,
69
+ zeros, sizeof(zeros));
70
+
71
+ buf_addr += sizeof(zeros);
72
+ buf_len -= sizeof(zeros);
73
+
74
+ /* We only do this once per Ethernet frame */
75
+ shift16 = false;
76
+ }
77
+
78
dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
79
buf += buf_len;
80
if (size < 4) {
81
--
95
--
82
2.7.4
96
2.20.1
83
97
84
98
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Christian Svensson <bluecmd@google.com>
2
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
This patch adds the missing checksum calculation on normal DMA transfer.
4
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
4
According to the datasheet this is how the SMC should behave.
5
Message-id: 20180103224208.30291-2-f4bug@amsat.org
5
6
Verified on AST1250 that the hardware matches the behaviour.
7
8
Signed-off-by: Christian Svensson <bluecmd@google.com>
9
Reviewed-by: Joel Stanley <joel@jms.id.au>
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
11
Message-id: 20190904070506.1052-9-clg@kaod.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
hw/timer/pxa2xx_timer.c | 17 +++++++++++++++--
14
hw/ssi/aspeed_smc.c | 1 +
9
1 file changed, 15 insertions(+), 2 deletions(-)
15
1 file changed, 1 insertion(+)
10
16
11
diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
17
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/timer/pxa2xx_timer.c
19
--- a/hw/ssi/aspeed_smc.c
14
+++ b/hw/timer/pxa2xx_timer.c
20
+++ b/hw/ssi/aspeed_smc.c
15
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
16
#include "sysemu/sysemu.h"
22
s->regs[R_DMA_FLASH_ADDR] += 4;
17
#include "hw/arm/pxa.h"
23
s->regs[R_DMA_DRAM_ADDR] += 4;
18
#include "hw/sysbus.h"
24
s->regs[R_DMA_LEN] -= 4;
19
+#include "qemu/log.h"
25
+ s->regs[R_DMA_CHECKSUM] += data;
20
21
#define OSMR0    0x00
22
#define OSMR1    0x04
23
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset,
24
case OSNR:
25
return s->snapshot;
26
default:
27
+ qemu_log_mask(LOG_UNIMP,
28
+ "%s: unknown register 0x%02" HWADDR_PRIx "\n",
29
+ __func__, offset);
30
+ break;
31
badreg:
32
- hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
33
+ qemu_log_mask(LOG_GUEST_ERROR,
34
+ "%s: incorrect register 0x%02" HWADDR_PRIx "\n",
35
+ __func__, offset);
36
}
37
38
return 0;
39
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset,
40
}
41
break;
42
default:
43
+ qemu_log_mask(LOG_UNIMP,
44
+ "%s: unknown register 0x%02" HWADDR_PRIx " "
45
+ "(value 0x%08" PRIx64 ")\n", __func__, offset, value);
46
+ break;
47
badreg:
48
- hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
49
+ qemu_log_mask(LOG_GUEST_ERROR,
50
+ "%s: incorrect register 0x%02" HWADDR_PRIx " "
51
+ "(value 0x%08" PRIx64 ")\n", __func__, offset, value);
52
}
26
}
53
}
27
}
54
28
55
--
29
--
56
2.7.4
30
2.20.1
57
31
58
32
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
Frame truncation length, TRUNC_FL, is determined by the contents of
3
and use a class AspeedSCUClass to define each SoC characteristics.
4
ENET_FTRL register, so convert the code to use it instead of a
4
5
hardcoded constant.
5
Signed-off-by: Cédric Le Goater <clg@kaod.org>
6
6
Message-id: 20190904070506.1052-10-clg@kaod.org
7
To avoid the case where TRUNC_FL is greater that ENET_MAX_FRAME_SIZE,
8
increase the value of the latter to its theoretical maximum of 16K.
9
10
Cc: Peter Maydell <peter.maydell@linaro.org>
11
Cc: Jason Wang <jasowang@redhat.com>
12
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Cc: qemu-devel@nongnu.org
14
Cc: qemu-arm@nongnu.org
15
Cc: yurovsky@gmail.com
16
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
9
---
20
include/hw/net/imx_fec.h | 3 ++-
10
include/hw/misc/aspeed_scu.h | 15 +++++++
21
hw/net/imx_fec.c | 4 ++--
11
hw/arm/aspeed_soc.c | 3 +-
22
2 files changed, 4 insertions(+), 3 deletions(-)
12
hw/misc/aspeed_scu.c | 83 ++++++++++++++++++++----------------
23
13
3 files changed, 64 insertions(+), 37 deletions(-)
24
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
14
15
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/net/imx_fec.h
17
--- a/include/hw/misc/aspeed_scu.h
27
+++ b/include/hw/net/imx_fec.h
18
+++ b/include/hw/misc/aspeed_scu.h
28
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
29
#define ENET_TCCR3 393
20
30
#define ENET_MAX 400
21
#define TYPE_ASPEED_SCU "aspeed.scu"
31
22
#define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU)
32
-#define ENET_MAX_FRAME_SIZE 2032
23
+#define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
33
24
+#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
34
/* EIR and EIMR */
25
35
#define ENET_INT_HB (1 << 31)
26
#define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
36
@@ -XXX,XX +XXX,XX @@
27
37
#define ENET_RCR_NLC (1 << 30)
28
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUState {
38
#define ENET_RCR_GRS (1 << 31)
29
39
30
extern bool is_supported_silicon_rev(uint32_t silicon_rev);
40
+#define ENET_MAX_FRAME_SIZE (1 << ENET_RCR_MAX_FL_LENGTH)
31
41
+
32
+#define ASPEED_SCU_CLASS(klass) \
42
/* TCR */
33
+ OBJECT_CLASS_CHECK(AspeedSCUClass, (klass), TYPE_ASPEED_SCU)
43
#define ENET_TCR_GTS (1 << 0)
34
+#define ASPEED_SCU_GET_CLASS(obj) \
44
#define ENET_TCR_FDEN (1 << 2)
35
+ OBJECT_GET_CLASS(AspeedSCUClass, (obj), TYPE_ASPEED_SCU)
45
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
36
+
37
+typedef struct AspeedSCUClass {
38
+ SysBusDeviceClass parent_class;
39
+
40
+ const uint32_t *resets;
41
+ uint32_t (*calc_hpll)(AspeedSCUState *s);
42
+ uint32_t apb_divider;
43
+} AspeedSCUClass;
44
+
45
#define ASPEED_SCU_PROT_KEY 0x1688A8A8
46
47
/*
48
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
46
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/net/imx_fec.c
50
--- a/hw/arm/aspeed_soc.c
48
+++ b/hw/net/imx_fec.c
51
+++ b/hw/arm/aspeed_soc.c
49
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
52
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
50
crc_ptr = (uint8_t *) &crc;
53
&error_abort, NULL);
51
52
/* Huge frames are truncted. */
53
- if (size > ENET_MAX_FRAME_SIZE) {
54
- size = ENET_MAX_FRAME_SIZE;
55
+ if (size > s->regs[ENET_FTRL]) {
56
+ size = s->regs[ENET_FTRL];
57
flags |= ENET_BD_TR | ENET_BD_LG;
58
}
54
}
59
55
56
+ snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);
57
sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu),
58
- TYPE_ASPEED_SCU);
59
+ typename);
60
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
61
sc->info->silicon_rev);
62
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
63
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/misc/aspeed_scu.c
66
+++ b/hw/misc/aspeed_scu.c
67
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_get_random(void)
68
69
static void aspeed_scu_set_apb_freq(AspeedSCUState *s)
70
{
71
- uint32_t apb_divider;
72
-
73
- switch (s->silicon_rev) {
74
- case AST2400_A0_SILICON_REV:
75
- case AST2400_A1_SILICON_REV:
76
- apb_divider = 2;
77
- break;
78
- case AST2500_A0_SILICON_REV:
79
- case AST2500_A1_SILICON_REV:
80
- apb_divider = 4;
81
- break;
82
- default:
83
- g_assert_not_reached();
84
- }
85
+ AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
86
87
s->apb_freq = s->hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
88
- / apb_divider;
89
+ / asc->apb_divider;
90
}
91
92
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
93
@@ -XXX,XX +XXX,XX @@ static const uint32_t hpll_ast2400_freqs[][4] = {
94
{ 400, 375, 350, 425 }, /* 25MHz */
95
};
96
97
-static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s)
98
+static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s)
99
{
100
uint32_t hpll_reg = s->regs[HPLL_PARAM];
101
uint8_t freq_select;
102
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s)
103
return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
104
}
105
106
-static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s)
107
+static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s)
108
{
109
uint32_t hpll_reg = s->regs[HPLL_PARAM];
110
uint32_t multiplier = 1;
111
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s)
112
static void aspeed_scu_reset(DeviceState *dev)
113
{
114
AspeedSCUState *s = ASPEED_SCU(dev);
115
- const uint32_t *reset;
116
- uint32_t (*calc_hpll)(AspeedSCUState *s);
117
+ AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
118
119
- switch (s->silicon_rev) {
120
- case AST2400_A0_SILICON_REV:
121
- case AST2400_A1_SILICON_REV:
122
- reset = ast2400_a0_resets;
123
- calc_hpll = aspeed_scu_calc_hpll_ast2400;
124
- break;
125
- case AST2500_A0_SILICON_REV:
126
- case AST2500_A1_SILICON_REV:
127
- reset = ast2500_a1_resets;
128
- calc_hpll = aspeed_scu_calc_hpll_ast2500;
129
- break;
130
- default:
131
- g_assert_not_reached();
132
- }
133
-
134
- memcpy(s->regs, reset, sizeof(s->regs));
135
+ memcpy(s->regs, asc->resets, sizeof(s->regs));
136
s->regs[SILICON_REV] = s->silicon_rev;
137
s->regs[HW_STRAP1] = s->hw_strap1;
138
s->regs[HW_STRAP2] = s->hw_strap2;
139
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_reset(DeviceState *dev)
140
* All registers are set. Now compute the frequencies of the main clocks
141
*/
142
s->clkin = aspeed_scu_get_clkin(s);
143
- s->hpll = calc_hpll(s);
144
+ s->hpll = asc->calc_hpll(s);
145
aspeed_scu_set_apb_freq(s);
146
}
147
148
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_scu_info = {
149
.parent = TYPE_SYS_BUS_DEVICE,
150
.instance_size = sizeof(AspeedSCUState),
151
.class_init = aspeed_scu_class_init,
152
+ .class_size = sizeof(AspeedSCUClass),
153
+ .abstract = true,
154
+};
155
+
156
+static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data)
157
+{
158
+ DeviceClass *dc = DEVICE_CLASS(klass);
159
+ AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
160
+
161
+ dc->desc = "ASPEED 2400 System Control Unit";
162
+ asc->resets = ast2400_a0_resets;
163
+ asc->calc_hpll = aspeed_2400_scu_calc_hpll;
164
+ asc->apb_divider = 2;
165
+}
166
+
167
+static const TypeInfo aspeed_2400_scu_info = {
168
+ .name = TYPE_ASPEED_2400_SCU,
169
+ .parent = TYPE_ASPEED_SCU,
170
+ .instance_size = sizeof(AspeedSCUState),
171
+ .class_init = aspeed_2400_scu_class_init,
172
+};
173
+
174
+static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
175
+{
176
+ DeviceClass *dc = DEVICE_CLASS(klass);
177
+ AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
178
+
179
+ dc->desc = "ASPEED 2500 System Control Unit";
180
+ asc->resets = ast2500_a1_resets;
181
+ asc->calc_hpll = aspeed_2500_scu_calc_hpll;
182
+ asc->apb_divider = 4;
183
+}
184
+
185
+static const TypeInfo aspeed_2500_scu_info = {
186
+ .name = TYPE_ASPEED_2500_SCU,
187
+ .parent = TYPE_ASPEED_SCU,
188
+ .instance_size = sizeof(AspeedSCUState),
189
+ .class_init = aspeed_2500_scu_class_init,
190
};
191
192
static void aspeed_scu_register_types(void)
193
{
194
type_register_static(&aspeed_scu_info);
195
+ type_register_static(&aspeed_2400_scu_info);
196
+ type_register_static(&aspeed_2500_scu_info);
197
}
198
199
type_init(aspeed_scu_register_types);
60
--
200
--
61
2.7.4
201
2.20.1
62
202
63
203
diff view generated by jsdifflib
1
From: Zhaoshenglong <zhaoshenglong@huawei.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
acpi_data_push uses g_array_set_size to resize the memory size. If there
3
The APB frequency can be calculated directly when needed from the
4
is no enough contiguous memory, the address will be changed. If we use
4
HPLL_PARAM and CLK_SEL register values. This removes useless state in
5
the old value, it will assert.
5
the model.
6
qemu-kvm: hw/acpi/bios-linker-loader.c:214: bios_linker_loader_add_checksum:
7
Assertion `start_offset < file->blob->len' failed.`
8
6
9
This issue only happens in building SRAT table now but here we unify the
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
pattern for other tables as well to avoid possible issues in the future.
8
Message-id: 20190904070506.1052-11-clg@kaod.org
11
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Zhaoshenglong <zhaoshenglong@huawei.com>
13
Reviewed-by: Andrew Jones <drjones@redhat.com>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
hw/arm/virt-acpi-build.c | 18 +++++++++++-------
12
include/hw/misc/aspeed_scu.h | 8 +++-----
17
1 file changed, 11 insertions(+), 7 deletions(-)
13
hw/misc/aspeed_scu.c | 25 +++++++++----------------
14
hw/timer/aspeed_timer.c | 3 ++-
15
3 files changed, 14 insertions(+), 22 deletions(-)
18
16
19
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
17
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/virt-acpi-build.c
19
--- a/include/hw/misc/aspeed_scu.h
22
+++ b/hw/arm/virt-acpi-build.c
20
+++ b/include/hw/misc/aspeed_scu.h
23
@@ -XXX,XX +XXX,XX @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
21
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUState {
24
AcpiSerialPortConsoleRedirection *spcr;
22
uint32_t hw_strap1;
25
const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART];
23
uint32_t hw_strap2;
26
int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE;
24
uint32_t hw_prot_key;
27
+ int spcr_start = table_data->len;
25
-
28
26
- uint32_t clkin;
29
spcr = acpi_data_push(table_data, sizeof(*spcr));
27
- uint32_t hpll;
30
28
- uint32_t apb_freq;
31
@@ -XXX,XX +XXX,XX @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
29
} AspeedSCUState;
32
spcr->pci_device_id = 0xffff; /* PCI Device ID: not a PCI device */
30
33
spcr->pci_vendor_id = 0xffff; /* PCI Vendor ID: not a PCI device */
31
#define AST2400_A0_SILICON_REV 0x02000303U
34
32
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUClass {
35
- build_header(linker, table_data, (void *)spcr, "SPCR", sizeof(*spcr), 2,
33
SysBusDeviceClass parent_class;
36
- NULL, NULL);
34
37
+ build_header(linker, table_data, (void *)(table_data->data + spcr_start),
35
const uint32_t *resets;
38
+ "SPCR", table_data->len - spcr_start, 2, NULL, NULL);
36
- uint32_t (*calc_hpll)(AspeedSCUState *s);
37
+ uint32_t (*calc_hpll)(AspeedSCUState *s, uint32_t hpll_reg);
38
uint32_t apb_divider;
39
} AspeedSCUClass;
40
41
#define ASPEED_SCU_PROT_KEY 0x1688A8A8
42
43
+uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
44
+
45
/*
46
* Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions
47
* were added.
48
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/misc/aspeed_scu.c
51
+++ b/hw/misc/aspeed_scu.c
52
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_get_random(void)
53
return num;
39
}
54
}
40
55
41
static void
56
-static void aspeed_scu_set_apb_freq(AspeedSCUState *s)
42
@@ -XXX,XX +XXX,XX @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
57
+uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s)
43
mem_base += numa_info[i].node_mem;
58
{
59
AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
60
+ uint32_t hpll = asc->calc_hpll(s, s->regs[HPLL_PARAM]);
61
62
- s->apb_freq = s->hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
63
+ return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
64
/ asc->apb_divider;
65
}
66
67
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
68
return;
69
case CLK_SEL:
70
s->regs[reg] = data;
71
- aspeed_scu_set_apb_freq(s);
72
break;
73
case HW_STRAP1:
74
if (ASPEED_IS_AST2500(s->regs[SILICON_REV])) {
75
@@ -XXX,XX +XXX,XX @@ static const uint32_t hpll_ast2400_freqs[][4] = {
76
{ 400, 375, 350, 425 }, /* 25MHz */
77
};
78
79
-static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s)
80
+static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
81
{
82
- uint32_t hpll_reg = s->regs[HPLL_PARAM];
83
uint8_t freq_select;
84
bool clk_25m_in;
85
+ uint32_t clkin = aspeed_scu_get_clkin(s);
86
87
if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
88
return 0;
89
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s)
90
multiplier = (2 - od) * ((n + 2) / (d + 1));
91
}
92
93
- return s->clkin * multiplier;
94
+ return clkin * multiplier;
44
}
95
}
45
96
46
- build_header(linker, table_data, (void *)srat, "SRAT",
97
/* HW strapping */
47
- table_data->len - srat_start, 3, NULL, NULL);
98
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s)
48
+ build_header(linker, table_data, (void *)(table_data->data + srat_start),
99
return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
49
+ "SRAT", table_data->len - srat_start, 3, NULL, NULL);
50
}
100
}
51
101
52
static void
102
-static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s)
53
@@ -XXX,XX +XXX,XX @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
103
+static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
54
AcpiTableMcfg *mcfg;
104
{
55
const MemMapEntry *memmap = vms->memmap;
105
- uint32_t hpll_reg = s->regs[HPLL_PARAM];
56
int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]);
106
uint32_t multiplier = 1;
57
+ int mcfg_start = table_data->len;
107
+ uint32_t clkin = aspeed_scu_get_clkin(s);
58
108
59
mcfg = acpi_data_push(table_data, len);
109
if (hpll_reg & SCU_H_PLL_OFF) {
60
mcfg->allocation[0].address = cpu_to_le64(memmap[VIRT_PCIE_ECAM].base);
110
return 0;
61
@@ -XXX,XX +XXX,XX @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
111
@@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s)
62
mcfg->allocation[0].end_bus_number = (memmap[VIRT_PCIE_ECAM].size
112
multiplier = ((m + 1) / (n + 1)) / (p + 1);
63
/ PCIE_MMCFG_SIZE_MIN) - 1;
113
}
64
114
65
- build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL);
115
- return s->clkin * multiplier;
66
+ build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
116
+ return clkin * multiplier;
67
+ "MCFG", table_data->len - mcfg_start, 1, NULL, NULL);
68
}
117
}
69
118
70
/* GTDT */
119
static void aspeed_scu_reset(DeviceState *dev)
71
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
120
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_reset(DeviceState *dev)
72
static void build_fadt(GArray *table_data, BIOSLinker *linker,
121
s->regs[HW_STRAP1] = s->hw_strap1;
73
VirtMachineState *vms, unsigned dsdt_tbl_offset)
122
s->regs[HW_STRAP2] = s->hw_strap2;
123
s->regs[PROT_KEY] = s->hw_prot_key;
124
-
125
- /*
126
- * All registers are set. Now compute the frequencies of the main clocks
127
- */
128
- s->clkin = aspeed_scu_get_clkin(s);
129
- s->hpll = asc->calc_hpll(s);
130
- aspeed_scu_set_apb_freq(s);
131
}
132
133
static uint32_t aspeed_silicon_revs[] = {
134
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/hw/timer/aspeed_timer.c
137
+++ b/hw/timer/aspeed_timer.c
138
@@ -XXX,XX +XXX,XX @@ static inline uint32_t calculate_rate(struct AspeedTimer *t)
74
{
139
{
75
+ int fadt_start = table_data->len;
140
AspeedTimerCtrlState *s = timer_to_ctrl(t);
76
AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
141
77
unsigned xdsdt_entry_offset = (char *)&fadt->x_dsdt - table_data->data;
142
- return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ : s->scu->apb_freq;
78
uint16_t bootflags;
143
+ return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ :
79
@@ -XXX,XX +XXX,XX @@ static void build_fadt(GArray *table_data, BIOSLinker *linker,
144
+ aspeed_scu_get_apb_freq(s->scu);
80
ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset, sizeof(fadt->x_dsdt),
81
ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset);
82
83
- build_header(linker, table_data,
84
- (void *)fadt, "FACP", sizeof(*fadt), 5, NULL, NULL);
85
+ build_header(linker, table_data, (void *)(table_data->data + fadt_start),
86
+ "FACP", table_data->len - fadt_start, 5, NULL, NULL);
87
}
145
}
88
146
89
/* DSDT */
147
static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t now_ns)
90
--
148
--
91
2.7.4
149
2.20.1
92
150
93
151
diff view generated by jsdifflib
Deleted patch
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
2
1
3
Binding to a particular netdev doesn't seem to belong to this layer
4
and should probably be done as a part of board or SoC specific code.
5
6
Convert all of the users of this IP block to use
7
qdev_set_nic_properties() instead.
8
9
Cc: Peter Maydell <peter.maydell@linaro.org>
10
Cc: Jason Wang <jasowang@redhat.com>
11
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Cc: qemu-devel@nongnu.org
13
Cc: qemu-arm@nongnu.org
14
Cc: yurovsky@gmail.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/arm/fsl-imx6.c | 1 +
20
hw/net/imx_fec.c | 2 --
21
2 files changed, 1 insertion(+), 2 deletions(-)
22
23
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/fsl-imx6.c
26
+++ b/hw/arm/fsl-imx6.c
27
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
28
spi_table[i].irq));
29
}
30
31
+ qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]);
32
object_property_set_bool(OBJECT(&s->eth), true, "realized", &err);
33
if (err) {
34
error_propagate(errp, err);
35
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/net/imx_fec.c
38
+++ b/hw/net/imx_fec.c
39
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
40
41
qemu_macaddr_default_if_unset(&s->conf.macaddr);
42
43
- s->conf.peers.ncs[0] = nd_table[0].netdev;
44
-
45
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
46
object_get_typename(OBJECT(dev)),
47
DEVICE(dev)->id, s);
48
--
49
2.7.4
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
2
1
3
Cc: Peter Maydell <peter.maydell@linaro.org>
4
Cc: Jason Wang <jasowang@redhat.com>
5
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Cc: qemu-devel@nongnu.org
7
Cc: qemu-arm@nongnu.org
8
Cc: yurovsky@gmail.com
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/net/imx_fec.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/imx_fec.c
19
+++ b/hw/net/imx_fec.c
20
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
21
TYPE_IMX_FEC, __func__);
22
break;
23
}
24
- buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR];
25
+ buf_len = MIN(size, s->regs[ENET_MRBR]);
26
bd.length = buf_len;
27
size -= buf_len;
28
29
--
30
2.7.4
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
2
1
3
Use 'frame_size' instead of 'len' when calling qemu_send_packet(),
4
failing to do so results in malformed packets send in case when that
5
packed is fragmented into multiple DMA transactions.
6
7
Cc: Peter Maydell <peter.maydell@linaro.org>
8
Cc: Jason Wang <jasowang@redhat.com>
9
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/net/imx_fec.c | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/net/imx_fec.c
23
+++ b/hw/net/imx_fec.c
24
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
25
}
26
/* Last buffer in frame. */
27
28
- qemu_send_packet(qemu_get_queue(s->nic), s->frame, len);
29
+ qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
30
ptr = s->frame;
31
32
frame_size = 0;
33
--
34
2.7.4
35
36
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: "Emilio G. Cota" <cota@braap.org>
2
2
3
Cc: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Cc: Jason Wang <jasowang@redhat.com>
4
Signed-off-by: Emilio G. Cota <cota@braap.org>
5
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Cc: qemu-devel@nongnu.org
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
Cc: qemu-arm@nongnu.org
8
Cc: yurovsky@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
8
---
13
hw/net/imx_fec.c | 2 +-
9
accel/tcg/atomic_template.h | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
15
11
16
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
12
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/imx_fec.c
14
--- a/accel/tcg/atomic_template.h
19
+++ b/hw/net/imx_fec.c
15
+++ b/accel/tcg/atomic_template.h
20
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
16
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
21
size += 2;
17
22
}
18
#define GEN_ATOMIC_HELPER(X) \
23
19
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
24
- /* Huge frames are truncted. */
20
- ABI_TYPE val EXTRA_ARGS) \
25
+ /* Huge frames are truncated. */
21
+ ABI_TYPE val EXTRA_ARGS) \
26
if (size > s->regs[ENET_FTRL]) {
22
{ \
27
size = s->regs[ENET_FTRL];
23
ATOMIC_MMU_DECLS; \
28
flags |= ENET_BD_TR | ENET_BD_LG;
24
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
29
--
25
--
30
2.7.4
26
2.20.1
31
27
32
28
diff view generated by jsdifflib
Deleted patch
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
2
1
3
Some i.MX SoCs (e.g. i.MX7) have FEC registers going as far as offset
4
0x614, so to avoid getting aborts when accessing those on QEMU, extend
5
the register file to cover FSL_IMX25_FEC_SIZE(16K) of address space
6
instead of just 1K.
7
8
Cc: Peter Maydell <peter.maydell@linaro.org>
9
Cc: Jason Wang <jasowang@redhat.com>
10
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Cc: qemu-devel@nongnu.org
12
Cc: qemu-arm@nongnu.org
13
Cc: yurovsky@gmail.com
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/hw/arm/fsl-imx25.h | 1 -
19
include/hw/net/imx_fec.h | 1 +
20
hw/net/imx_fec.c | 2 +-
21
3 files changed, 2 insertions(+), 2 deletions(-)
22
23
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/fsl-imx25.h
26
+++ b/include/hw/arm/fsl-imx25.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
28
#define FSL_IMX25_UART5_ADDR 0x5002C000
29
#define FSL_IMX25_UART5_SIZE 0x4000
30
#define FSL_IMX25_FEC_ADDR 0x50038000
31
-#define FSL_IMX25_FEC_SIZE 0x4000
32
#define FSL_IMX25_CCM_ADDR 0x53F80000
33
#define FSL_IMX25_CCM_SIZE 0x4000
34
#define FSL_IMX25_GPT4_ADDR 0x53F84000
35
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/net/imx_fec.h
38
+++ b/include/hw/net/imx_fec.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct {
40
41
#define ENET_TX_RING_NUM 3
42
43
+#define FSL_IMX25_FEC_SIZE 0x4000
44
45
typedef struct IMXFECState {
46
/*< private >*/
47
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/net/imx_fec.c
50
+++ b/hw/net/imx_fec.c
51
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
52
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
53
54
memory_region_init_io(&s->iomem, OBJECT(dev), &imx_eth_ops, s,
55
- TYPE_IMX_FEC, 0x400);
56
+ TYPE_IMX_FEC, FSL_IMX25_FEC_SIZE);
57
sysbus_init_mmio(sbd, &s->iomem);
58
sysbus_init_irq(sbd, &s->irq[0]);
59
sysbus_init_irq(sbd, &s->irq[1]);
60
--
61
2.7.4
62
63
diff view generated by jsdifflib
Deleted patch
1
Our copy of the nwfpe code for emulating of the old FPA11 floating
2
point unit doesn't check the coprocessor number in the instruction
3
when it emulates it. This means that we might treat some
4
instructions which should really UNDEF as being FPA11 instructions by
5
accident.
6
1
7
The kernel's copy of the nwfpe code doesn't make this error; I suspect
8
the bug was noticed and fixed as part of the process of mainlining
9
the nwfpe code more than a decade ago.
10
11
Add a check that the coprocessor number (which is always in bits
12
[11:8] of the instruction) is either 1 or 2, which is where the
13
FPA11 lives.
14
15
Reported-by: Richard Henderson <richard.henderson@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
linux-user/arm/nwfpe/fpa11.c | 9 +++++++++
19
1 file changed, 9 insertions(+)
20
21
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/linux-user/arm/nwfpe/fpa11.c
24
+++ b/linux-user/arm/nwfpe/fpa11.c
25
@@ -XXX,XX +XXX,XX @@ unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs)
26
unsigned int nRc = 0;
27
// unsigned long flags;
28
FPA11 *fpa11;
29
+ unsigned int cp;
30
// save_flags(flags); sti();
31
32
+ /* Check that this is really an FPA11 instruction: the coprocessor
33
+ * field in bits [11:8] must be 1 or 2.
34
+ */
35
+ cp = (opcode >> 8) & 0xf;
36
+ if (cp != 1 && cp != 2) {
37
+ return 0;
38
+ }
39
+
40
qemufpa=qfpa;
41
user_registers=qregs;
42
43
--
44
2.7.4
45
46
diff view generated by jsdifflib
1
Refactor disas_thumb2_insn() so that it generates the code for raising
1
The qemu-ga documentation is currently in qemu-ga.texi in
2
an UNDEF exception for invalid insns, rather than returning a flag
2
Texinfo format, which we present to the user as:
3
which the caller must check to see if it needs to generate the UNDEF
3
* a qemu-ga manpage
4
code. This brings the function in to line with the behaviour of
4
* a section of the main qemu-doc HTML documentation
5
disas_thumb_insn() and disas_arm_insn().
5
6
Convert the documentation to rST format, and present it to
7
the user as:
8
* a qemu-ga manpage
9
* part of the interop/ Sphinx manual
6
10
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
9
Message-id: 1513080506-17703-1-git-send-email-peter.maydell@linaro.org
13
Tested-by: Michael Roth <mdroth@linux.vnet.ibm.com>
14
Message-id: 20190905131040.8350-1-peter.maydell@linaro.org
10
---
15
---
11
target/arm/translate.c | 23 ++++++++++-------------
16
Makefile | 24 ++++---
12
1 file changed, 10 insertions(+), 13 deletions(-)
17
MAINTAINERS | 2 +-
18
docs/conf.py | 18 ++---
19
docs/interop/conf.py | 7 ++
20
docs/interop/index.rst | 1 +
21
docs/interop/qemu-ga.rst | 133 +++++++++++++++++++++++++++++++++++++
22
qemu-doc.texi | 5 --
23
qemu-ga.texi | 137 ---------------------------------------
24
8 files changed, 166 insertions(+), 161 deletions(-)
25
create mode 100644 docs/interop/qemu-ga.rst
26
delete mode 100644 qemu-ga.texi
13
27
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
28
diff --git a/Makefile b/Makefile
15
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
30
--- a/Makefile
17
+++ b/target/arm/translate.c
31
+++ b/Makefile
18
@@ -XXX,XX +XXX,XX @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
32
@@ -XXX,XX +XXX,XX @@ endif
19
return 0;
33
endif
20
}
34
21
35
ifdef BUILD_DOCS
22
-/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
36
-DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
23
- is not legal. */
37
+DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 docs/interop/qemu-ga.8
24
-static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
38
DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7
25
+/* Translate a 32-bit thumb instruction. */
39
DOCS+=docs/interop/qemu-ga-ref.html docs/interop/qemu-ga-ref.txt docs/interop/qemu-ga-ref.7
26
+static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
40
DOCS+=docs/qemu-block-drivers.7
27
{
41
@@ -XXX,XX +XXX,XX @@ DESCS=
28
uint32_t imm, shift, offset;
42
endif
29
uint32_t rd, rn, rm, rs;
43
30
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
44
# Note that we manually filter-out the non-Sphinx documentation which
31
/* UNPREDICTABLE, unallocated hint or
45
-# is currently built into the docs/interop directory in the build tree.
32
* PLD/PLDW/PLI (literal)
46
+# is currently built into the docs/interop directory in the build tree,
33
*/
47
+# and also any sphinx-built manpages.
34
- return 0;
48
define install-manual =
35
+ return;
49
for d in $$(cd $(MANUAL_BUILDDIR) && find $1 -type d); do $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)/$$d"; done
36
}
50
-for f in $$(cd $(MANUAL_BUILDDIR) && find $1 -type f -a '!' '(' -name 'qemu-*-qapi.*' -o -name 'qemu-*-ref.*' ')' ); do $(INSTALL_DATA) "$(MANUAL_BUILDDIR)/$$f" "$(DESTDIR)$(qemu_docdir)/$$f"; done
37
if (op1 & 1) {
51
+for f in $$(cd $(MANUAL_BUILDDIR) && find $1 -type f -a '!' '(' -name '*.[0-9]' -o -name 'qemu-*-qapi.*' -o -name 'qemu-*-ref.*' ')' ); do $(INSTALL_DATA) "$(MANUAL_BUILDDIR)/$$f" "$(DESTDIR)$(qemu_docdir)/$$f"; done
38
- return 0; /* PLD/PLDW/PLI or unallocated hint */
52
endef
39
+ return; /* PLD/PLDW/PLI or unallocated hint */
53
40
}
54
# Note that we deliberately do not install the "devel" manual: it is
41
if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
55
@@ -XXX,XX +XXX,XX @@ ifdef CONFIG_TRACE_SYSTEMTAP
42
- return 0; /* PLD/PLDW/PLI or unallocated hint */
56
    $(INSTALL_DATA) scripts/qemu-trace-stap.1 "$(DESTDIR)$(mandir)/man1"
43
+ return; /* PLD/PLDW/PLI or unallocated hint */
57
endif
44
}
58
ifneq (,$(findstring qemu-ga,$(TOOLS)))
45
/* UNDEF space, or an UNPREDICTABLE */
59
-    $(INSTALL_DATA) qemu-ga.8 "$(DESTDIR)$(mandir)/man8"
46
- return 1;
60
+    $(INSTALL_DATA) docs/interop/qemu-ga.8 "$(DESTDIR)$(mandir)/man8"
47
+ goto illegal_op;
61
    $(INSTALL_DATA) docs/interop/qemu-ga-ref.html "$(DESTDIR)$(qemu_docdir)"
48
}
62
    $(INSTALL_DATA) docs/interop/qemu-ga-ref.txt "$(DESTDIR)$(qemu_docdir)"
49
}
63
    $(INSTALL_DATA) docs/interop/qemu-ga-ref.7 "$(DESTDIR)$(mandir)/man7"
50
memidx = get_mem_index(s);
64
@@ -XXX,XX +XXX,XX @@ docs/version.texi: $(SRC_PATH)/VERSION config-host.mak
51
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
65
sphinxdocs: $(MANUAL_BUILDDIR)/devel/index.html $(MANUAL_BUILDDIR)/interop/index.html $(MANUAL_BUILDDIR)/specs/index.html
52
default:
66
53
goto illegal_op;
67
# Canned command to build a single manual
54
}
68
-build-manual = $(call quiet-command,sphinx-build $(if $(V),,-q) -W -n -b html -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1")
55
- return 0;
69
+# Arguments: $1 = manual name, $2 = Sphinx builder ('html' or 'man')
56
+ return;
70
+build-manual = $(call quiet-command,CONFDIR="$(qemu_confdir)" sphinx-build $(if $(V),,-q) -W -n -b $2 -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1")
57
illegal_op:
71
# We assume all RST files in the manual's directory are used in it
58
- return 1;
72
manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst) $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py
59
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
73
60
+ default_exception_el(s));
74
$(MANUAL_BUILDDIR)/devel/index.html: $(call manual-deps,devel)
61
}
75
-    $(call build-manual,devel)
62
76
+    $(call build-manual,devel,html)
63
static void disas_thumb_insn(DisasContext *s, uint32_t insn)
77
64
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
78
$(MANUAL_BUILDDIR)/interop/index.html: $(call manual-deps,interop)
65
if (is_16bit) {
79
-    $(call build-manual,interop)
66
disas_thumb_insn(dc, insn);
80
+    $(call build-manual,interop,html)
67
} else {
81
68
- if (disas_thumb2_insn(dc, insn)) {
82
$(MANUAL_BUILDDIR)/specs/index.html: $(call manual-deps,specs)
69
- gen_exception_insn(dc, 4, EXCP_UDEF, syn_uncategorized(),
83
-    $(call build-manual,specs)
70
- default_exception_el(dc));
84
+    $(call build-manual,specs,html)
71
- }
85
+
72
+ disas_thumb2_insn(dc, insn);
86
+$(MANUAL_BUILDDIR)/interop/qemu-ga.8: $(call manual-deps,interop)
73
}
87
+    $(call build-manual,interop,man)
74
88
75
/* Advance the Thumb condexec condition. */
89
qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
90
    $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
91
@@ -XXX,XX +XXX,XX @@ qemu.1: qemu-option-trace.texi
92
qemu-img.1: qemu-img.texi qemu-option-trace.texi qemu-img-cmds.texi
93
fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
94
qemu-nbd.8: qemu-nbd.texi qemu-option-trace.texi
95
-qemu-ga.8: qemu-ga.texi
96
docs/qemu-block-drivers.7: docs/qemu-block-drivers.texi
97
docs/qemu-cpu-models.7: docs/qemu-cpu-models.texi
98
scripts/qemu-trace-stap.1: scripts/qemu-trace-stap.texi
99
@@ -XXX,XX +XXX,XX @@ txt: qemu-doc.txt docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt
100
qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \
101
    qemu-img.texi qemu-nbd.texi qemu-options.texi \
102
    qemu-tech.texi qemu-option-trace.texi \
103
-    qemu-deprecated.texi qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \
104
+    qemu-deprecated.texi qemu-monitor.texi qemu-img-cmds.texi \
105
    qemu-monitor-info.texi docs/qemu-block-drivers.texi \
106
    docs/qemu-cpu-models.texi docs/security.texi
107
108
diff --git a/MAINTAINERS b/MAINTAINERS
109
index XXXXXXX..XXXXXXX 100644
110
--- a/MAINTAINERS
111
+++ b/MAINTAINERS
112
@@ -XXX,XX +XXX,XX @@ QEMU Guest Agent
113
M: Michael Roth <mdroth@linux.vnet.ibm.com>
114
S: Maintained
115
F: qga/
116
-F: qemu-ga.texi
117
+F: docs/interop/qemu-ga.rst
118
F: scripts/qemu-guest-agent/
119
F: tests/test-qga.c
120
F: docs/interop/qemu-ga-ref.texi
121
diff --git a/docs/conf.py b/docs/conf.py
122
index XXXXXXX..XXXXXXX 100644
123
--- a/docs/conf.py
124
+++ b/docs/conf.py
125
@@ -XXX,XX +XXX,XX @@ todo_include_todos = False
126
# with "option::" in the document being processed. Turn that off.
127
suppress_warnings = ["ref.option"]
128
129
+# The rst_epilog fragment is effectively included in every rST file.
130
+# We use it to define substitutions based on build config that
131
+# can then be used in the documentation. The fallback if the
132
+# environment variable is not set is for the benefit of readthedocs
133
+# style document building; our Makefile always sets the variable.
134
+confdir = os.getenv('CONFDIR', "/etc/qemu")
135
+rst_epilog = ".. |CONFDIR| replace:: ``" + confdir + "``\n"
136
+
137
# -- Options for HTML output ----------------------------------------------
138
139
# The theme to use for HTML and HTML Help pages. See the documentation for
140
@@ -XXX,XX +XXX,XX @@ latex_documents = [
141
142
143
# -- Options for manual page output ---------------------------------------
144
-
145
-# One entry per manual page. List of tuples
146
-# (source start file, name, description, authors, manual section).
147
-man_pages = [
148
- (master_doc, 'qemu', u'QEMU Documentation',
149
- [author], 1)
150
-]
151
-
152
+# Individual manual/conf.py can override this to create man pages
153
+man_pages = []
154
155
# -- Options for Texinfo output -------------------------------------------
156
157
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
158
index XXXXXXX..XXXXXXX 100644
159
--- a/docs/interop/conf.py
160
+++ b/docs/interop/conf.py
161
@@ -XXX,XX +XXX,XX @@ exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
162
# This slightly misuses the 'description', but is the best way to get
163
# the manual title to appear in the sidebar.
164
html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
165
+
166
+# One entry per manual page. List of tuples
167
+# (source start file, name, description, authors, manual section).
168
+man_pages = [
169
+ ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
170
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8)
171
+]
172
diff --git a/docs/interop/index.rst b/docs/interop/index.rst
173
index XXXXXXX..XXXXXXX 100644
174
--- a/docs/interop/index.rst
175
+++ b/docs/interop/index.rst
176
@@ -XXX,XX +XXX,XX @@ Contents:
177
bitmaps
178
live-block-operations
179
pr-helper
180
+ qemu-ga
181
vhost-user
182
vhost-user-gpu
183
diff --git a/docs/interop/qemu-ga.rst b/docs/interop/qemu-ga.rst
184
new file mode 100644
185
index XXXXXXX..XXXXXXX
186
--- /dev/null
187
+++ b/docs/interop/qemu-ga.rst
188
@@ -XXX,XX +XXX,XX @@
189
+QEMU Guest Agent
190
+================
191
+
192
+Synopsis
193
+--------
194
+
195
+**qemu-ga** [*OPTIONS*]
196
+
197
+Description
198
+-----------
199
+
200
+The QEMU Guest Agent is a daemon intended to be run within virtual
201
+machines. It allows the hypervisor host to perform various operations
202
+in the guest, such as:
203
+
204
+- get information from the guest
205
+- set the guest's system time
206
+- read/write a file
207
+- sync and freeze the filesystems
208
+- suspend the guest
209
+- reconfigure guest local processors
210
+- set user's password
211
+- ...
212
+
213
+qemu-ga will read a system configuration file on startup (located at
214
+|CONFDIR|\ ``/qemu-ga.conf`` by default), then parse remaining
215
+configuration options on the command line. For the same key, the last
216
+option wins, but the lists accumulate (see below for configuration
217
+file format).
218
+
219
+Options
220
+-------
221
+
222
+.. program:: qemu-ga
223
+
224
+.. option:: -m, --method=METHOD
225
+
226
+ Transport method: one of ``unix-listen``, ``virtio-serial``, or
227
+ ``isa-serial`` (``virtio-serial`` is the default).
228
+
229
+.. option:: -p, --path=PATH
230
+
231
+ Device/socket path (the default for virtio-serial is
232
+ ``/dev/virtio-ports/org.qemu.guest_agent.0``,
233
+ the default for isa-serial is ``/dev/ttyS0``)
234
+
235
+.. option:: -l, --logfile=PATH
236
+
237
+ Set log file path (default is stderr).
238
+
239
+.. option:: -f, --pidfile=PATH
240
+
241
+ Specify pid file (default is ``/var/run/qemu-ga.pid``).
242
+
243
+.. option:: -F, --fsfreeze-hook=PATH
244
+
245
+ Enable fsfreeze hook. Accepts an optional argument that specifies
246
+ script to run on freeze/thaw. Script will be called with
247
+ 'freeze'/'thaw' arguments accordingly (default is
248
+ |CONFDIR|\ ``/fsfreeze-hook``). If using -F with an argument, do
249
+ not follow -F with a space (for example:
250
+ ``-F/var/run/fsfreezehook.sh``).
251
+
252
+.. option:: -t, --statedir=PATH
253
+
254
+ Specify the directory to store state information (absolute paths only,
255
+ default is ``/var/run``).
256
+
257
+.. option:: -v, --verbose
258
+
259
+ Log extra debugging information.
260
+
261
+.. option:: -V, --version
262
+
263
+ Print version information and exit.
264
+
265
+.. option:: -d, --daemon
266
+
267
+ Daemonize after startup (detach from terminal).
268
+
269
+.. option:: -b, --blacklist=LIST
270
+
271
+ Comma-separated list of RPCs to disable (no spaces, ``?`` to list
272
+ available RPCs).
273
+
274
+.. option:: -D, --dump-conf
275
+
276
+ Dump the configuration in a format compatible with ``qemu-ga.conf``
277
+ and exit.
278
+
279
+.. option:: -h, --help
280
+
281
+ Display this help and exit.
282
+
283
+Files
284
+-----
285
+
286
+
287
+The syntax of the ``qemu-ga.conf`` configuration file follows the
288
+Desktop Entry Specification, here is a quick summary: it consists of
289
+groups of key-value pairs, interspersed with comments.
290
+
291
+::
292
+
293
+ # qemu-ga configuration sample
294
+ [general]
295
+ daemonize = 0
296
+ pidfile = /var/run/qemu-ga.pid
297
+ verbose = 0
298
+ method = virtio-serial
299
+ path = /dev/virtio-ports/org.qemu.guest_agent.0
300
+ statedir = /var/run
301
+
302
+The list of keys follows the command line options:
303
+
304
+============= ===========
305
+Key Key type
306
+============= ===========
307
+daemon boolean
308
+method string
309
+path string
310
+logfile string
311
+pidfile string
312
+fsfreeze-hook string
313
+statedir string
314
+verbose boolean
315
+blacklist string list
316
+============= ===========
317
+
318
+See also
319
+--------
320
+
321
+:manpage:`qemu(1)`
322
diff --git a/qemu-doc.texi b/qemu-doc.texi
323
index XXXXXXX..XXXXXXX 100644
324
--- a/qemu-doc.texi
325
+++ b/qemu-doc.texi
326
@@ -XXX,XX +XXX,XX @@ so should only be used with trusted guest OS.
327
328
@c man end
329
330
-@node QEMU Guest Agent
331
-@chapter QEMU Guest Agent invocation
332
-
333
-@include qemu-ga.texi
334
-
335
@node QEMU User space emulator
336
@chapter QEMU User space emulator
337
338
diff --git a/qemu-ga.texi b/qemu-ga.texi
339
deleted file mode 100644
340
index XXXXXXX..XXXXXXX
341
--- a/qemu-ga.texi
342
+++ /dev/null
343
@@ -XXX,XX +XXX,XX @@
344
-@example
345
-@c man begin SYNOPSIS
346
-@command{qemu-ga} [@var{OPTIONS}]
347
-@c man end
348
-@end example
349
-
350
-@c man begin DESCRIPTION
351
-
352
-The QEMU Guest Agent is a daemon intended to be run within virtual
353
-machines. It allows the hypervisor host to perform various operations
354
-in the guest, such as:
355
-
356
-@itemize
357
-@item
358
-get information from the guest
359
-@item
360
-set the guest's system time
361
-@item
362
-read/write a file
363
-@item
364
-sync and freeze the filesystems
365
-@item
366
-suspend the guest
367
-@item
368
-reconfigure guest local processors
369
-@item
370
-set user's password
371
-@item
372
-...
373
-@end itemize
374
-
375
-qemu-ga will read a system configuration file on startup (located at
376
-@file{@value{CONFDIR}/qemu-ga.conf} by default), then parse remaining
377
-configuration options on the command line. For the same key, the last
378
-option wins, but the lists accumulate (see below for configuration
379
-file format).
380
-
381
-@c man end
382
-
383
-@c man begin OPTIONS
384
-@table @option
385
-@item -m, --method=@var{method}
386
- Transport method: one of @samp{unix-listen}, @samp{virtio-serial}, or
387
- @samp{isa-serial} (@samp{virtio-serial} is the default).
388
-
389
-@item -p, --path=@var{path}
390
- Device/socket path (the default for virtio-serial is
391
- @samp{/dev/virtio-ports/org.qemu.guest_agent.0},
392
- the default for isa-serial is @samp{/dev/ttyS0})
393
-
394
-@item -l, --logfile=@var{path}
395
- Set log file path (default is stderr).
396
-
397
-@item -f, --pidfile=@var{path}
398
- Specify pid file (default is @samp{/var/run/qemu-ga.pid}).
399
-
400
-@item -F, --fsfreeze-hook=@var{path}
401
- Enable fsfreeze hook. Accepts an optional argument that specifies
402
- script to run on freeze/thaw. Script will be called with
403
- 'freeze'/'thaw' arguments accordingly (default is
404
- @samp{@value{CONFDIR}/fsfreeze-hook}). If using -F with an argument, do
405
- not follow -F with a space (for example:
406
- @samp{-F/var/run/fsfreezehook.sh}).
407
-
408
-@item -t, --statedir=@var{path}
409
- Specify the directory to store state information (absolute paths only,
410
- default is @samp{/var/run}).
411
-
412
-@item -v, --verbose
413
- Log extra debugging information.
414
-
415
-@item -V, --version
416
- Print version information and exit.
417
-
418
-@item -d, --daemon
419
- Daemonize after startup (detach from terminal).
420
-
421
-@item -b, --blacklist=@var{list}
422
- Comma-separated list of RPCs to disable (no spaces, @samp{?} to list
423
- available RPCs).
424
-
425
-@item -D, --dump-conf
426
- Dump the configuration in a format compatible with @file{qemu-ga.conf}
427
- and exit.
428
-
429
-@item -h, --help
430
- Display this help and exit.
431
-@end table
432
-
433
-@c man end
434
-
435
-@c man begin FILES
436
-
437
-The syntax of the @file{qemu-ga.conf} configuration file follows the
438
-Desktop Entry Specification, here is a quick summary: it consists of
439
-groups of key-value pairs, interspersed with comments.
440
-
441
-@example
442
-# qemu-ga configuration sample
443
-[general]
444
-daemonize = 0
445
-pidfile = /var/run/qemu-ga.pid
446
-verbose = 0
447
-method = virtio-serial
448
-path = /dev/virtio-ports/org.qemu.guest_agent.0
449
-statedir = /var/run
450
-@end example
451
-
452
-The list of keys follows the command line options:
453
-@table @option
454
-@item daemon= boolean
455
-@item method= string
456
-@item path= string
457
-@item logfile= string
458
-@item pidfile= string
459
-@item fsfreeze-hook= string
460
-@item statedir= string
461
-@item verbose= boolean
462
-@item blacklist= string list
463
-@end table
464
-
465
-@c man end
466
-
467
-@ignore
468
-
469
-@setfilename qemu-ga
470
-@settitle QEMU Guest Agent
471
-
472
-@c man begin AUTHOR
473
-Michael Roth <mdroth@linux.vnet.ibm.com>
474
-@c man end
475
-
476
-@c man begin SEEALSO
477
-qemu(1)
478
-@c man end
479
-
480
-@end ignore
76
--
481
--
77
2.7.4
482
2.20.1
78
483
79
484
diff view generated by jsdifflib
Deleted patch
1
The GICv3 specification says that reserved register addresses
2
should RAZ/WI. This means we need to return MEMTX_OK, not MEMTX_ERROR,
3
because now that we support generating external aborts the
4
latter will cause an abort on new board models.
5
1
6
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1513183941-24300-2-git-send-email-peter.maydell@linaro.org
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
10
---
11
hw/intc/arm_gicv3_dist.c | 13 +++++++++++++
12
hw/intc/arm_gicv3_its_common.c | 8 +++-----
13
hw/intc/arm_gicv3_redist.c | 13 +++++++++++++
14
3 files changed, 29 insertions(+), 5 deletions(-)
15
16
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/arm_gicv3_dist.c
19
+++ b/hw/intc/arm_gicv3_dist.c
20
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
21
"%s: invalid guest read at offset " TARGET_FMT_plx
22
"size %u\n", __func__, offset, size);
23
trace_gicv3_dist_badread(offset, size, attrs.secure);
24
+ /* The spec requires that reserved registers are RAZ/WI;
25
+ * so use MEMTX_ERROR returns from leaf functions as a way to
26
+ * trigger the guest-error logging but don't return it to
27
+ * the caller, or we'll cause a spurious guest data abort.
28
+ */
29
+ r = MEMTX_OK;
30
+ *data = 0;
31
} else {
32
trace_gicv3_dist_read(offset, *data, size, attrs.secure);
33
}
34
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
35
"%s: invalid guest write at offset " TARGET_FMT_plx
36
"size %u\n", __func__, offset, size);
37
trace_gicv3_dist_badwrite(offset, data, size, attrs.secure);
38
+ /* The spec requires that reserved registers are RAZ/WI;
39
+ * so use MEMTX_ERROR returns from leaf functions as a way to
40
+ * trigger the guest-error logging but don't return it to
41
+ * the caller, or we'll cause a spurious guest data abort.
42
+ */
43
+ r = MEMTX_OK;
44
} else {
45
trace_gicv3_dist_write(offset, data, size, attrs.secure);
46
}
47
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/intc/arm_gicv3_its_common.c
50
+++ b/hw/intc/arm_gicv3_its_common.c
51
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
52
MemTxAttrs attrs)
53
{
54
qemu_log_mask(LOG_GUEST_ERROR, "ITS read at offset 0x%"PRIx64"\n", offset);
55
- return MEMTX_ERROR;
56
+ *data = 0;
57
+ return MEMTX_OK;
58
}
59
60
static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
61
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
62
if (ret <= 0) {
63
qemu_log_mask(LOG_GUEST_ERROR,
64
"ITS: Error sending MSI: %s\n", strerror(-ret));
65
- return MEMTX_DECODE_ERROR;
66
}
67
-
68
- return MEMTX_OK;
69
} else {
70
qemu_log_mask(LOG_GUEST_ERROR,
71
"ITS write at bad offset 0x%"PRIx64"\n", offset);
72
- return MEMTX_DECODE_ERROR;
73
}
74
+ return MEMTX_OK;
75
}
76
77
static const MemoryRegionOps gicv3_its_trans_ops = {
78
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/intc/arm_gicv3_redist.c
81
+++ b/hw/intc/arm_gicv3_redist.c
82
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
83
"size %u\n", __func__, offset, size);
84
trace_gicv3_redist_badread(gicv3_redist_affid(cs), offset,
85
size, attrs.secure);
86
+ /* The spec requires that reserved registers are RAZ/WI;
87
+ * so use MEMTX_ERROR returns from leaf functions as a way to
88
+ * trigger the guest-error logging but don't return it to
89
+ * the caller, or we'll cause a spurious guest data abort.
90
+ */
91
+ r = MEMTX_OK;
92
+ *data = 0;
93
} else {
94
trace_gicv3_redist_read(gicv3_redist_affid(cs), offset, *data,
95
size, attrs.secure);
96
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
97
"size %u\n", __func__, offset, size);
98
trace_gicv3_redist_badwrite(gicv3_redist_affid(cs), offset, data,
99
size, attrs.secure);
100
+ /* The spec requires that reserved registers are RAZ/WI;
101
+ * so use MEMTX_ERROR returns from leaf functions as a way to
102
+ * trigger the guest-error logging but don't return it to
103
+ * the caller, or we'll cause a spurious guest data abort.
104
+ */
105
+ r = MEMTX_OK;
106
} else {
107
trace_gicv3_redist_write(gicv3_redist_affid(cs), offset, data,
108
size, attrs.secure);
109
--
110
2.7.4
111
112
diff view generated by jsdifflib
Deleted patch
1
The GICv2 specification says that reserved register addresses
2
must RAZ/WI; now that we implement external abort handling
3
for Arm CPUs this means we must return MEMTX_OK rather than
4
MEMTX_ERROR, to avoid generating a spurious guest data abort.
5
1
6
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1513183941-24300-3-git-send-email-peter.maydell@linaro.org
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
10
---
11
hw/intc/arm_gic.c | 5 +++--
12
1 file changed, 3 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/arm_gic.c
17
+++ b/hw/intc/arm_gic.c
18
@@ -XXX,XX +XXX,XX @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
19
default:
20
qemu_log_mask(LOG_GUEST_ERROR,
21
"gic_cpu_read: Bad offset %x\n", (int)offset);
22
- return MEMTX_ERROR;
23
+ *data = 0;
24
+ break;
25
}
26
return MEMTX_OK;
27
}
28
@@ -XXX,XX +XXX,XX @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
29
default:
30
qemu_log_mask(LOG_GUEST_ERROR,
31
"gic_cpu_write: Bad offset %x\n", (int)offset);
32
- return MEMTX_ERROR;
33
+ return MEMTX_OK;
34
}
35
gic_update(s);
36
return MEMTX_OK;
37
--
38
2.7.4
39
40
diff view generated by jsdifflib