1 | The following changes since commit 4cc10cae64c51e17844dc4358481c393d7bf1ed4: | 1 | target-arm queue: mostly aspeed changes from Cédric. |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-05-06 18:56:17 +0100) | 3 | thanks |
4 | -- PMM | ||
5 | |||
6 | The following changes since commit 85182c96de61f0b600bbe834d5a23e713162e892: | ||
7 | |||
8 | Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20190912a' into staging (2019-09-13 14:37:48 +0100) | ||
4 | 9 | ||
5 | are available in the Git repository at: | 10 | are available in the Git repository at: |
6 | 11 | ||
7 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210510 | 12 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190913 |
8 | 13 | ||
9 | for you to fetch changes up to 8f96812baa53005f32aece3e30b140826c20aa19: | 14 | for you to fetch changes up to 27a296fce9821e3608d537756cffa6e43a46df3b: |
10 | 15 | ||
11 | hw/arm/xlnx: Fix PHY address for xilinx-zynq-a9 (2021-05-10 13:24:09 +0100) | 16 | qemu-ga: Convert invocation documentation to rST (2019-09-13 16:05:01 +0100) |
12 | 17 | ||
13 | ---------------------------------------------------------------- | 18 | ---------------------------------------------------------------- |
14 | target-arm queue: | 19 | target-arm queue: |
15 | * docs: fix link in sbsa description | 20 | * aspeed: add a GPIO controller to the SoC |
16 | * linux-user/aarch64: Enable hwcap for RND, BTI, and MTE | 21 | * aspeed: Various refactorings |
17 | * target/arm: Fix tlbbits calculation in tlbi_aa64_vae2is_write() | 22 | * aspeed: Improve DMA controller modelling |
18 | * target/arm: Split neon and vfp translation to their own | 23 | * atomic_template: fix indentation in GEN_ATOMIC_HELPER |
19 | compilation units | 24 | * qemu-ga: Convert invocation documentation to rST |
20 | * target/arm: Make WFI a NOP for userspace emulators | ||
21 | * hw/sd/omap_mmc: Use device_cold_reset() instead of | ||
22 | device_legacy_reset() | ||
23 | * include: More fixes for 'extern "C"' block use | ||
24 | * hw/arm/imx25_pdk: Fix error message for invalid RAM size | ||
25 | * hw/arm/mps2-tz: Implement AN524 memory remapping via machine property | ||
26 | * hw/arm/xlnx: Fix PHY address for xilinx-zynq-a9 | ||
27 | 25 | ||
28 | ---------------------------------------------------------------- | 26 | ---------------------------------------------------------------- |
29 | Alex Bennée (1): | 27 | Christian Svensson (1): |
30 | docs: fix link in sbsa description | 28 | aspeed/smc: Calculate checksum on normal DMA |
31 | 29 | ||
32 | Guenter Roeck (1): | 30 | Cédric Le Goater (7): |
33 | hw/arm/xlnx: Fix PHY address for xilinx-zynq-a9 | 31 | aspeed: Remove unused SoC definitions |
32 | aspeed: Use consistent typenames | ||
33 | aspeed/smc: Add support for DMAs | ||
34 | aspeed/smc: Add DMA calibration settings | ||
35 | aspeed/smc: Inject errors in DMA checksum | ||
36 | aspeed/scu: Introduce per-SoC SCU types | ||
37 | aspeed/scu: Introduce a aspeed_scu_get_apb_freq() routine | ||
34 | 38 | ||
35 | Peter Maydell (22): | 39 | Emilio G. Cota (1): |
36 | target/arm: Fix tlbbits calculation in tlbi_aa64_vae2is_write() | 40 | atomic_template: fix indentation in GEN_ATOMIC_HELPER |
37 | target/arm: Move constant expanders to translate.h | ||
38 | target/arm: Share unallocated_encoding() and gen_exception_insn() | ||
39 | target/arm: Make functions used by m-nocp global | ||
40 | target/arm: Split m-nocp trans functions into their own file | ||
41 | target/arm: Move gen_aa32 functions to translate-a32.h | ||
42 | target/arm: Move vfp_{load, store}_reg{32, 64} to translate-vfp.c.inc | ||
43 | target/arm: Make functions used by translate-vfp global | ||
44 | target/arm: Make translate-vfp.c.inc its own compilation unit | ||
45 | target/arm: Move vfp_reg_ptr() to translate-neon.c.inc | ||
46 | target/arm: Delete unused typedef | ||
47 | target/arm: Move NeonGenThreeOpEnvFn typedef to translate.h | ||
48 | target/arm: Make functions used by translate-neon global | ||
49 | target/arm: Make translate-neon.c.inc its own compilation unit | ||
50 | target/arm: Make WFI a NOP for userspace emulators | ||
51 | hw/sd/omap_mmc: Use device_cold_reset() instead of device_legacy_reset() | ||
52 | osdep: Make os-win32.h and os-posix.h handle 'extern "C"' themselves | ||
53 | include/qemu/bswap.h: Handle being included outside extern "C" block | ||
54 | include/disas/dis-asm.h: Handle being included outside 'extern "C"' | ||
55 | hw/misc/mps2-scc: Add "QEMU interface" comment | ||
56 | hw/misc/mps2-scc: Support using CFG0 bit 0 for remapping | ||
57 | hw/arm/mps2-tz: Implement AN524 memory remapping via machine property | ||
58 | 41 | ||
59 | Philippe Mathieu-Daudé (1): | 42 | Peter Maydell (1): |
60 | hw/arm/imx25_pdk: Fix error message for invalid RAM size | 43 | qemu-ga: Convert invocation documentation to rST |
61 | 44 | ||
62 | Richard Henderson (1): | 45 | Rashmica Gupta (2): |
63 | linux-user/aarch64: Enable hwcap for RND, BTI, and MTE | 46 | hw/gpio: Add basic Aspeed GPIO model for AST2400 and AST2500 |
47 | aspeed: add a GPIO controller to the SoC | ||
64 | 48 | ||
65 | docs/system/arm/mps2.rst | 10 + | 49 | Makefile | 24 +- |
66 | docs/system/arm/sbsa.rst | 2 +- | 50 | hw/gpio/Makefile.objs | 1 + |
67 | include/disas/dis-asm.h | 12 +- | 51 | accel/tcg/atomic_template.h | 2 +- |
68 | include/hw/misc/mps2-scc.h | 21 ++ | 52 | include/hw/arm/aspeed_soc.h | 4 +- |
69 | include/qemu/bswap.h | 26 ++- | 53 | include/hw/gpio/aspeed_gpio.h | 100 +++++ |
70 | include/qemu/osdep.h | 8 +- | 54 | include/hw/misc/aspeed_scu.h | 21 +- |
71 | include/sysemu/os-posix.h | 8 + | 55 | include/hw/ssi/aspeed_smc.h | 7 + |
72 | include/sysemu/os-win32.h | 8 + | 56 | hw/arm/aspeed.c | 2 + |
73 | target/arm/translate-a32.h | 144 +++++++++++++ | 57 | hw/arm/aspeed_soc.c | 63 ++- |
74 | target/arm/translate-a64.h | 2 - | 58 | hw/gpio/aspeed_gpio.c | 884 ++++++++++++++++++++++++++++++++++++++++++ |
75 | target/arm/translate.h | 29 +++ | 59 | hw/misc/aspeed_scu.c | 102 ++--- |
76 | hw/arm/imx25_pdk.c | 5 +- | 60 | hw/ssi/aspeed_smc.c | 335 +++++++++++++++- |
77 | hw/arm/mps2-tz.c | 108 +++++++++- | 61 | hw/timer/aspeed_timer.c | 3 +- |
78 | hw/arm/xilinx_zynq.c | 2 +- | 62 | MAINTAINERS | 2 +- |
79 | hw/misc/mps2-scc.c | 13 +- | 63 | docs/conf.py | 18 +- |
80 | hw/sd/omap_mmc.c | 2 +- | 64 | docs/interop/conf.py | 7 + |
81 | linux-user/elfload.c | 13 ++ | 65 | docs/interop/index.rst | 1 + |
82 | target/arm/helper.c | 2 +- | 66 | docs/interop/qemu-ga.rst | 133 +++++++ |
83 | target/arm/op_helper.c | 12 ++ | 67 | qemu-doc.texi | 5 - |
84 | target/arm/translate-a64.c | 15 -- | 68 | qemu-ga.texi | 137 ------- |
85 | target/arm/translate-m-nocp.c | 221 ++++++++++++++++++++ | 69 | 20 files changed, 1585 insertions(+), 266 deletions(-) |
86 | .../arm/{translate-neon.c.inc => translate-neon.c} | 19 +- | 70 | create mode 100644 include/hw/gpio/aspeed_gpio.h |
87 | .../arm/{translate-vfp.c.inc => translate-vfp.c} | 230 +++------------------ | 71 | create mode 100644 hw/gpio/aspeed_gpio.c |
88 | target/arm/translate.c | 200 ++++-------------- | 72 | create mode 100644 docs/interop/qemu-ga.rst |
89 | disas/arm-a64.cc | 2 - | 73 | delete mode 100644 qemu-ga.texi |
90 | disas/nanomips.cpp | 2 - | ||
91 | target/arm/meson.build | 15 +- | ||
92 | 27 files changed, 718 insertions(+), 413 deletions(-) | ||
93 | create mode 100644 target/arm/translate-a32.h | ||
94 | create mode 100644 target/arm/translate-m-nocp.c | ||
95 | rename target/arm/{translate-neon.c.inc => translate-neon.c} (99%) | ||
96 | rename target/arm/{translate-vfp.c.inc => translate-vfp.c} (94%) | ||
97 | 74 | diff view generated by jsdifflib |
1 | Currently the trans functions for m-nocp.decode all live in | 1 | From: Rashmica Gupta <rashmica.g@gmail.com> |
---|---|---|---|
2 | translate-vfp.inc.c; move them out into their own translation unit, | ||
3 | translate-m-nocp.c. | ||
4 | 2 | ||
5 | The trans_* functions here are pure code motion with no changes. | 3 | GPIO pins are arranged in groups of 8 pins labeled A,B,..,Y,Z,AA,AB,AC. |
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. | ||
6 | 8 | ||
9 | These registers operate on a per pin level where each bit in the register | ||
10 | corresponds to a pin, except for the command source registers. The command | ||
11 | source registers operate on a per group level where bits 24, 16, 8 and 0 | ||
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> | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 36 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Message-id: 20210430132740.10391-5-peter.maydell@linaro.org | ||
10 | --- | 37 | --- |
11 | target/arm/translate-a32.h | 3 + | 38 | hw/gpio/Makefile.objs | 1 + |
12 | target/arm/translate-m-nocp.c | 221 +++++++++++++++++++++++++++++++++ | 39 | include/hw/gpio/aspeed_gpio.h | 100 ++++ |
13 | target/arm/translate.c | 1 - | 40 | hw/gpio/aspeed_gpio.c | 884 ++++++++++++++++++++++++++++++++++ |
14 | target/arm/translate-vfp.c.inc | 196 ----------------------------- | 41 | 3 files changed, 985 insertions(+) |
15 | target/arm/meson.build | 3 +- | 42 | create mode 100644 include/hw/gpio/aspeed_gpio.h |
16 | 5 files changed, 226 insertions(+), 198 deletions(-) | 43 | create mode 100644 hw/gpio/aspeed_gpio.c |
17 | create mode 100644 target/arm/translate-m-nocp.c | ||
18 | 44 | ||
19 | diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h | 45 | diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs |
20 | index XXXXXXX..XXXXXXX 100644 | 46 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/target/arm/translate-a32.h | 47 | --- a/hw/gpio/Makefile.objs |
22 | +++ b/target/arm/translate-a32.h | 48 | +++ b/hw/gpio/Makefile.objs |
23 | @@ -XXX,XX +XXX,XX @@ | 49 | @@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_gpio.o |
24 | #ifndef TARGET_ARM_TRANSLATE_A64_H | 50 | obj-$(CONFIG_IMX) += imx_gpio.o |
25 | #define TARGET_ARM_TRANSLATE_A64_H | 51 | obj-$(CONFIG_RASPI) += bcm2835_gpio.o |
26 | 52 | obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o | |
27 | +/* Prototypes for autogenerated disassembler functions */ | 53 | +obj-$(CONFIG_ASPEED_SOC) += aspeed_gpio.o |
28 | +bool disas_m_nocp(DisasContext *dc, uint32_t insn); | 54 | diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h |
29 | + | ||
30 | void load_reg_var(DisasContext *s, TCGv_i32 var, int reg); | ||
31 | void arm_gen_condlabel(DisasContext *s); | ||
32 | bool vfp_access_check(DisasContext *s); | ||
33 | diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c | ||
34 | new file mode 100644 | 55 | new file mode 100644 |
35 | index XXXXXXX..XXXXXXX | 56 | index XXXXXXX..XXXXXXX |
36 | --- /dev/null | 57 | --- /dev/null |
37 | +++ b/target/arm/translate-m-nocp.c | 58 | +++ b/include/hw/gpio/aspeed_gpio.h |
38 | @@ -XXX,XX +XXX,XX @@ | 59 | @@ -XXX,XX +XXX,XX @@ |
39 | +/* | 60 | +/* |
40 | + * ARM translation: M-profile NOCP special-case instructions | 61 | + * ASPEED GPIO Controller |
41 | + * | 62 | + * |
42 | + * Copyright (c) 2020 Linaro, Ltd. | 63 | + * Copyright (C) 2017-2018 IBM Corp. |
43 | + * | 64 | + * |
44 | + * This library is free software; you can redistribute it and/or | 65 | + * This code is licensed under the GPL version 2 or later. See |
45 | + * modify it under the terms of the GNU Lesser General Public | 66 | + * the COPYING file in the top-level directory. |
46 | + * License as published by the Free Software Foundation; either | 67 | + */ |
47 | + * version 2.1 of the License, or (at your option) any later version. | 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 | ||
48 | + * | 168 | + * |
49 | + * This library is distributed in the hope that it will be useful, | 169 | + * Copyright (C) 2017-2019 IBM Corp. |
50 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
51 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
52 | + * Lesser General Public License for more details. | ||
53 | + * | 170 | + * |
54 | + * You should have received a copy of the GNU Lesser General Public | 171 | + * SPDX-License-Identifier: GPL-2.0-or-later |
55 | + * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
56 | + */ | 172 | + */ |
57 | + | 173 | + |
174 | +#include <assert.h> | ||
175 | + | ||
58 | +#include "qemu/osdep.h" | 176 | +#include "qemu/osdep.h" |
59 | +#include "tcg/tcg-op.h" | 177 | +#include "qemu/host-utils.h" |
60 | +#include "translate.h" | 178 | +#include "qemu/log.h" |
61 | +#include "translate-a32.h" | 179 | +#include "hw/gpio/aspeed_gpio.h" |
62 | + | 180 | +#include "include/hw/misc/aspeed_scu.h" |
63 | +#include "decode-m-nocp.c.inc" | 181 | +#include "qapi/error.h" |
64 | + | 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 */ | ||
65 | +/* | 200 | +/* |
66 | + * Decode VLLDM and VLSTM are nonstandard because: | 201 | + * For each set of gpios there are three sensitivity registers that control |
67 | + * * if there is no FPU then these insns must NOP in | 202 | + * the interrupt trigger mode. |
68 | + * Secure state and UNDEF in Nonsecure state | 203 | + * |
69 | + * * if there is an FPU then these insns do not have | 204 | + * | 2 | 1 | 0 | trigger mode |
70 | + * the usual behaviour that vfp_access_check() provides of | 205 | + * ----------------------------- |
71 | + * being controlled by CPACR/NSACR enable bits or the | 206 | + * | 0 | 0 | 0 | falling-edge |
72 | + * lazy-stacking logic. | 207 | + * | 0 | 0 | 1 | rising-edge |
208 | + * | 0 | 1 | 0 | level-low | ||
209 | + * | 0 | 1 | 1 | level-high | ||
210 | + * | 1 | X | X | dual-edge | ||
73 | + */ | 211 | + */ |
74 | +static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a) | 212 | +#define ASPEED_FALLING_EDGE 0 |
75 | +{ | 213 | +#define ASPEED_RISING_EDGE 1 |
76 | + TCGv_i32 fptr; | 214 | +#define ASPEED_LEVEL_LOW 2 |
77 | + | 215 | +#define ASPEED_LEVEL_HIGH 3 |
78 | + if (!arm_dc_feature(s, ARM_FEATURE_M) || | 216 | +#define ASPEED_DUAL_EDGE 4 |
79 | + !arm_dc_feature(s, ARM_FEATURE_V8)) { | 217 | + |
80 | + return false; | 218 | +/* GPIO Register Address Offsets */ |
81 | + } | 219 | +#define GPIO_ABCD_DATA_VALUE (0x000 >> 2) |
82 | + | 220 | +#define GPIO_ABCD_DIRECTION (0x004 >> 2) |
83 | + if (a->op) { | 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: | ||
84 | + /* | 727 | + /* |
85 | + * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not | 728 | + * where data is the value attempted to be written to the pin: |
86 | + * to take the IMPDEF option to make memory accesses to the stack | 729 | + * pin type | input mask | output mask | expected value |
87 | + * slots that correspond to the D16-D31 registers (discarding | 730 | + * ------------------------------------------------------------ |
88 | + * read data and writing UNKNOWN values), so for us the T2 | 731 | + * bidirectional | 1 | 1 | data |
89 | + * encoding behaves identically to the T1 encoding. | 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; | ||
90 | + */ | 738 | + */ |
91 | + if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) { | 739 | + data = (data | ~props->input) & props->output; |
92 | + return false; | 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; | ||
93 | + } | 763 | + } |
94 | + } else { | 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: | ||
95 | + /* | 788 | + /* |
96 | + * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs. | 789 | + * feeds into interrupt generation |
97 | + * This is currently architecturally impossible, but we add the | 790 | + * 0: read from data value reg will be updated |
98 | + * check to stay in line with the pseudocode. Note that we must | 791 | + * 1: read from data value reg will not be updated |
99 | + * emit code for the UNDEF so it takes precedence over the NOCP. | ||
100 | + */ | 792 | + */ |
101 | + if (dc_isar_feature(aa32_simd_r32, s)) { | 793 | + set->input_mask = data & props->input; |
102 | + unallocated_encoding(s); | 794 | + break; |
103 | + return true; | 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 | + } | ||
104 | + } | 816 | + } |
105 | + } | 817 | + } |
106 | + | 818 | + return -1; |
107 | + /* | 819 | +} |
108 | + * If not secure, UNDEF. We must emit code for this | 820 | + |
109 | + * rather than returning false so that this takes | 821 | +static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name, |
110 | + * precedence over the m-nocp.decode NOCP fallback. | 822 | + void *opaque, Error **errp) |
111 | + */ | 823 | +{ |
112 | + if (!s->v8m_secure) { | 824 | + int pin = 0xfff; |
113 | + unallocated_encoding(s); | 825 | + bool level = true; |
114 | + return true; | 826 | + char group[3]; |
115 | + } | 827 | + AspeedGPIOState *s = ASPEED_GPIO(obj); |
116 | + /* If no fpu, NOP. */ | 828 | + int set_idx, group_idx = 0; |
117 | + if (!dc_isar_feature(aa32_vfp, s)) { | 829 | + |
118 | + return true; | 830 | + if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) { |
119 | + } | 831 | + error_setg(errp, "%s: error reading %s", __func__, name); |
120 | + | 832 | + return; |
121 | + fptr = load_reg(s, a->rn); | 833 | + } |
122 | + if (a->l) { | 834 | + set_idx = get_set_idx(s, group, &group_idx); |
123 | + gen_helper_v7m_vlldm(cpu_env, fptr); | 835 | + if (set_idx == -1) { |
124 | + } else { | 836 | + error_setg(errp, "%s: invalid group %s", __func__, group); |
125 | + gen_helper_v7m_vlstm(cpu_env, fptr); | 837 | + return; |
126 | + } | 838 | + } |
127 | + tcg_temp_free_i32(fptr); | 839 | + pin = pin + group_idx * GPIOS_PER_GROUP; |
128 | + | 840 | + level = aspeed_gpio_get_pin_level(s, set_idx, pin); |
129 | + /* End the TB, because we have updated FP control bits */ | 841 | + visit_type_bool(v, name, &level, errp); |
130 | + s->base.is_jmp = DISAS_UPDATE_EXIT; | 842 | +} |
131 | + return true; | 843 | + |
132 | +} | 844 | +static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name, |
133 | + | 845 | + void *opaque, Error **errp) |
134 | +static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a) | 846 | +{ |
135 | +{ | 847 | + Error *local_err = NULL; |
136 | + int btmreg, topreg; | 848 | + bool level; |
137 | + TCGv_i64 zero; | 849 | + int pin = 0xfff; |
138 | + TCGv_i32 aspen, sfpa; | 850 | + char group[3]; |
139 | + | 851 | + AspeedGPIOState *s = ASPEED_GPIO(obj); |
140 | + if (!dc_isar_feature(aa32_m_sec_state, s)) { | 852 | + int set_idx, group_idx = 0; |
141 | + /* Before v8.1M, fall through in decode to NOCP check */ | 853 | + |
142 | + return false; | 854 | + visit_type_bool(v, name, &level, &local_err); |
143 | + } | 855 | + if (local_err) { |
144 | + | 856 | + error_propagate(errp, local_err); |
145 | + /* Explicitly UNDEF because this takes precedence over NOCP */ | 857 | + return; |
146 | + if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) { | 858 | + } |
147 | + unallocated_encoding(s); | 859 | + if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) { |
148 | + return true; | 860 | + error_setg(errp, "%s: error reading %s", __func__, name); |
149 | + } | 861 | + return; |
150 | + | 862 | + } |
151 | + if (!dc_isar_feature(aa32_vfp_simd, s)) { | 863 | + set_idx = get_set_idx(s, group, &group_idx); |
152 | + /* NOP if we have neither FP nor MVE */ | 864 | + if (set_idx == -1) { |
153 | + return true; | 865 | + error_setg(errp, "%s: invalid group %s", __func__, group); |
154 | + } | 866 | + return; |
155 | + | 867 | + } |
156 | + /* | 868 | + pin = pin + group_idx * GPIOS_PER_GROUP; |
157 | + * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no | 869 | + aspeed_gpio_set_pin_level(s, set_idx, pin, level); |
158 | + * active floating point context so we must NOP (without doing | 870 | +} |
159 | + * any lazy state preservation or the NOCP check). | 871 | + |
160 | + */ | 872 | +/****************** Setup functions ******************/ |
161 | + aspen = load_cpu_field(v7m.fpccr[M_REG_S]); | 873 | +static const GPIOSetProperties ast2400_set_props[] = { |
162 | + sfpa = load_cpu_field(v7m.control[M_REG_S]); | 874 | + [0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} }, |
163 | + tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK); | 875 | + [1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} }, |
164 | + tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK); | 876 | + [2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} }, |
165 | + tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK); | 877 | + [3] = {0xffffffff, 0xffffffff, {"M", "N", "O", "P"} }, |
166 | + tcg_gen_or_i32(sfpa, sfpa, aspen); | 878 | + [4] = {0xffffffff, 0xffffffff, {"Q", "R", "S", "T"} }, |
167 | + arm_gen_condlabel(s); | 879 | + [5] = {0xffffffff, 0x0000ffff, {"U", "V", "W", "X"} }, |
168 | + tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel); | 880 | + [6] = {0x0000000f, 0x0fffff0f, {"Y", "Z", "AA", "AB"} }, |
169 | + | 881 | +}; |
170 | + if (s->fp_excp_el != 0) { | 882 | + |
171 | + gen_exception_insn(s, s->pc_curr, EXCP_NOCP, | 883 | +static const GPIOSetProperties ast2500_set_props[] = { |
172 | + syn_uncategorized(), s->fp_excp_el); | 884 | + [0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} }, |
173 | + return true; | 885 | + [1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} }, |
174 | + } | 886 | + [2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} }, |
175 | + | 887 | + [3] = {0xffffffff, 0xffffffff, {"M", "N", "O", "P"} }, |
176 | + topreg = a->vd + a->imm - 1; | 888 | + [4] = {0xffffffff, 0xffffffff, {"Q", "R", "S", "T"} }, |
177 | + btmreg = a->vd; | 889 | + [5] = {0xffffffff, 0x0000ffff, {"U", "V", "W", "X"} }, |
178 | + | 890 | + [6] = {0xffffff0f, 0x0fffff0f, {"Y", "Z", "AA", "AB"} }, |
179 | + /* Convert to Sreg numbers if the insn specified in Dregs */ | 891 | + [7] = {0x000000ff, 0x000000ff, {"AC"} }, |
180 | + if (a->size == 3) { | 892 | +}; |
181 | + topreg = topreg * 2 + 1; | 893 | + |
182 | + btmreg *= 2; | 894 | +static const MemoryRegionOps aspeed_gpio_ops = { |
183 | + } | 895 | + .read = aspeed_gpio_read, |
184 | + | 896 | + .write = aspeed_gpio_write, |
185 | + if (topreg > 63 || (topreg > 31 && !(topreg & 1))) { | 897 | + .endianness = DEVICE_LITTLE_ENDIAN, |
186 | + /* UNPREDICTABLE: we choose to undef */ | 898 | + .valid.min_access_size = 4, |
187 | + unallocated_encoding(s); | 899 | + .valid.max_access_size = 4, |
188 | + return true; | 900 | +}; |
189 | + } | 901 | + |
190 | + | 902 | +static void aspeed_gpio_reset(DeviceState *dev) |
191 | + /* Silently ignore requests to clear D16-D31 if they don't exist */ | 903 | +{ |
192 | + if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) { | 904 | + AspeedGPIOState *s = ASPEED_GPIO(dev); |
193 | + topreg = 31; | 905 | + |
194 | + } | 906 | + /* TODO: respect the reset tolerance registers */ |
195 | + | 907 | + memset(s->sets, 0, sizeof(s->sets)); |
196 | + if (!vfp_access_check(s)) { | 908 | +} |
197 | + return true; | 909 | + |
198 | + } | 910 | +static void aspeed_gpio_realize(DeviceState *dev, Error **errp) |
199 | + | 911 | +{ |
200 | + /* Zero the Sregs from btmreg to topreg inclusive. */ | 912 | + AspeedGPIOState *s = ASPEED_GPIO(dev); |
201 | + zero = tcg_const_i64(0); | 913 | + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); |
202 | + if (btmreg & 1) { | 914 | + AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s); |
203 | + write_neon_element64(zero, btmreg >> 1, 1, MO_32); | 915 | + int pin; |
204 | + btmreg++; | 916 | + |
205 | + } | 917 | + /* Interrupt parent line */ |
206 | + for (; btmreg + 1 <= topreg; btmreg += 2) { | 918 | + sysbus_init_irq(sbd, &s->irq); |
207 | + write_neon_element64(zero, btmreg >> 1, 0, MO_64); | 919 | + |
208 | + } | 920 | + /* Individual GPIOs */ |
209 | + if (btmreg == topreg) { | 921 | + for (pin = 0; pin < agc->nr_gpio_pins; pin++) { |
210 | + write_neon_element64(zero, btmreg >> 1, 0, MO_32); | 922 | + sysbus_init_irq(sbd, &s->gpios[pin]); |
211 | + btmreg++; | 923 | + } |
212 | + } | 924 | + |
213 | + assert(btmreg == topreg + 1); | 925 | + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s, |
214 | + /* TODO: when MVE is implemented, zero VPR here */ | 926 | + TYPE_ASPEED_GPIO, GPIO_3_6V_MEM_SIZE); |
215 | + return true; | 927 | + |
216 | +} | 928 | + sysbus_init_mmio(sbd, &s->iomem); |
217 | + | 929 | +} |
218 | +static bool trans_NOCP(DisasContext *s, arg_nocp *a) | 930 | + |
219 | +{ | 931 | +static void aspeed_gpio_init(Object *obj) |
220 | + /* | 932 | +{ |
221 | + * Handle M-profile early check for disabled coprocessor: | 933 | + AspeedGPIOState *s = ASPEED_GPIO(obj); |
222 | + * all we need to do here is emit the NOCP exception if | 934 | + AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s); |
223 | + * the coprocessor is disabled. Otherwise we return false | 935 | + int pin; |
224 | + * and the real VFP/etc decode will handle the insn. | 936 | + |
225 | + */ | 937 | + for (pin = 0; pin < agc->nr_gpio_pins; pin++) { |
226 | + assert(arm_dc_feature(s, ARM_FEATURE_M)); | 938 | + char *name; |
227 | + | 939 | + int set_idx = pin / GPIOS_PER_SET; |
228 | + if (a->cp == 11) { | 940 | + int pin_idx = aspeed_adjust_pin(s, pin) - (set_idx * GPIOS_PER_SET); |
229 | + a->cp = 10; | 941 | + int group_idx = pin_idx >> GPIO_GROUP_SHIFT; |
230 | + } | 942 | + const GPIOSetProperties *props = &agc->props[set_idx]; |
231 | + if (arm_dc_feature(s, ARM_FEATURE_V8_1M) && | 943 | + |
232 | + (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) { | 944 | + name = g_strdup_printf("gpio%s%d", props->group_label[group_idx], |
233 | + /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */ | 945 | + pin_idx % GPIOS_PER_GROUP); |
234 | + a->cp = 10; | 946 | + object_property_add(obj, name, "bool", aspeed_gpio_get_pin, |
235 | + } | 947 | + aspeed_gpio_set_pin, NULL, NULL, NULL); |
236 | + | 948 | + } |
237 | + if (a->cp != 10) { | 949 | +} |
238 | + gen_exception_insn(s, s->pc_curr, EXCP_NOCP, | 950 | + |
239 | + syn_uncategorized(), default_exception_el(s)); | 951 | +static const VMStateDescription vmstate_gpio_regs = { |
240 | + return true; | 952 | + .name = TYPE_ASPEED_GPIO"/regs", |
241 | + } | 953 | + .version_id = 1, |
242 | + | 954 | + .minimum_version_id = 1, |
243 | + if (s->fp_excp_el != 0) { | 955 | + .fields = (VMStateField[]) { |
244 | + gen_exception_insn(s, s->pc_curr, EXCP_NOCP, | 956 | + VMSTATE_UINT32(data_value, GPIOSets), |
245 | + syn_uncategorized(), s->fp_excp_el); | 957 | + VMSTATE_UINT32(data_read, GPIOSets), |
246 | + return true; | 958 | + VMSTATE_UINT32(direction, GPIOSets), |
247 | + } | 959 | + VMSTATE_UINT32(int_enable, GPIOSets), |
248 | + | 960 | + VMSTATE_UINT32(int_sens_0, GPIOSets), |
249 | + return false; | 961 | + VMSTATE_UINT32(int_sens_1, GPIOSets), |
250 | +} | 962 | + VMSTATE_UINT32(int_sens_2, GPIOSets), |
251 | + | 963 | + VMSTATE_UINT32(int_status, GPIOSets), |
252 | +static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a) | 964 | + VMSTATE_UINT32(reset_tol, GPIOSets), |
253 | +{ | 965 | + VMSTATE_UINT32(cmd_source_0, GPIOSets), |
254 | + /* This range needs a coprocessor check for v8.1M and later only */ | 966 | + VMSTATE_UINT32(cmd_source_1, GPIOSets), |
255 | + if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) { | 967 | + VMSTATE_UINT32(debounce_1, GPIOSets), |
256 | + return false; | 968 | + VMSTATE_UINT32(debounce_2, GPIOSets), |
257 | + } | 969 | + VMSTATE_UINT32(input_mask, GPIOSets), |
258 | + return trans_NOCP(s, a); | 970 | + VMSTATE_END_OF_LIST(), |
259 | +} | 971 | + } |
260 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 972 | +}; |
261 | index XXXXXXX..XXXXXXX 100644 | 973 | + |
262 | --- a/target/arm/translate.c | 974 | +static const VMStateDescription vmstate_aspeed_gpio = { |
263 | +++ b/target/arm/translate.c | 975 | + .name = TYPE_ASPEED_GPIO, |
264 | @@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg) | 976 | + .version_id = 1, |
265 | #define ARM_CP_RW_BIT (1 << 20) | 977 | + .minimum_version_id = 1, |
266 | 978 | + .fields = (VMStateField[]) { | |
267 | /* Include the VFP and Neon decoders */ | 979 | + VMSTATE_STRUCT_ARRAY(sets, AspeedGPIOState, ASPEED_GPIO_MAX_NR_SETS, |
268 | -#include "decode-m-nocp.c.inc" | 980 | + 1, vmstate_gpio_regs, GPIOSets), |
269 | #include "translate-vfp.c.inc" | 981 | + VMSTATE_UINT32_ARRAY(debounce_regs, AspeedGPIOState, |
270 | #include "translate-neon.c.inc" | 982 | + ASPEED_GPIO_NR_DEBOUNCE_REGS), |
271 | 983 | + VMSTATE_END_OF_LIST(), | |
272 | diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc | 984 | + } |
273 | index XXXXXXX..XXXXXXX 100644 | 985 | +}; |
274 | --- a/target/arm/translate-vfp.c.inc | 986 | + |
275 | +++ b/target/arm/translate-vfp.c.inc | 987 | +static void aspeed_gpio_class_init(ObjectClass *klass, void *data) |
276 | @@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a) | 988 | +{ |
277 | return true; | 989 | + DeviceClass *dc = DEVICE_CLASS(klass); |
278 | } | 990 | + |
279 | 991 | + dc->realize = aspeed_gpio_realize; | |
280 | -/* | 992 | + dc->reset = aspeed_gpio_reset; |
281 | - * Decode VLLDM and VLSTM are nonstandard because: | 993 | + dc->desc = "Aspeed GPIO Controller"; |
282 | - * * if there is no FPU then these insns must NOP in | 994 | + dc->vmsd = &vmstate_aspeed_gpio; |
283 | - * Secure state and UNDEF in Nonsecure state | 995 | +} |
284 | - * * if there is an FPU then these insns do not have | 996 | + |
285 | - * the usual behaviour that vfp_access_check() provides of | 997 | +static void aspeed_gpio_ast2400_class_init(ObjectClass *klass, void *data) |
286 | - * being controlled by CPACR/NSACR enable bits or the | 998 | +{ |
287 | - * lazy-stacking logic. | 999 | + AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass); |
288 | - */ | 1000 | + |
289 | -static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a) | 1001 | + agc->props = ast2400_set_props; |
290 | -{ | 1002 | + agc->nr_gpio_pins = 216; |
291 | - TCGv_i32 fptr; | 1003 | + agc->nr_gpio_sets = 7; |
292 | - | 1004 | + agc->gap = 196; |
293 | - if (!arm_dc_feature(s, ARM_FEATURE_M) || | 1005 | + agc->reg_table = aspeed_3_6v_gpios; |
294 | - !arm_dc_feature(s, ARM_FEATURE_V8)) { | 1006 | +} |
295 | - return false; | 1007 | + |
296 | - } | 1008 | +static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data) |
297 | - | 1009 | +{ |
298 | - if (a->op) { | 1010 | + AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass); |
299 | - /* | 1011 | + |
300 | - * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not | 1012 | + agc->props = ast2500_set_props; |
301 | - * to take the IMPDEF option to make memory accesses to the stack | 1013 | + agc->nr_gpio_pins = 228; |
302 | - * slots that correspond to the D16-D31 registers (discarding | 1014 | + agc->nr_gpio_sets = 8; |
303 | - * read data and writing UNKNOWN values), so for us the T2 | 1015 | + agc->gap = 220; |
304 | - * encoding behaves identically to the T1 encoding. | 1016 | + agc->reg_table = aspeed_3_6v_gpios; |
305 | - */ | 1017 | +} |
306 | - if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) { | 1018 | + |
307 | - return false; | 1019 | +static const TypeInfo aspeed_gpio_info = { |
308 | - } | 1020 | + .name = TYPE_ASPEED_GPIO, |
309 | - } else { | 1021 | + .parent = TYPE_SYS_BUS_DEVICE, |
310 | - /* | 1022 | + .instance_size = sizeof(AspeedGPIOState), |
311 | - * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs. | 1023 | + .class_size = sizeof(AspeedGPIOClass), |
312 | - * This is currently architecturally impossible, but we add the | 1024 | + .class_init = aspeed_gpio_class_init, |
313 | - * check to stay in line with the pseudocode. Note that we must | 1025 | + .abstract = true, |
314 | - * emit code for the UNDEF so it takes precedence over the NOCP. | 1026 | +}; |
315 | - */ | 1027 | + |
316 | - if (dc_isar_feature(aa32_simd_r32, s)) { | 1028 | +static const TypeInfo aspeed_gpio_ast2400_info = { |
317 | - unallocated_encoding(s); | 1029 | + .name = TYPE_ASPEED_GPIO "-ast2400", |
318 | - return true; | 1030 | + .parent = TYPE_ASPEED_GPIO, |
319 | - } | 1031 | + .class_init = aspeed_gpio_ast2400_class_init, |
320 | - } | 1032 | + .instance_init = aspeed_gpio_init, |
321 | - | 1033 | +}; |
322 | - /* | 1034 | + |
323 | - * If not secure, UNDEF. We must emit code for this | 1035 | +static const TypeInfo aspeed_gpio_ast2500_info = { |
324 | - * rather than returning false so that this takes | 1036 | + .name = TYPE_ASPEED_GPIO "-ast2500", |
325 | - * precedence over the m-nocp.decode NOCP fallback. | 1037 | + .parent = TYPE_ASPEED_GPIO, |
326 | - */ | 1038 | + .class_init = aspeed_gpio_2500_class_init, |
327 | - if (!s->v8m_secure) { | 1039 | + .instance_init = aspeed_gpio_init, |
328 | - unallocated_encoding(s); | 1040 | +}; |
329 | - return true; | 1041 | + |
330 | - } | 1042 | +static void aspeed_gpio_register_types(void) |
331 | - /* If no fpu, NOP. */ | 1043 | +{ |
332 | - if (!dc_isar_feature(aa32_vfp, s)) { | 1044 | + type_register_static(&aspeed_gpio_info); |
333 | - return true; | 1045 | + type_register_static(&aspeed_gpio_ast2400_info); |
334 | - } | 1046 | + type_register_static(&aspeed_gpio_ast2500_info); |
335 | - | 1047 | +} |
336 | - fptr = load_reg(s, a->rn); | 1048 | + |
337 | - if (a->l) { | 1049 | +type_init(aspeed_gpio_register_types); |
338 | - gen_helper_v7m_vlldm(cpu_env, fptr); | ||
339 | - } else { | ||
340 | - gen_helper_v7m_vlstm(cpu_env, fptr); | ||
341 | - } | ||
342 | - tcg_temp_free_i32(fptr); | ||
343 | - | ||
344 | - /* End the TB, because we have updated FP control bits */ | ||
345 | - s->base.is_jmp = DISAS_UPDATE_EXIT; | ||
346 | - return true; | ||
347 | -} | ||
348 | - | ||
349 | -static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a) | ||
350 | -{ | ||
351 | - int btmreg, topreg; | ||
352 | - TCGv_i64 zero; | ||
353 | - TCGv_i32 aspen, sfpa; | ||
354 | - | ||
355 | - if (!dc_isar_feature(aa32_m_sec_state, s)) { | ||
356 | - /* Before v8.1M, fall through in decode to NOCP check */ | ||
357 | - return false; | ||
358 | - } | ||
359 | - | ||
360 | - /* Explicitly UNDEF because this takes precedence over NOCP */ | ||
361 | - if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) { | ||
362 | - unallocated_encoding(s); | ||
363 | - return true; | ||
364 | - } | ||
365 | - | ||
366 | - if (!dc_isar_feature(aa32_vfp_simd, s)) { | ||
367 | - /* NOP if we have neither FP nor MVE */ | ||
368 | - return true; | ||
369 | - } | ||
370 | - | ||
371 | - /* | ||
372 | - * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no | ||
373 | - * active floating point context so we must NOP (without doing | ||
374 | - * any lazy state preservation or the NOCP check). | ||
375 | - */ | ||
376 | - aspen = load_cpu_field(v7m.fpccr[M_REG_S]); | ||
377 | - sfpa = load_cpu_field(v7m.control[M_REG_S]); | ||
378 | - tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK); | ||
379 | - tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK); | ||
380 | - tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK); | ||
381 | - tcg_gen_or_i32(sfpa, sfpa, aspen); | ||
382 | - arm_gen_condlabel(s); | ||
383 | - tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel); | ||
384 | - | ||
385 | - if (s->fp_excp_el != 0) { | ||
386 | - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, | ||
387 | - syn_uncategorized(), s->fp_excp_el); | ||
388 | - return true; | ||
389 | - } | ||
390 | - | ||
391 | - topreg = a->vd + a->imm - 1; | ||
392 | - btmreg = a->vd; | ||
393 | - | ||
394 | - /* Convert to Sreg numbers if the insn specified in Dregs */ | ||
395 | - if (a->size == 3) { | ||
396 | - topreg = topreg * 2 + 1; | ||
397 | - btmreg *= 2; | ||
398 | - } | ||
399 | - | ||
400 | - if (topreg > 63 || (topreg > 31 && !(topreg & 1))) { | ||
401 | - /* UNPREDICTABLE: we choose to undef */ | ||
402 | - unallocated_encoding(s); | ||
403 | - return true; | ||
404 | - } | ||
405 | - | ||
406 | - /* Silently ignore requests to clear D16-D31 if they don't exist */ | ||
407 | - if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) { | ||
408 | - topreg = 31; | ||
409 | - } | ||
410 | - | ||
411 | - if (!vfp_access_check(s)) { | ||
412 | - return true; | ||
413 | - } | ||
414 | - | ||
415 | - /* Zero the Sregs from btmreg to topreg inclusive. */ | ||
416 | - zero = tcg_const_i64(0); | ||
417 | - if (btmreg & 1) { | ||
418 | - write_neon_element64(zero, btmreg >> 1, 1, MO_32); | ||
419 | - btmreg++; | ||
420 | - } | ||
421 | - for (; btmreg + 1 <= topreg; btmreg += 2) { | ||
422 | - write_neon_element64(zero, btmreg >> 1, 0, MO_64); | ||
423 | - } | ||
424 | - if (btmreg == topreg) { | ||
425 | - write_neon_element64(zero, btmreg >> 1, 0, MO_32); | ||
426 | - btmreg++; | ||
427 | - } | ||
428 | - assert(btmreg == topreg + 1); | ||
429 | - /* TODO: when MVE is implemented, zero VPR here */ | ||
430 | - return true; | ||
431 | -} | ||
432 | - | ||
433 | -static bool trans_NOCP(DisasContext *s, arg_nocp *a) | ||
434 | -{ | ||
435 | - /* | ||
436 | - * Handle M-profile early check for disabled coprocessor: | ||
437 | - * all we need to do here is emit the NOCP exception if | ||
438 | - * the coprocessor is disabled. Otherwise we return false | ||
439 | - * and the real VFP/etc decode will handle the insn. | ||
440 | - */ | ||
441 | - assert(arm_dc_feature(s, ARM_FEATURE_M)); | ||
442 | - | ||
443 | - if (a->cp == 11) { | ||
444 | - a->cp = 10; | ||
445 | - } | ||
446 | - if (arm_dc_feature(s, ARM_FEATURE_V8_1M) && | ||
447 | - (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) { | ||
448 | - /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */ | ||
449 | - a->cp = 10; | ||
450 | - } | ||
451 | - | ||
452 | - if (a->cp != 10) { | ||
453 | - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, | ||
454 | - syn_uncategorized(), default_exception_el(s)); | ||
455 | - return true; | ||
456 | - } | ||
457 | - | ||
458 | - if (s->fp_excp_el != 0) { | ||
459 | - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, | ||
460 | - syn_uncategorized(), s->fp_excp_el); | ||
461 | - return true; | ||
462 | - } | ||
463 | - | ||
464 | - return false; | ||
465 | -} | ||
466 | - | ||
467 | -static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a) | ||
468 | -{ | ||
469 | - /* This range needs a coprocessor check for v8.1M and later only */ | ||
470 | - if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) { | ||
471 | - return false; | ||
472 | - } | ||
473 | - return trans_NOCP(s, a); | ||
474 | -} | ||
475 | - | ||
476 | static bool trans_VINS(DisasContext *s, arg_VINS *a) | ||
477 | { | ||
478 | TCGv_i32 rd, rm; | ||
479 | diff --git a/target/arm/meson.build b/target/arm/meson.build | ||
480 | index XXXXXXX..XXXXXXX 100644 | ||
481 | --- a/target/arm/meson.build | ||
482 | +++ b/target/arm/meson.build | ||
483 | @@ -XXX,XX +XXX,XX @@ gen = [ | ||
484 | decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'), | ||
485 | decodetree.process('vfp.decode', extra_args: '--static-decode=disas_vfp'), | ||
486 | decodetree.process('vfp-uncond.decode', extra_args: '--static-decode=disas_vfp_uncond'), | ||
487 | - decodetree.process('m-nocp.decode', extra_args: '--static-decode=disas_m_nocp'), | ||
488 | + decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'), | ||
489 | decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'), | ||
490 | decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'), | ||
491 | decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'), | ||
492 | @@ -XXX,XX +XXX,XX @@ arm_ss.add(files( | ||
493 | 'op_helper.c', | ||
494 | 'tlb_helper.c', | ||
495 | 'translate.c', | ||
496 | + 'translate-m-nocp.c', | ||
497 | 'vec_helper.c', | ||
498 | 'vfp_helper.c', | ||
499 | 'cpu_tcg.c', | ||
500 | -- | 1050 | -- |
501 | 2.20.1 | 1051 | 2.20.1 |
502 | 1052 | ||
503 | 1053 | diff view generated by jsdifflib |
1 | On some boards, SCC config register CFG0 bit 0 controls whether | 1 | From: Rashmica Gupta <rashmica.g@gmail.com> |
---|---|---|---|
2 | parts of the board memory map are remapped. Support this with: | ||
3 | * a device property scc-cfg0 so the board can specify the | ||
4 | initial value of the CFG0 register | ||
5 | * an outbound GPIO line which tracks bit 0 and which the board | ||
6 | can wire up to provide the remapping | ||
7 | 2 | ||
3 | Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com> | ||
4 | Reviewed-by: Cédric Le Goater <clg@kaod.org> | ||
5 | Signed-off-by: Cédric Le Goater <clg@kaod.org> | ||
6 | Message-id: 20190904070506.1052-3-clg@kaod.org | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
10 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
11 | Message-id: 20210504120912.23094-3-peter.maydell@linaro.org | ||
12 | --- | 8 | --- |
13 | include/hw/misc/mps2-scc.h | 9 +++++++++ | 9 | include/hw/arm/aspeed_soc.h | 3 +++ |
14 | hw/misc/mps2-scc.c | 13 ++++++++++--- | 10 | hw/arm/aspeed_soc.c | 17 +++++++++++++++++ |
15 | 2 files changed, 19 insertions(+), 3 deletions(-) | 11 | 2 files changed, 20 insertions(+) |
16 | 12 | ||
17 | diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h | 13 | diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h |
18 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/include/hw/misc/mps2-scc.h | 15 | --- a/include/hw/arm/aspeed_soc.h |
20 | +++ b/include/hw/misc/mps2-scc.h | 16 | +++ b/include/hw/arm/aspeed_soc.h |
21 | @@ -XXX,XX +XXX,XX @@ | 17 | @@ -XXX,XX +XXX,XX @@ |
22 | * + QOM property "scc-cfg4": value of the read-only CFG4 register | 18 | #include "hw/watchdog/wdt_aspeed.h" |
23 | * + QOM property "scc-aid": value of the read-only SCC_AID register | 19 | #include "hw/net/ftgmac100.h" |
24 | * + QOM property "scc-id": value of the read-only SCC_ID register | 20 | #include "target/arm/cpu.h" |
25 | + * + QOM property "scc-cfg0": reset value of the CFG0 register | 21 | +#include "hw/gpio/aspeed_gpio.h" |
26 | * + QOM property array "oscclk": reset values of the OSCCLK registers | 22 | |
27 | * (which are accessed via the SYS_CFG channel provided by this device) | 23 | #define ASPEED_SPIS_NUM 2 |
28 | + * + named GPIO output "remap": this tracks the value of CFG0 register | 24 | #define ASPEED_WDTS_NUM 3 |
29 | + * bit 0. Boards where this bit controls memory remapping should | 25 | @@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState { |
30 | + * connect this GPIO line to a function performing that mapping. | 26 | AspeedSDMCState sdmc; |
31 | + * Boards where bit 0 has no special function should leave the GPIO | 27 | AspeedWDTState wdt[ASPEED_WDTS_NUM]; |
32 | + * output disconnected. | 28 | FTGMAC100State ftgmac100[ASPEED_MACS_NUM]; |
33 | */ | 29 | + AspeedGPIOState gpio; |
34 | #ifndef MPS2_SCC_H | 30 | } AspeedSoCState; |
35 | #define MPS2_SCC_H | 31 | |
36 | @@ -XXX,XX +XXX,XX @@ struct MPS2SCC { | 32 | #define TYPE_ASPEED_SOC "aspeed-soc" |
37 | uint32_t num_oscclk; | 33 | @@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCInfo { |
38 | uint32_t *oscclk; | 34 | int spis_num; |
39 | uint32_t *oscclk_reset; | 35 | const char *fmc_typename; |
40 | + uint32_t cfg0_reset; | 36 | const char **spi_typename; |
37 | + const char *gpio_typename; | ||
38 | int wdts_num; | ||
39 | const int *irqmap; | ||
40 | const hwaddr *memmap; | ||
41 | diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c | ||
42 | index XXXXXXX..XXXXXXX 100644 | ||
43 | --- a/hw/arm/aspeed_soc.c | ||
44 | +++ b/hw/arm/aspeed_soc.c | ||
45 | @@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = { | ||
46 | .spis_num = 1, | ||
47 | .fmc_typename = "aspeed.smc.fmc", | ||
48 | .spi_typename = aspeed_soc_ast2400_typenames, | ||
49 | + .gpio_typename = "aspeed.gpio-ast2400", | ||
50 | .wdts_num = 2, | ||
51 | .irqmap = aspeed_soc_ast2400_irqmap, | ||
52 | .memmap = aspeed_soc_ast2400_memmap, | ||
53 | @@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = { | ||
54 | .spis_num = 1, | ||
55 | .fmc_typename = "aspeed.smc.fmc", | ||
56 | .spi_typename = aspeed_soc_ast2400_typenames, | ||
57 | + .gpio_typename = "aspeed.gpio-ast2400", | ||
58 | .wdts_num = 2, | ||
59 | .irqmap = aspeed_soc_ast2400_irqmap, | ||
60 | .memmap = aspeed_soc_ast2400_memmap, | ||
61 | @@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = { | ||
62 | .spis_num = 1, | ||
63 | .fmc_typename = "aspeed.smc.fmc", | ||
64 | .spi_typename = aspeed_soc_ast2400_typenames, | ||
65 | + .gpio_typename = "aspeed.gpio-ast2400", | ||
66 | .wdts_num = 2, | ||
67 | .irqmap = aspeed_soc_ast2400_irqmap, | ||
68 | .memmap = aspeed_soc_ast2400_memmap, | ||
69 | @@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = { | ||
70 | .spis_num = 2, | ||
71 | .fmc_typename = "aspeed.smc.ast2500-fmc", | ||
72 | .spi_typename = aspeed_soc_ast2500_typenames, | ||
73 | + .gpio_typename = "aspeed.gpio-ast2500", | ||
74 | .wdts_num = 3, | ||
75 | .irqmap = aspeed_soc_ast2500_irqmap, | ||
76 | .memmap = aspeed_soc_ast2500_memmap, | ||
77 | @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj) | ||
78 | |||
79 | sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma), | ||
80 | TYPE_ASPEED_XDMA); | ||
41 | + | 81 | + |
42 | + qemu_irq remap; | 82 | + sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio), |
43 | }; | 83 | + sc->info->gpio_typename); |
44 | |||
45 | #endif | ||
46 | diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c | ||
47 | index XXXXXXX..XXXXXXX 100644 | ||
48 | --- a/hw/misc/mps2-scc.c | ||
49 | +++ b/hw/misc/mps2-scc.c | ||
50 | @@ -XXX,XX +XXX,XX @@ | ||
51 | #include "qemu/bitops.h" | ||
52 | #include "trace.h" | ||
53 | #include "hw/sysbus.h" | ||
54 | +#include "hw/irq.h" | ||
55 | #include "migration/vmstate.h" | ||
56 | #include "hw/registerfields.h" | ||
57 | #include "hw/misc/mps2-scc.h" | ||
58 | @@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value, | ||
59 | switch (offset) { | ||
60 | case A_CFG0: | ||
61 | /* | ||
62 | - * TODO on some boards bit 0 controls RAM remapping; | ||
63 | - * on others bit 1 is CPU_WAIT. | ||
64 | + * On some boards bit 0 controls board-specific remapping; | ||
65 | + * we always reflect bit 0 in the 'remap' GPIO output line, | ||
66 | + * and let the board wire it up or not as it chooses. | ||
67 | + * TODO on some boards bit 1 is CPU_WAIT. | ||
68 | */ | ||
69 | s->cfg0 = value; | ||
70 | + qemu_set_irq(s->remap, s->cfg0 & 1); | ||
71 | break; | ||
72 | case A_CFG1: | ||
73 | s->cfg1 = value; | ||
74 | @@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev) | ||
75 | int i; | ||
76 | |||
77 | trace_mps2_scc_reset(); | ||
78 | - s->cfg0 = 0; | ||
79 | + s->cfg0 = s->cfg0_reset; | ||
80 | s->cfg1 = 0; | ||
81 | s->cfg2 = 0; | ||
82 | s->cfg5 = 0; | ||
83 | @@ -XXX,XX +XXX,XX @@ static void mps2_scc_init(Object *obj) | ||
84 | |||
85 | memory_region_init_io(&s->iomem, obj, &mps2_scc_ops, s, "mps2-scc", 0x1000); | ||
86 | sysbus_init_mmio(sbd, &s->iomem); | ||
87 | + qdev_init_gpio_out_named(DEVICE(obj), &s->remap, "remap", 1); | ||
88 | } | 84 | } |
89 | 85 | ||
90 | static void mps2_scc_realize(DeviceState *dev, Error **errp) | 86 | static void aspeed_soc_realize(DeviceState *dev, Error **errp) |
91 | @@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = { | 87 | @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) |
92 | DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0), | 88 | sc->info->memmap[ASPEED_XDMA]); |
93 | DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0), | 89 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0, |
94 | DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0), | 90 | aspeed_soc_get_irq(s, ASPEED_XDMA)); |
95 | + /* Reset value for CFG0 register */ | 91 | + |
96 | + DEFINE_PROP_UINT32("scc-cfg0", MPS2SCC, cfg0_reset, 0), | 92 | + /* GPIO */ |
97 | /* | 93 | + object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); |
98 | * These are the initial settings for the source clocks on the board. | 94 | + if (err) { |
99 | * In hardware they can be configured via a config file read by the | 95 | + error_propagate(errp, err); |
96 | + return; | ||
97 | + } | ||
98 | + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->info->memmap[ASPEED_GPIO]); | ||
99 | + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0, | ||
100 | + aspeed_soc_get_irq(s, ASPEED_GPIO)); | ||
101 | } | ||
102 | static Property aspeed_soc_properties[] = { | ||
103 | DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0), | ||
100 | -- | 104 | -- |
101 | 2.20.1 | 105 | 2.20.1 |
102 | 106 | ||
103 | 107 | diff view generated by jsdifflib |
1 | From: Philippe Mathieu-Daudé <f4bug@amsat.org> | 1 | From: Cédric Le Goater <clg@kaod.org> |
---|---|---|---|
2 | 2 | ||
3 | The i.MX25 PDK board has 2 banks for SDRAM, each can | 3 | There are no QEMU Aspeed machines using the SoCs "ast2400-a0" or |
4 | address up to 256 MiB. So the total RAM usable for this | 4 | "ast2400". |
5 | board is 512M. When we ask for more we get a misleading | ||
6 | error message: | ||
7 | 5 | ||
8 | $ qemu-system-arm -M imx25-pdk -m 513M | 6 | Signed-off-by: Cédric Le Goater <clg@kaod.org> |
9 | qemu-system-arm: Invalid RAM size, should be 128 MiB | 7 | Message-id: 20190904070506.1052-4-clg@kaod.org |
10 | 8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | |
11 | Update the error message to better match the reality: | ||
12 | |||
13 | $ qemu-system-arm -M imx25-pdk -m 513M | ||
14 | qemu-system-arm: RAM size more than 512 MiB is not supported | ||
15 | |||
16 | Fixes: bf350daae02 ("arm/imx25_pdk: drop RAM size fixup") | ||
17 | Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
18 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
19 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | ||
20 | Message-id: 20210407225608.1882855-1-f4bug@amsat.org | ||
21 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
22 | --- | 10 | --- |
23 | hw/arm/imx25_pdk.c | 5 ++--- | 11 | hw/arm/aspeed_soc.c | 26 -------------------------- |
24 | 1 file changed, 2 insertions(+), 3 deletions(-) | 12 | 1 file changed, 26 deletions(-) |
25 | 13 | ||
26 | diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c | 14 | diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c |
27 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
28 | --- a/hw/arm/imx25_pdk.c | 16 | --- a/hw/arm/aspeed_soc.c |
29 | +++ b/hw/arm/imx25_pdk.c | 17 | +++ b/hw/arm/aspeed_soc.c |
30 | @@ -XXX,XX +XXX,XX @@ static struct arm_boot_info imx25_pdk_binfo; | 18 | @@ -XXX,XX +XXX,XX @@ static const char *aspeed_soc_ast2500_typenames[] = { |
31 | 19 | ||
32 | static void imx25_pdk_init(MachineState *machine) | 20 | static const AspeedSoCInfo aspeed_socs[] = { |
33 | { | 21 | { |
34 | - MachineClass *mc = MACHINE_GET_CLASS(machine); | 22 | - .name = "ast2400-a0", |
35 | IMX25PDK *s = g_new0(IMX25PDK, 1); | 23 | - .cpu_type = ARM_CPU_TYPE_NAME("arm926"), |
36 | unsigned int ram_size; | 24 | - .silicon_rev = AST2400_A0_SILICON_REV, |
37 | unsigned int alias_offset; | 25 | - .sram_size = 0x8000, |
38 | @@ -XXX,XX +XXX,XX @@ static void imx25_pdk_init(MachineState *machine) | 26 | - .spis_num = 1, |
39 | 27 | - .fmc_typename = "aspeed.smc.fmc", | |
40 | /* We need to initialize our memory */ | 28 | - .spi_typename = aspeed_soc_ast2400_typenames, |
41 | if (machine->ram_size > (FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE)) { | 29 | - .gpio_typename = "aspeed.gpio-ast2400", |
42 | - char *sz = size_to_str(mc->default_ram_size); | 30 | - .wdts_num = 2, |
43 | - error_report("Invalid RAM size, should be %s", sz); | 31 | - .irqmap = aspeed_soc_ast2400_irqmap, |
44 | + char *sz = size_to_str(FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE); | 32 | - .memmap = aspeed_soc_ast2400_memmap, |
45 | + error_report("RAM size more than %s is not supported", sz); | 33 | - .num_cpus = 1, |
46 | g_free(sz); | 34 | - }, { |
47 | exit(EXIT_FAILURE); | 35 | .name = "ast2400-a1", |
48 | } | 36 | .cpu_type = ARM_CPU_TYPE_NAME("arm926"), |
37 | .silicon_rev = AST2400_A1_SILICON_REV, | ||
38 | @@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = { | ||
39 | .irqmap = aspeed_soc_ast2400_irqmap, | ||
40 | .memmap = aspeed_soc_ast2400_memmap, | ||
41 | .num_cpus = 1, | ||
42 | - }, { | ||
43 | - .name = "ast2400", | ||
44 | - .cpu_type = ARM_CPU_TYPE_NAME("arm926"), | ||
45 | - .silicon_rev = AST2400_A0_SILICON_REV, | ||
46 | - .sram_size = 0x8000, | ||
47 | - .spis_num = 1, | ||
48 | - .fmc_typename = "aspeed.smc.fmc", | ||
49 | - .spi_typename = aspeed_soc_ast2400_typenames, | ||
50 | - .gpio_typename = "aspeed.gpio-ast2400", | ||
51 | - .wdts_num = 2, | ||
52 | - .irqmap = aspeed_soc_ast2400_irqmap, | ||
53 | - .memmap = aspeed_soc_ast2400_memmap, | ||
54 | - .num_cpus = 1, | ||
55 | }, { | ||
56 | .name = "ast2500-a1", | ||
57 | .cpu_type = ARM_CPU_TYPE_NAME("arm1176"), | ||
49 | -- | 58 | -- |
50 | 2.20.1 | 59 | 2.20.1 |
51 | 60 | ||
52 | 61 | diff view generated by jsdifflib |
1 | From: Alex Bennée <alex.bennee@linaro.org> | 1 | From: Cédric Le Goater <clg@kaod.org> |
---|---|---|---|
2 | 2 | ||
3 | A trailing _ makes all the difference to the rendered link. | 3 | Improve the naming of the different controller models to ease their |
4 | generation when initializing the SoC. The rename of the SMC types is | ||
5 | breaking migration compatibility. | ||
4 | 6 | ||
5 | Signed-off-by: Alex Bennée <alex.bennee@linaro.org> | 7 | Signed-off-by: Cédric Le Goater <clg@kaod.org> |
6 | Message-id: 20210428131316.31390-1-alex.bennee@linaro.org | 8 | Message-id: 20190904070506.1052-5-clg@kaod.org |
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 9 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | --- | 11 | --- |
10 | docs/system/arm/sbsa.rst | 2 +- | 12 | include/hw/arm/aspeed_soc.h | 3 --- |
11 | 1 file changed, 1 insertion(+), 1 deletion(-) | 13 | hw/arm/aspeed_soc.c | 25 ++++++++++++------------- |
14 | hw/ssi/aspeed_smc.c | 12 ++++++------ | ||
15 | 3 files changed, 18 insertions(+), 22 deletions(-) | ||
12 | 16 | ||
13 | diff --git a/docs/system/arm/sbsa.rst b/docs/system/arm/sbsa.rst | 17 | diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h |
14 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/docs/system/arm/sbsa.rst | 19 | --- a/include/hw/arm/aspeed_soc.h |
16 | +++ b/docs/system/arm/sbsa.rst | 20 | +++ b/include/hw/arm/aspeed_soc.h |
17 | @@ -XXX,XX +XXX,XX @@ Arm Server Base System Architecture Reference board (``sbsa-ref``) | 21 | @@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCInfo { |
18 | While the `virt` board is a generic board platform that doesn't match | 22 | uint32_t silicon_rev; |
19 | any real hardware the `sbsa-ref` board intends to look like real | 23 | uint64_t sram_size; |
20 | hardware. The `Server Base System Architecture | 24 | int spis_num; |
21 | -<https://developer.arm.com/documentation/den0029/latest>` defines a | 25 | - const char *fmc_typename; |
22 | +<https://developer.arm.com/documentation/den0029/latest>`_ defines a | 26 | - const char **spi_typename; |
23 | minimum base line of hardware support and importantly how the firmware | 27 | - const char *gpio_typename; |
24 | reports that to any operating system. It is a static system that | 28 | int wdts_num; |
25 | reports a very minimal DT to the firmware for non-discoverable | 29 | const int *irqmap; |
30 | const hwaddr *memmap; | ||
31 | diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c | ||
32 | index XXXXXXX..XXXXXXX 100644 | ||
33 | --- a/hw/arm/aspeed_soc.c | ||
34 | +++ b/hw/arm/aspeed_soc.c | ||
35 | @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2400_irqmap[] = { | ||
36 | |||
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); | ||
95 | } | ||
96 | |||
97 | sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc), | ||
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); | ||
106 | } | ||
107 | |||
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, | ||
26 | -- | 167 | -- |
27 | 2.20.1 | 168 | 2.20.1 |
28 | 169 | ||
29 | 170 | diff view generated by jsdifflib |
1 | Some of the constant expanders defined in translate.c are generically | 1 | From: Cédric Le Goater <clg@kaod.org> |
---|---|---|---|
2 | useful and will be used by the separate C files for VFP and Neon once | 2 | |
3 | they are created; move the expander definitions to translate.h. | 3 | The FMC controller on the Aspeed SoCs support DMA to access the flash |
4 | 4 | modules. It can operate in a normal mode, to copy to or from the flash | |
5 | module mapping window, or in a checksum calculation mode, to evaluate | ||
6 | the best clock settings for reads. | ||
7 | |||
8 | The model introduces two custom address spaces for DMAs: one for the | ||
9 | AHB window of the FMC flash devices and one for the DRAM. The latter | ||
10 | is populated using a "dram" link set from the machine with the RAM | ||
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 | ||
16 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
7 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
8 | Message-id: 20210430132740.10391-2-peter.maydell@linaro.org | ||
9 | --- | 18 | --- |
10 | target/arm/translate.h | 24 ++++++++++++++++++++++++ | 19 | include/hw/ssi/aspeed_smc.h | 6 + |
11 | target/arm/translate.c | 24 ------------------------ | 20 | hw/arm/aspeed.c | 2 + |
12 | 2 files changed, 24 insertions(+), 24 deletions(-) | 21 | hw/arm/aspeed_soc.c | 2 + |
13 | 22 | hw/ssi/aspeed_smc.c | 222 +++++++++++++++++++++++++++++++++++- | |
14 | diff --git a/target/arm/translate.h b/target/arm/translate.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 | ||
15 | index XXXXXXX..XXXXXXX 100644 | 26 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/translate.h | 27 | --- a/include/hw/ssi/aspeed_smc.h |
17 | +++ b/target/arm/translate.h | 28 | +++ b/include/hw/ssi/aspeed_smc.h |
18 | @@ -XXX,XX +XXX,XX @@ extern TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF; | 29 | @@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCController { |
19 | extern TCGv_i64 cpu_exclusive_addr; | 30 | hwaddr flash_window_base; |
20 | extern TCGv_i64 cpu_exclusive_val; | 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 | ||
79 | @@ -XXX,XX +XXX,XX @@ | ||
80 | #include "qemu/log.h" | ||
81 | #include "qemu/module.h" | ||
82 | #include "qemu/error-report.h" | ||
83 | +#include "qapi/error.h" | ||
84 | +#include "exec/address-spaces.h" | ||
85 | |||
86 | #include "hw/irq.h" | ||
87 | #include "hw/qdev-properties.h" | ||
88 | @@ -XXX,XX +XXX,XX @@ | ||
89 | #define DMA_CTRL_FREQ_SHIFT 4 | ||
90 | #define DMA_CTRL_MODE (1 << 3) | ||
91 | #define DMA_CTRL_CKSUM (1 << 2) | ||
92 | -#define DMA_CTRL_DIR (1 << 1) | ||
93 | -#define DMA_CTRL_EN (1 << 0) | ||
94 | +#define DMA_CTRL_WRITE (1 << 1) | ||
95 | +#define DMA_CTRL_ENABLE (1 << 0) | ||
96 | |||
97 | /* DMA Flash Side Address */ | ||
98 | #define R_DMA_FLASH_ADDR (0x84 / 4) | ||
99 | @@ -XXX,XX +XXX,XX @@ | ||
100 | #define ASPEED_SOC_SPI_FLASH_BASE 0x30000000 | ||
101 | #define ASPEED_SOC_SPI2_FLASH_BASE 0x38000000 | ||
21 | 102 | ||
22 | +/* | 103 | +/* |
23 | + * Constant expanders for the decoders. | 104 | + * DMA DRAM addresses should be 4 bytes aligned and the valid address |
105 | + * range is 0x40000000 - 0x5FFFFFFF (AST2400) | ||
106 | + * 0x80000000 - 0xBFFFFFFF (AST2500) | ||
107 | + * | ||
108 | + * DMA flash addresses should be 4 bytes aligned and the valid address | ||
109 | + * range is 0x20000000 - 0x2FFFFFFF. | ||
110 | + * | ||
111 | + * DMA length is from 4 bytes to 32MB | ||
112 | + * 0: 4 bytes | ||
113 | + * 0x7FFFFF: 32M bytes | ||
24 | + */ | 114 | + */ |
25 | + | 115 | +#define DMA_DRAM_ADDR(s, val) ((s)->sdram_base | \ |
26 | +static inline int negate(DisasContext *s, int x) | 116 | + ((val) & (s)->ctrl->dma_dram_mask)) |
27 | +{ | 117 | +#define DMA_FLASH_ADDR(s, val) ((s)->ctrl->flash_window_base | \ |
28 | + return -x; | 118 | + ((val) & (s)->ctrl->dma_flash_mask)) |
29 | +} | 119 | +#define DMA_LENGTH(val) ((val) & 0x01FFFFFC) |
30 | + | 120 | + |
31 | +static inline int plus_2(DisasContext *s, int x) | 121 | /* Flash opcodes. */ |
32 | +{ | 122 | #define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */ |
33 | + return x + 2; | 123 | |
34 | +} | 124 | @@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = { |
35 | + | 125 | .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE, |
36 | +static inline int times_2(DisasContext *s, int x) | 126 | .flash_window_size = 0x10000000, |
37 | +{ | 127 | .has_dma = true, |
38 | + return x * 2; | 128 | + .dma_flash_mask = 0x0FFFFFFC, |
39 | +} | 129 | + .dma_dram_mask = 0x1FFFFFFC, |
40 | + | 130 | .nregs = ASPEED_SMC_R_MAX, |
41 | +static inline int times_4(DisasContext *s, int x) | 131 | }, { |
42 | +{ | 132 | .name = "aspeed.spi1-ast2400", |
43 | + return x * 4; | 133 | @@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = { |
44 | +} | 134 | .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE, |
45 | + | 135 | .flash_window_size = 0x10000000, |
46 | static inline int arm_dc_feature(DisasContext *dc, int feature) | 136 | .has_dma = true, |
47 | { | 137 | + .dma_flash_mask = 0x0FFFFFFC, |
48 | return (dc->features & (1ULL << feature)) != 0; | 138 | + .dma_dram_mask = 0x3FFFFFFC, |
49 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 139 | .nregs = ASPEED_SMC_R_MAX, |
50 | index XXXXXXX..XXXXXXX 100644 | 140 | }, { |
51 | --- a/target/arm/translate.c | 141 | .name = "aspeed.spi1-ast2500", |
52 | +++ b/target/arm/translate.c | 142 | @@ -XXX,XX +XXX,XX @@ static void aspeed_smc_reset(DeviceState *d) |
53 | @@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s) | 143 | |
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) | ||
54 | } | 165 | } |
55 | } | 166 | } |
56 | 167 | ||
57 | -/* | 168 | +/* |
58 | - * Constant expanders for the decoders. | 169 | + * Accumulate the result of the reads to provide a checksum that will |
59 | - */ | 170 | + * be used to validate the read timing settings. |
60 | - | 171 | + */ |
61 | -static int negate(DisasContext *s, int x) | 172 | +static void aspeed_smc_dma_checksum(AspeedSMCState *s) |
62 | -{ | 173 | +{ |
63 | - return -x; | 174 | + MemTxResult result; |
64 | -} | 175 | + uint32_t data; |
65 | - | 176 | + |
66 | -static int plus_2(DisasContext *s, int x) | 177 | + if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) { |
67 | -{ | 178 | + qemu_log_mask(LOG_GUEST_ERROR, |
68 | - return x + 2; | 179 | + "%s: invalid direction for DMA checksum\n", __func__); |
69 | -} | 180 | + return; |
70 | - | 181 | + } |
71 | -static int times_2(DisasContext *s, int x) | 182 | + |
72 | -{ | 183 | + while (s->regs[R_DMA_LEN]) { |
73 | - return x * 2; | 184 | + data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR], |
74 | -} | 185 | + MEMTXATTRS_UNSPECIFIED, &result); |
75 | - | 186 | + if (result != MEMTX_OK) { |
76 | -static int times_4(DisasContext *s, int x) | 187 | + qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash read failed @%08x\n", |
77 | -{ | 188 | + __func__, s->regs[R_DMA_FLASH_ADDR]); |
78 | - return x * 4; | 189 | + return; |
79 | -} | 190 | + } |
80 | - | 191 | + |
81 | /* Flags for the disas_set_da_iss info argument: | 192 | + /* |
82 | * lower bits hold the Rt register number, higher bits are flags. | 193 | + * When the DMA is on-going, the DMA registers are updated |
83 | */ | 194 | + * with the current working addresses and length. |
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, | ||
315 | } | ||
316 | } else if (addr == R_DUMMY_DATA) { | ||
317 | s->regs[addr] = value & 0xff; | ||
318 | + } else if (addr == R_INTR_CTRL) { | ||
319 | + s->regs[addr] = value; | ||
320 | + } else if (s->ctrl->has_dma && addr == R_DMA_CTRL) { | ||
321 | + aspeed_smc_dma_ctrl(s, value); | ||
322 | + } else if (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) { | ||
323 | + s->regs[addr] = DMA_DRAM_ADDR(s, value); | ||
324 | + } else if (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) { | ||
325 | + s->regs[addr] = DMA_FLASH_ADDR(s, value); | ||
326 | + } else if (s->ctrl->has_dma && addr == R_DMA_LEN) { | ||
327 | + s->regs[addr] = DMA_LENGTH(value); | ||
328 | } else { | ||
329 | qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n", | ||
330 | __func__, addr); | ||
331 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_smc_ops = { | ||
332 | .valid.unaligned = true, | ||
333 | }; | ||
334 | |||
335 | + | ||
336 | +/* | ||
337 | + * Initialize the custom address spaces for DMAs | ||
338 | + */ | ||
339 | +static void aspeed_smc_dma_setup(AspeedSMCState *s, Error **errp) | ||
340 | +{ | ||
341 | + char *name; | ||
342 | + | ||
343 | + if (!s->dram_mr) { | ||
344 | + error_setg(errp, TYPE_ASPEED_SMC ": 'dram' link not set"); | ||
345 | + return; | ||
346 | + } | ||
347 | + | ||
348 | + name = g_strdup_printf("%s-dma-flash", s->ctrl->name); | ||
349 | + address_space_init(&s->flash_as, &s->mmio_flash, name); | ||
350 | + g_free(name); | ||
351 | + | ||
352 | + name = g_strdup_printf("%s-dma-dram", s->ctrl->name); | ||
353 | + address_space_init(&s->dram_as, s->dram_mr, name); | ||
354 | + g_free(name); | ||
355 | +} | ||
356 | + | ||
357 | static void aspeed_smc_realize(DeviceState *dev, Error **errp) | ||
358 | { | ||
359 | SysBusDevice *sbd = SYS_BUS_DEVICE(dev); | ||
360 | @@ -XXX,XX +XXX,XX @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) | ||
361 | s->num_cs = s->ctrl->max_slaves; | ||
362 | } | ||
363 | |||
364 | + /* DMA irq. Keep it first for the initialization in the SoC */ | ||
365 | + sysbus_init_irq(sbd, &s->irq); | ||
366 | + | ||
367 | s->spi = ssi_create_bus(dev, "spi"); | ||
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 *), | ||
392 | DEFINE_PROP_END_OF_LIST(), | ||
393 | }; | ||
394 | |||
84 | -- | 395 | -- |
85 | 2.20.1 | 396 | 2.20.1 |
86 | 397 | ||
87 | 398 | diff view generated by jsdifflib |
1 | The functions vfp_load_reg32(), vfp_load_reg64(), vfp_store_reg32() | 1 | From: Cédric Le Goater <clg@kaod.org> |
---|---|---|---|
2 | and vfp_store_reg64() are used only in translate-vfp.c.inc. Move | ||
3 | them to that file. | ||
4 | 2 | ||
3 | When doing calibration, the SPI clock rate in the CE0 Control Register | ||
4 | and the read delay cycles in the Read Timing Compensation Register are | ||
5 | set using bit[11:4] of the DMA Control Register. | ||
6 | |||
7 | Signed-off-by: Cédric Le Goater <clg@kaod.org> | ||
8 | Acked-by: Joel Stanley <joel@jms.id.au> | ||
9 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | Message-id: 20190904070506.1052-7-clg@kaod.org | ||
5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
7 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
8 | Message-id: 20210430132740.10391-7-peter.maydell@linaro.org | ||
9 | --- | 12 | --- |
10 | target/arm/translate.c | 20 -------------------- | 13 | hw/ssi/aspeed_smc.c | 64 ++++++++++++++++++++++++++++++++++++++++++++- |
11 | target/arm/translate-vfp.c.inc | 20 ++++++++++++++++++++ | 14 | 1 file changed, 63 insertions(+), 1 deletion(-) |
12 | 2 files changed, 20 insertions(+), 20 deletions(-) | ||
13 | 15 | ||
14 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 16 | diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c |
15 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/translate.c | 18 | --- a/hw/ssi/aspeed_smc.c |
17 | +++ b/target/arm/translate.c | 19 | +++ b/hw/ssi/aspeed_smc.c |
18 | @@ -XXX,XX +XXX,XX @@ static long vfp_reg_offset(bool dp, unsigned reg) | 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) | ||
19 | } | 41 | } |
20 | } | 42 | } |
21 | 43 | ||
22 | -static inline void vfp_load_reg64(TCGv_i64 var, int reg) | 44 | +static uint8_t aspeed_smc_hclk_divisor(uint8_t hclk_mask) |
23 | -{ | ||
24 | - tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(true, reg)); | ||
25 | -} | ||
26 | - | ||
27 | -static inline void vfp_store_reg64(TCGv_i64 var, int reg) | ||
28 | -{ | ||
29 | - tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(true, reg)); | ||
30 | -} | ||
31 | - | ||
32 | -static inline void vfp_load_reg32(TCGv_i32 var, int reg) | ||
33 | -{ | ||
34 | - tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg)); | ||
35 | -} | ||
36 | - | ||
37 | -static inline void vfp_store_reg32(TCGv_i32 var, int reg) | ||
38 | -{ | ||
39 | - tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg)); | ||
40 | -} | ||
41 | - | ||
42 | void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop) | ||
43 | { | ||
44 | long off = neon_element_offset(reg, ele, memop); | ||
45 | diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc | ||
46 | index XXXXXXX..XXXXXXX 100644 | ||
47 | --- a/target/arm/translate-vfp.c.inc | ||
48 | +++ b/target/arm/translate-vfp.c.inc | ||
49 | @@ -XXX,XX +XXX,XX @@ | ||
50 | #include "decode-vfp.c.inc" | ||
51 | #include "decode-vfp-uncond.c.inc" | ||
52 | |||
53 | +static inline void vfp_load_reg64(TCGv_i64 var, int reg) | ||
54 | +{ | 45 | +{ |
55 | + tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(true, reg)); | 46 | + /* HCLK/1 .. HCLK/16 */ |
47 | + const uint8_t hclk_divisors[] = { | ||
48 | + 15, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0 | ||
49 | + }; | ||
50 | + int i; | ||
51 | + | ||
52 | + for (i = 0; i < ARRAY_SIZE(hclk_divisors); i++) { | ||
53 | + if (hclk_mask == hclk_divisors[i]) { | ||
54 | + return i + 1; | ||
55 | + } | ||
56 | + } | ||
57 | + | ||
58 | + qemu_log_mask(LOG_GUEST_ERROR, "invalid HCLK mask %x", hclk_mask); | ||
59 | + return 0; | ||
56 | +} | 60 | +} |
57 | + | 61 | + |
58 | +static inline void vfp_store_reg64(TCGv_i64 var, int reg) | 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) | ||
59 | +{ | 68 | +{ |
60 | + tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(true, reg)); | 69 | + uint8_t delay = |
61 | +} | 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; | ||
62 | + | 76 | + |
63 | +static inline void vfp_load_reg32(TCGv_i32 var, int reg) | 77 | + /* |
64 | +{ | 78 | + * The Read Timing Compensation Register values apply to all CS on |
65 | + tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg)); | 79 | + * the SPI bus and only HCLK/1 - HCLK/5 can have tunable delays |
66 | +} | 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 | + } | ||
67 | + | 85 | + |
68 | +static inline void vfp_store_reg32(TCGv_i32 var, int reg) | 86 | + /* |
69 | +{ | 87 | + * TODO: compute the CS from the DMA address and the segment |
70 | + tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg)); | 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); | ||
71 | +} | 96 | +} |
72 | + | 97 | + |
73 | /* | 98 | /* |
74 | * The imm8 encodes the sign bit, enough bits to represent an exponent in | 99 | * Accumulate the result of the reads to provide a checksum that will |
75 | * the range 01....1xx to 10....0xx, and the most significant 4 bits of | 100 | * be used to validate the read timing settings. |
101 | @@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s) | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | + if (s->regs[R_DMA_CTRL] & DMA_CTRL_CALIB) { | ||
106 | + aspeed_smc_dma_calibration(s); | ||
107 | + } | ||
108 | + | ||
109 | while (s->regs[R_DMA_LEN]) { | ||
110 | data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR], | ||
111 | MEMTXATTRS_UNSPECIFIED, &result); | ||
76 | -- | 112 | -- |
77 | 2.20.1 | 113 | 2.20.1 |
78 | 114 | ||
79 | 115 | diff view generated by jsdifflib |
1 | Move the various gen_aa32* functions and macros out of translate.c | 1 | From: Cédric Le Goater <clg@kaod.org> |
---|---|---|---|
2 | and into translate-a32.h. | ||
3 | 2 | ||
3 | Emulate read errors in the DMA Checksum Register for high frequencies | ||
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. | ||
8 | |||
9 | The values below are those to expect from the first flash device of | ||
10 | the FMC controller of a palmetto-bmc machine. | ||
11 | |||
12 | Cc: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
13 | Signed-off-by: Cédric Le Goater <clg@kaod.org> | ||
14 | Reviewed-by: Joel Stanley <joel@jms.id.au> | ||
15 | Message-id: 20190904070506.1052-8-clg@kaod.org | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 16 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20210430132740.10391-6-peter.maydell@linaro.org | ||
8 | --- | 17 | --- |
9 | target/arm/translate-a32.h | 53 ++++++++++++++++++++++++++++++++++++++ | 18 | include/hw/ssi/aspeed_smc.h | 1 + |
10 | target/arm/translate.c | 51 ++++++++++++------------------------ | 19 | hw/ssi/aspeed_smc.c | 36 ++++++++++++++++++++++++++++++++++++ |
11 | 2 files changed, 69 insertions(+), 35 deletions(-) | 20 | 2 files changed, 37 insertions(+) |
12 | 21 | ||
13 | diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h | 22 | diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h |
14 | index XXXXXXX..XXXXXXX 100644 | 23 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/target/arm/translate-a32.h | 24 | --- a/include/hw/ssi/aspeed_smc.h |
16 | +++ b/target/arm/translate-a32.h | 25 | +++ b/include/hw/ssi/aspeed_smc.h |
17 | @@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg) | 26 | @@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCState { |
18 | return tmp; | 27 | |
28 | uint32_t num_cs; | ||
29 | qemu_irq *cs_lines; | ||
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); | ||
19 | } | 40 | } |
20 | 41 | ||
21 | +void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val, | 42 | +/* |
22 | + TCGv_i32 a32, int index, MemOp opc); | 43 | + * Emulate read errors in the DMA Checksum Register for high |
23 | +void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val, | 44 | + * frequencies and optimistic settings of the Read Timing Compensation |
24 | + TCGv_i32 a32, int index, MemOp opc); | 45 | + * Register. This will help in tuning the SPI timing calibration |
25 | +void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val, | 46 | + * algorithm. |
26 | + TCGv_i32 a32, int index, MemOp opc); | 47 | + */ |
27 | +void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val, | 48 | +static bool aspeed_smc_inject_read_failure(AspeedSMCState *s) |
28 | + TCGv_i32 a32, int index, MemOp opc); | 49 | +{ |
29 | +void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32, | 50 | + uint8_t delay = |
30 | + int index, MemOp opc); | 51 | + (s->regs[R_DMA_CTRL] >> DMA_CTRL_DELAY_SHIFT) & DMA_CTRL_DELAY_MASK; |
31 | +void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32, | 52 | + uint8_t hclk_mask = |
32 | + int index, MemOp opc); | 53 | + (s->regs[R_DMA_CTRL] >> DMA_CTRL_FREQ_SHIFT) & DMA_CTRL_FREQ_MASK; |
33 | +void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, | ||
34 | + int index, MemOp opc); | ||
35 | +void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, | ||
36 | + int index, MemOp opc); | ||
37 | + | 54 | + |
38 | +#define DO_GEN_LD(SUFF, OPC) \ | 55 | + /* |
39 | + static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \ | 56 | + * Typical values of a palmetto-bmc machine. |
40 | + TCGv_i32 a32, int index) \ | 57 | + */ |
41 | + { \ | 58 | + switch (aspeed_smc_hclk_divisor(hclk_mask)) { |
42 | + gen_aa32_ld_i32(s, val, a32, index, OPC); \ | 59 | + case 4 ... 16: |
60 | + return false; | ||
61 | + case 3: /* at least one HCLK cycle delay */ | ||
62 | + return (delay & 0x7) < 1; | ||
63 | + case 2: /* at least two HCLK cycle delay */ | ||
64 | + return (delay & 0x7) < 2; | ||
65 | + case 1: /* (> 100MHz) is above the max freq of the controller */ | ||
66 | + return true; | ||
67 | + default: | ||
68 | + g_assert_not_reached(); | ||
69 | + } | ||
70 | +} | ||
71 | + | ||
72 | /* | ||
73 | * Accumulate the result of the reads to provide a checksum that will | ||
74 | * be used to validate the read timing settings. | ||
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; | ||
43 | + } | 82 | + } |
44 | + | 83 | + |
45 | +#define DO_GEN_ST(SUFF, OPC) \ | ||
46 | + static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \ | ||
47 | + TCGv_i32 a32, int index) \ | ||
48 | + { \ | ||
49 | + gen_aa32_st_i32(s, val, a32, index, OPC); \ | ||
50 | + } | ||
51 | + | ||
52 | +static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, | ||
53 | + TCGv_i32 a32, int index) | ||
54 | +{ | ||
55 | + gen_aa32_ld_i64(s, val, a32, index, MO_Q); | ||
56 | +} | ||
57 | + | ||
58 | +static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, | ||
59 | + TCGv_i32 a32, int index) | ||
60 | +{ | ||
61 | + gen_aa32_st_i64(s, val, a32, index, MO_Q); | ||
62 | +} | ||
63 | + | ||
64 | +DO_GEN_LD(8u, MO_UB) | ||
65 | +DO_GEN_LD(16u, MO_UW) | ||
66 | +DO_GEN_LD(32u, MO_UL) | ||
67 | +DO_GEN_ST(8, MO_UB) | ||
68 | +DO_GEN_ST(16, MO_UW) | ||
69 | +DO_GEN_ST(32, MO_UL) | ||
70 | + | ||
71 | +#undef DO_GEN_LD | ||
72 | +#undef DO_GEN_ST | ||
73 | + | ||
74 | #endif | ||
75 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
76 | index XXXXXXX..XXXXXXX 100644 | ||
77 | --- a/target/arm/translate.c | ||
78 | +++ b/target/arm/translate.c | ||
79 | @@ -XXX,XX +XXX,XX @@ static TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op) | ||
80 | * Internal routines are used for NEON cases where the endianness | ||
81 | * and/or alignment has already been taken into account and manipulated. | ||
82 | */ | ||
83 | -static void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val, | ||
84 | - TCGv_i32 a32, int index, MemOp opc) | ||
85 | +void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val, | ||
86 | + TCGv_i32 a32, int index, MemOp opc) | ||
87 | { | ||
88 | TCGv addr = gen_aa32_addr(s, a32, opc); | ||
89 | tcg_gen_qemu_ld_i32(val, addr, index, opc); | ||
90 | tcg_temp_free(addr); | ||
91 | } | 84 | } |
92 | 85 | ||
93 | -static void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val, | 86 | static void aspeed_smc_dma_rw(AspeedSMCState *s) |
94 | - TCGv_i32 a32, int index, MemOp opc) | 87 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_smc = { |
95 | +void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val, | 88 | |
96 | + TCGv_i32 a32, int index, MemOp opc) | 89 | static Property aspeed_smc_properties[] = { |
97 | { | 90 | DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1), |
98 | TCGv addr = gen_aa32_addr(s, a32, opc); | 91 | + DEFINE_PROP_BOOL("inject-failure", AspeedSMCState, inject_failure, false), |
99 | tcg_gen_qemu_st_i32(val, addr, index, opc); | 92 | DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0), |
100 | tcg_temp_free(addr); | 93 | DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr, |
101 | } | 94 | TYPE_MEMORY_REGION, MemoryRegion *), |
102 | |||
103 | -static void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val, | ||
104 | - TCGv_i32 a32, int index, MemOp opc) | ||
105 | +void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val, | ||
106 | + TCGv_i32 a32, int index, MemOp opc) | ||
107 | { | ||
108 | TCGv addr = gen_aa32_addr(s, a32, opc); | ||
109 | |||
110 | @@ -XXX,XX +XXX,XX @@ static void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val, | ||
111 | tcg_temp_free(addr); | ||
112 | } | ||
113 | |||
114 | -static void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val, | ||
115 | - TCGv_i32 a32, int index, MemOp opc) | ||
116 | +void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val, | ||
117 | + TCGv_i32 a32, int index, MemOp opc) | ||
118 | { | ||
119 | TCGv addr = gen_aa32_addr(s, a32, opc); | ||
120 | |||
121 | @@ -XXX,XX +XXX,XX @@ static void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val, | ||
122 | tcg_temp_free(addr); | ||
123 | } | ||
124 | |||
125 | -static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32, | ||
126 | - int index, MemOp opc) | ||
127 | +void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32, | ||
128 | + int index, MemOp opc) | ||
129 | { | ||
130 | gen_aa32_ld_internal_i32(s, val, a32, index, finalize_memop(s, opc)); | ||
131 | } | ||
132 | |||
133 | -static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32, | ||
134 | - int index, MemOp opc) | ||
135 | +void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32, | ||
136 | + int index, MemOp opc) | ||
137 | { | ||
138 | gen_aa32_st_internal_i32(s, val, a32, index, finalize_memop(s, opc)); | ||
139 | } | ||
140 | |||
141 | -static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, | ||
142 | - int index, MemOp opc) | ||
143 | +void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, | ||
144 | + int index, MemOp opc) | ||
145 | { | ||
146 | gen_aa32_ld_internal_i64(s, val, a32, index, finalize_memop(s, opc)); | ||
147 | } | ||
148 | |||
149 | -static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, | ||
150 | - int index, MemOp opc) | ||
151 | +void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, | ||
152 | + int index, MemOp opc) | ||
153 | { | ||
154 | gen_aa32_st_internal_i64(s, val, a32, index, finalize_memop(s, opc)); | ||
155 | } | ||
156 | @@ -XXX,XX +XXX,XX @@ static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, | ||
157 | gen_aa32_st_i32(s, val, a32, index, OPC); \ | ||
158 | } | ||
159 | |||
160 | -static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, | ||
161 | - TCGv_i32 a32, int index) | ||
162 | -{ | ||
163 | - gen_aa32_ld_i64(s, val, a32, index, MO_Q); | ||
164 | -} | ||
165 | - | ||
166 | -static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, | ||
167 | - TCGv_i32 a32, int index) | ||
168 | -{ | ||
169 | - gen_aa32_st_i64(s, val, a32, index, MO_Q); | ||
170 | -} | ||
171 | - | ||
172 | -DO_GEN_LD(8u, MO_UB) | ||
173 | -DO_GEN_LD(16u, MO_UW) | ||
174 | -DO_GEN_LD(32u, MO_UL) | ||
175 | -DO_GEN_ST(8, MO_UB) | ||
176 | -DO_GEN_ST(16, MO_UW) | ||
177 | -DO_GEN_ST(32, MO_UL) | ||
178 | - | ||
179 | static inline void gen_hvc(DisasContext *s, int imm16) | ||
180 | { | ||
181 | /* The pre HVC helper handles cases when HVC gets trapped | ||
182 | -- | 95 | -- |
183 | 2.20.1 | 96 | 2.20.1 |
184 | 97 | ||
185 | 98 | diff view generated by jsdifflib |
1 | The unallocated_encoding() function is the same in both | 1 | From: Christian Svensson <bluecmd@google.com> |
---|---|---|---|
2 | translate-a64.c and translate.c; make the translate.c function global | ||
3 | and drop the translate-a64.c version. To do this we need to also | ||
4 | share gen_exception_insn(), which currently exists in two slightly | ||
5 | different versions for A32 and A64: merge those into a single | ||
6 | function that can work for both. | ||
7 | 2 | ||
8 | This will be useful for splitting up translate.c, which will require | 3 | This patch adds the missing checksum calculation on normal DMA transfer. |
9 | unallocated_encoding() to no longer be file-local. It's also | 4 | According to the datasheet this is how the SMC should behave. |
10 | hopefully less confusing to have only one version of the function | ||
11 | rather than two. | ||
12 | 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 | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
14 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
15 | Message-id: 20210430132740.10391-3-peter.maydell@linaro.org | ||
16 | --- | 13 | --- |
17 | target/arm/translate-a64.h | 2 -- | 14 | hw/ssi/aspeed_smc.c | 1 + |
18 | target/arm/translate.h | 3 +++ | 15 | 1 file changed, 1 insertion(+) |
19 | target/arm/translate-a64.c | 15 --------------- | ||
20 | target/arm/translate.c | 14 +++++++++----- | ||
21 | 4 files changed, 12 insertions(+), 22 deletions(-) | ||
22 | 16 | ||
23 | diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h | 17 | diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c |
24 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/target/arm/translate-a64.h | 19 | --- a/hw/ssi/aspeed_smc.c |
26 | +++ b/target/arm/translate-a64.h | 20 | +++ b/hw/ssi/aspeed_smc.c |
27 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_rw(AspeedSMCState *s) |
28 | #ifndef TARGET_ARM_TRANSLATE_A64_H | 22 | s->regs[R_DMA_FLASH_ADDR] += 4; |
29 | #define TARGET_ARM_TRANSLATE_A64_H | 23 | s->regs[R_DMA_DRAM_ADDR] += 4; |
30 | 24 | s->regs[R_DMA_LEN] -= 4; | |
31 | -void unallocated_encoding(DisasContext *s); | 25 | + s->regs[R_DMA_CHECKSUM] += data; |
32 | - | ||
33 | #define unsupported_encoding(s, insn) \ | ||
34 | do { \ | ||
35 | qemu_log_mask(LOG_UNIMP, \ | ||
36 | diff --git a/target/arm/translate.h b/target/arm/translate.h | ||
37 | index XXXXXXX..XXXXXXX 100644 | ||
38 | --- a/target/arm/translate.h | ||
39 | +++ b/target/arm/translate.h | ||
40 | @@ -XXX,XX +XXX,XX @@ void arm_free_cc(DisasCompare *cmp); | ||
41 | void arm_jump_cc(DisasCompare *cmp, TCGLabel *label); | ||
42 | void arm_gen_test_cc(int cc, TCGLabel *label); | ||
43 | MemOp pow2_align(unsigned i); | ||
44 | +void unallocated_encoding(DisasContext *s); | ||
45 | +void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, | ||
46 | + uint32_t syn, uint32_t target_el); | ||
47 | |||
48 | /* Return state of Alternate Half-precision flag, caller frees result */ | ||
49 | static inline TCGv_i32 get_ahp_flag(void) | ||
50 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c | ||
51 | index XXXXXXX..XXXXXXX 100644 | ||
52 | --- a/target/arm/translate-a64.c | ||
53 | +++ b/target/arm/translate-a64.c | ||
54 | @@ -XXX,XX +XXX,XX @@ static void gen_exception_internal_insn(DisasContext *s, uint64_t pc, int excp) | ||
55 | s->base.is_jmp = DISAS_NORETURN; | ||
56 | } | ||
57 | |||
58 | -static void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, | ||
59 | - uint32_t syndrome, uint32_t target_el) | ||
60 | -{ | ||
61 | - gen_a64_set_pc_im(pc); | ||
62 | - gen_exception(excp, syndrome, target_el); | ||
63 | - s->base.is_jmp = DISAS_NORETURN; | ||
64 | -} | ||
65 | - | ||
66 | static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syndrome) | ||
67 | { | ||
68 | TCGv_i32 tcg_syn; | ||
69 | @@ -XXX,XX +XXX,XX @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest) | ||
70 | } | 26 | } |
71 | } | 27 | } |
72 | 28 | ||
73 | -void unallocated_encoding(DisasContext *s) | ||
74 | -{ | ||
75 | - /* Unallocated and reserved encodings are uncategorized */ | ||
76 | - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), | ||
77 | - default_exception_el(s)); | ||
78 | -} | ||
79 | - | ||
80 | static void init_tmp_a64_array(DisasContext *s) | ||
81 | { | ||
82 | #ifdef CONFIG_DEBUG_TCG | ||
83 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
84 | index XXXXXXX..XXXXXXX 100644 | ||
85 | --- a/target/arm/translate.c | ||
86 | +++ b/target/arm/translate.c | ||
87 | @@ -XXX,XX +XXX,XX @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) | ||
88 | s->base.is_jmp = DISAS_NORETURN; | ||
89 | } | ||
90 | |||
91 | -static void gen_exception_insn(DisasContext *s, uint32_t pc, int excp, | ||
92 | - int syn, uint32_t target_el) | ||
93 | +void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, | ||
94 | + uint32_t syn, uint32_t target_el) | ||
95 | { | ||
96 | - gen_set_condexec(s); | ||
97 | - gen_set_pc_im(s, pc); | ||
98 | + if (s->aarch64) { | ||
99 | + gen_a64_set_pc_im(pc); | ||
100 | + } else { | ||
101 | + gen_set_condexec(s); | ||
102 | + gen_set_pc_im(s, pc); | ||
103 | + } | ||
104 | gen_exception(excp, syn, target_el); | ||
105 | s->base.is_jmp = DISAS_NORETURN; | ||
106 | } | ||
107 | @@ -XXX,XX +XXX,XX @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) | ||
108 | s->base.is_jmp = DISAS_NORETURN; | ||
109 | } | ||
110 | |||
111 | -static void unallocated_encoding(DisasContext *s) | ||
112 | +void unallocated_encoding(DisasContext *s) | ||
113 | { | ||
114 | /* Unallocated and reserved encodings are uncategorized */ | ||
115 | gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), | ||
116 | -- | 29 | -- |
117 | 2.20.1 | 30 | 2.20.1 |
118 | 31 | ||
119 | 32 | diff view generated by jsdifflib |
1 | From: Richard Henderson <richard.henderson@linaro.org> | 1 | From: Cédric Le Goater <clg@kaod.org> |
---|---|---|---|
2 | 2 | ||
3 | These three features are already enabled by TCG, but are missing | 3 | and use a class AspeedSCUClass to define each SoC characteristics. |
4 | their hwcap bits. Update HWCAP2 from linux v5.12. | 4 | |
5 | 5 | Signed-off-by: Cédric Le Goater <clg@kaod.org> | |
6 | Cc: qemu-stable@nongnu.org (for 6.0.1) | 6 | Message-id: 20190904070506.1052-10-clg@kaod.org |
7 | Buglink: https://bugs.launchpad.net/bugs/1926044 | 7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Message-id: 20210427214108.88503-1-richard.henderson@linaro.org | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
11 | --- | 9 | --- |
12 | linux-user/elfload.c | 13 +++++++++++++ | 10 | include/hw/misc/aspeed_scu.h | 15 +++++++ |
13 | 1 file changed, 13 insertions(+) | 11 | hw/arm/aspeed_soc.c | 3 +- |
14 | 12 | hw/misc/aspeed_scu.c | 83 ++++++++++++++++++++---------------- | |
15 | diff --git a/linux-user/elfload.c b/linux-user/elfload.c | 13 | 3 files changed, 64 insertions(+), 37 deletions(-) |
14 | |||
15 | diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/linux-user/elfload.c | 17 | --- a/include/hw/misc/aspeed_scu.h |
18 | +++ b/linux-user/elfload.c | 18 | +++ b/include/hw/misc/aspeed_scu.h |
19 | @@ -XXX,XX +XXX,XX @@ enum { | 19 | @@ -XXX,XX +XXX,XX @@ |
20 | ARM_HWCAP2_A64_SVESM4 = 1 << 6, | 20 | |
21 | ARM_HWCAP2_A64_FLAGM2 = 1 << 7, | 21 | #define TYPE_ASPEED_SCU "aspeed.scu" |
22 | ARM_HWCAP2_A64_FRINT = 1 << 8, | 22 | #define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU) |
23 | + ARM_HWCAP2_A64_SVEI8MM = 1 << 9, | 23 | +#define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400" |
24 | + ARM_HWCAP2_A64_SVEF32MM = 1 << 10, | 24 | +#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500" |
25 | + ARM_HWCAP2_A64_SVEF64MM = 1 << 11, | 25 | |
26 | + ARM_HWCAP2_A64_SVEBF16 = 1 << 12, | 26 | #define ASPEED_SCU_NR_REGS (0x1A8 >> 2) |
27 | + ARM_HWCAP2_A64_I8MM = 1 << 13, | 27 | |
28 | + ARM_HWCAP2_A64_BF16 = 1 << 14, | 28 | @@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUState { |
29 | + ARM_HWCAP2_A64_DGH = 1 << 15, | 29 | |
30 | + ARM_HWCAP2_A64_RNG = 1 << 16, | 30 | extern bool is_supported_silicon_rev(uint32_t silicon_rev); |
31 | + ARM_HWCAP2_A64_BTI = 1 << 17, | 31 | |
32 | + ARM_HWCAP2_A64_MTE = 1 << 18, | 32 | +#define ASPEED_SCU_CLASS(klass) \ |
33 | + OBJECT_CLASS_CHECK(AspeedSCUClass, (klass), TYPE_ASPEED_SCU) | ||
34 | +#define ASPEED_SCU_GET_CLASS(obj) \ | ||
35 | + OBJECT_GET_CLASS(AspeedSCUClass, (obj), TYPE_ASPEED_SCU) | ||
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 | ||
49 | index XXXXXXX..XXXXXXX 100644 | ||
50 | --- a/hw/arm/aspeed_soc.c | ||
51 | +++ b/hw/arm/aspeed_soc.c | ||
52 | @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj) | ||
53 | &error_abort, NULL); | ||
54 | } | ||
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 */ | ||
33 | }; | 95 | }; |
34 | 96 | ||
35 | #define ELF_HWCAP get_elf_hwcap() | 97 | -static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s) |
36 | @@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap2(void) | 98 | +static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s) |
37 | GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP); | 99 | { |
38 | GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2); | 100 | uint32_t hpll_reg = s->regs[HPLL_PARAM]; |
39 | GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT); | 101 | uint8_t freq_select; |
40 | + GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG); | 102 | @@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s) |
41 | + GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI); | 103 | return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000; |
42 | + GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE); | 104 | } |
43 | 105 | ||
44 | return hwcaps; | 106 | -static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s) |
45 | } | 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); | ||
46 | -- | 200 | -- |
47 | 2.20.1 | 201 | 2.20.1 |
48 | 202 | ||
49 | 203 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | In tlbi_aa64_vae2is_write() the calculation | ||
2 | bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_E2 : ARMMMUIdx_SE2, | ||
3 | pageaddr) | ||
4 | 1 | ||
5 | has the two arms of the ?: expression reversed. Fix the bug. | ||
6 | |||
7 | Fixes: b6ad6062f1e5 | ||
8 | Reported-by: Rebecca Cran <rebecca@nuviainc.com> | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
11 | Reviewed-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com> | ||
12 | Reviewed-by: Rebecca Cran <rebecca@nuviainc.com> | ||
13 | Message-id: 20210420123106.10861-1-peter.maydell@linaro.org | ||
14 | --- | ||
15 | target/arm/helper.c | 2 +- | ||
16 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
17 | |||
18 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/target/arm/helper.c | ||
21 | +++ b/target/arm/helper.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
23 | uint64_t pageaddr = sextract64(value << 12, 0, 56); | ||
24 | bool secure = arm_is_secure_below_el3(env); | ||
25 | int mask = secure ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2; | ||
26 | - int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_E2 : ARMMMUIdx_SE2, | ||
27 | + int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2, | ||
28 | pageaddr); | ||
29 | |||
30 | tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits); | ||
31 | -- | ||
32 | 2.20.1 | ||
33 | |||
34 | diff view generated by jsdifflib |
1 | The AN524 FPGA image supports two memory maps, which differ in where | 1 | From: Cédric Le Goater <clg@kaod.org> |
---|---|---|---|
2 | the QSPI and BRAM are. In the default map, the BRAM is at | ||
3 | 0x0000_0000, and the QSPI at 0x2800_0000. In the second map, they | ||
4 | are the other way around. | ||
5 | 2 | ||
6 | In hardware, the initial mapping can be selected by the user by | 3 | The APB frequency can be calculated directly when needed from the |
7 | writing either "REMAP: BRAM" (the default) or "REMAP: QSPI" in the | 4 | HPLL_PARAM and CLK_SEL register values. This removes useless state in |
8 | board configuration file. The board config file is acted on by the | 5 | the model. |
9 | "Motherboard Configuration Controller", which is an entirely separate | ||
10 | microcontroller on the dev board but outside the FPGA. | ||
11 | 6 | ||
12 | The guest can also dynamically change the mapping via the SCC | 7 | Signed-off-by: Cédric Le Goater <clg@kaod.org> |
13 | CFG_REG0 register. | 8 | Message-id: 20190904070506.1052-11-clg@kaod.org |
9 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | --- | ||
12 | include/hw/misc/aspeed_scu.h | 8 +++----- | ||
13 | hw/misc/aspeed_scu.c | 25 +++++++++---------------- | ||
14 | hw/timer/aspeed_timer.c | 3 ++- | ||
15 | 3 files changed, 14 insertions(+), 22 deletions(-) | ||
14 | 16 | ||
15 | Implement this functionality for QEMU, using a machine property | 17 | diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h |
16 | "remap" with valid values "BRAM" and "QSPI" to allow the user to set | ||
17 | the initial mapping, in the same way they can on the FPGA, and | ||
18 | wiring up the bit from the SCC register to also switch the mapping. | ||
19 | |||
20 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
21 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
22 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
23 | Message-id: 20210504120912.23094-4-peter.maydell@linaro.org | ||
24 | --- | ||
25 | docs/system/arm/mps2.rst | 10 ++++ | ||
26 | hw/arm/mps2-tz.c | 108 ++++++++++++++++++++++++++++++++++++++- | ||
27 | 2 files changed, 117 insertions(+), 1 deletion(-) | ||
28 | |||
29 | diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst | ||
30 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
31 | --- a/docs/system/arm/mps2.rst | 19 | --- a/include/hw/misc/aspeed_scu.h |
32 | +++ b/docs/system/arm/mps2.rst | 20 | +++ b/include/hw/misc/aspeed_scu.h |
33 | @@ -XXX,XX +XXX,XX @@ Differences between QEMU and real hardware: | 21 | @@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUState { |
34 | flash, but only as simple ROM, so attempting to rewrite the flash | 22 | uint32_t hw_strap1; |
35 | from the guest will fail | 23 | uint32_t hw_strap2; |
36 | - QEMU does not model the USB controller in MPS3 boards | 24 | uint32_t hw_prot_key; |
25 | - | ||
26 | - uint32_t clkin; | ||
27 | - uint32_t hpll; | ||
28 | - uint32_t apb_freq; | ||
29 | } AspeedSCUState; | ||
30 | |||
31 | #define AST2400_A0_SILICON_REV 0x02000303U | ||
32 | @@ -XXX,XX +XXX,XX @@ typedef struct AspeedSCUClass { | ||
33 | SysBusDeviceClass parent_class; | ||
34 | |||
35 | const uint32_t *resets; | ||
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); | ||
37 | + | 44 | + |
38 | +Machine-specific options | 45 | /* |
39 | +"""""""""""""""""""""""" | 46 | * Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions |
40 | + | 47 | * were added. |
41 | +The following machine-specific options are supported: | 48 | diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c |
42 | + | ||
43 | +remap | ||
44 | + Supported for ``mps3-an524`` only. | ||
45 | + Set ``BRAM``/``QSPI`` to select the initial memory mapping. The | ||
46 | + default is ``BRAM``. | ||
47 | diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c | ||
48 | index XXXXXXX..XXXXXXX 100644 | 49 | index XXXXXXX..XXXXXXX 100644 |
49 | --- a/hw/arm/mps2-tz.c | 50 | --- a/hw/misc/aspeed_scu.c |
50 | +++ b/hw/arm/mps2-tz.c | 51 | +++ b/hw/misc/aspeed_scu.c |
51 | @@ -XXX,XX +XXX,XX @@ | 52 | @@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_scu_get_random(void) |
52 | #include "hw/boards.h" | 53 | return num; |
53 | #include "exec/address-spaces.h" | 54 | } |
54 | #include "sysemu/sysemu.h" | 55 | |
55 | +#include "sysemu/reset.h" | 56 | -static void aspeed_scu_set_apb_freq(AspeedSCUState *s) |
56 | #include "hw/misc/unimp.h" | 57 | +uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s) |
57 | #include "hw/char/cmsdk-apb-uart.h" | 58 | { |
58 | #include "hw/timer/cmsdk-apb-timer.h" | 59 | AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s); |
59 | @@ -XXX,XX +XXX,XX @@ | 60 | + uint32_t hpll = asc->calc_hpll(s, s->regs[HPLL_PARAM]); |
60 | #include "hw/core/split-irq.h" | 61 | |
61 | #include "hw/qdev-clock.h" | 62 | - s->apb_freq = s->hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1) |
62 | #include "qom/object.h" | 63 | + return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1) |
63 | +#include "hw/irq.h" | 64 | / asc->apb_divider; |
64 | 65 | } | |
65 | #define MPS2TZ_NUMIRQ_MAX 96 | 66 | |
66 | #define MPS2TZ_RAM_MAX 5 | 67 | @@ -XXX,XX +XXX,XX @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data, |
67 | @@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState { | 68 | return; |
68 | SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX]; | 69 | case CLK_SEL: |
69 | Clock *sysclk; | 70 | s->regs[reg] = data; |
70 | Clock *s32kclk; | 71 | - aspeed_scu_set_apb_freq(s); |
71 | + | 72 | break; |
72 | + bool remap; | 73 | case HW_STRAP1: |
73 | + qemu_irq remap_irq; | 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 */ | ||
74 | }; | 77 | }; |
75 | 78 | ||
76 | #define TYPE_MPS2TZ_MACHINE "mps2tz" | 79 | -static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s) |
77 | @@ -XXX,XX +XXX,XX @@ static const RAMInfo an505_raminfo[] = { { | 80 | +static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg) |
78 | }, | 81 | { |
79 | }; | 82 | - uint32_t hpll_reg = s->regs[HPLL_PARAM]; |
80 | 83 | uint8_t freq_select; | |
81 | +/* | 84 | bool clk_25m_in; |
82 | + * Note that the addresses and MPC numbering here should match up | 85 | + uint32_t clkin = aspeed_scu_get_clkin(s); |
83 | + * with those used in remap_memory(), which can swap the BRAM and QSPI. | 86 | |
84 | + */ | 87 | if (hpll_reg & SCU_AST2400_H_PLL_OFF) { |
85 | static const RAMInfo an524_raminfo[] = { { | 88 | return 0; |
86 | .name = "bram", | 89 | @@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s) |
87 | .base = 0x00000000, | 90 | multiplier = (2 - od) * ((n + 2) / (d + 1)); |
88 | @@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque, | 91 | } |
89 | 92 | ||
90 | object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC); | 93 | - return s->clkin * multiplier; |
91 | sccdev = DEVICE(scc); | 94 | + return clkin * multiplier; |
92 | + qdev_prop_set_uint32(sccdev, "scc-cfg0", mms->remap ? 1 : 0); | 95 | } |
93 | qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2); | 96 | |
94 | qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008); | 97 | /* HW strapping */ |
95 | qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id); | 98 | @@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s) |
96 | @@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque, | 99 | return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000; |
97 | return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); | ||
98 | } | 100 | } |
99 | 101 | ||
100 | +static hwaddr boot_mem_base(MPS2TZMachineState *mms) | 102 | -static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s) |
101 | +{ | 103 | +static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg) |
102 | + /* | 104 | { |
103 | + * Return the canonical address of the block which will be mapped | 105 | - uint32_t hpll_reg = s->regs[HPLL_PARAM]; |
104 | + * at address 0x0 (i.e. where the vector table is). | 106 | uint32_t multiplier = 1; |
105 | + * This is usually 0, but if the AN524 alternate memory map is | 107 | + uint32_t clkin = aspeed_scu_get_clkin(s); |
106 | + * enabled it will be the base address of the QSPI block. | 108 | |
107 | + */ | 109 | if (hpll_reg & SCU_H_PLL_OFF) { |
108 | + return mms->remap ? 0x28000000 : 0; | 110 | return 0; |
109 | +} | 111 | @@ -XXX,XX +XXX,XX @@ static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s) |
110 | + | 112 | multiplier = ((m + 1) / (n + 1)) / (p + 1); |
111 | +static void remap_memory(MPS2TZMachineState *mms, int map) | ||
112 | +{ | ||
113 | + /* | ||
114 | + * Remap the memory for the AN524. 'map' is the value of | ||
115 | + * SCC CFG_REG0 bit 0, i.e. 0 for the default map and 1 | ||
116 | + * for the "option 1" mapping where QSPI is at address 0. | ||
117 | + * | ||
118 | + * Effectively we need to swap around the "upstream" ends of | ||
119 | + * MPC 0 and MPC 1. | ||
120 | + */ | ||
121 | + MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms); | ||
122 | + int i; | ||
123 | + | ||
124 | + if (mmc->fpga_type != FPGA_AN524) { | ||
125 | + return; | ||
126 | + } | ||
127 | + | ||
128 | + memory_region_transaction_begin(); | ||
129 | + for (i = 0; i < 2; i++) { | ||
130 | + TZMPC *mpc = &mms->mpc[i]; | ||
131 | + MemoryRegion *upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); | ||
132 | + hwaddr addr = (i ^ map) ? 0x28000000 : 0; | ||
133 | + | ||
134 | + memory_region_set_address(upstream, addr); | ||
135 | + } | ||
136 | + memory_region_transaction_commit(); | ||
137 | +} | ||
138 | + | ||
139 | +static void remap_irq_fn(void *opaque, int n, int level) | ||
140 | +{ | ||
141 | + MPS2TZMachineState *mms = opaque; | ||
142 | + | ||
143 | + remap_memory(mms, level); | ||
144 | +} | ||
145 | + | ||
146 | static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque, | ||
147 | const char *name, hwaddr size, | ||
148 | const int *irqs) | ||
149 | @@ -XXX,XX +XXX,XX @@ static uint32_t boot_ram_size(MPS2TZMachineState *mms) | ||
150 | MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms); | ||
151 | |||
152 | for (p = mmc->raminfo; p->name; p++) { | ||
153 | - if (p->base == 0) { | ||
154 | + if (p->base == boot_mem_base(mms)) { | ||
155 | return p->size; | ||
156 | } | ||
157 | } | 113 | } |
158 | @@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine) | 114 | |
159 | 115 | - return s->clkin * multiplier; | |
160 | create_non_mpc_ram(mms); | 116 | + return clkin * multiplier; |
161 | |||
162 | + if (mmc->fpga_type == FPGA_AN524) { | ||
163 | + /* | ||
164 | + * Connect the line from the SCC so that we can remap when the | ||
165 | + * guest updates that register. | ||
166 | + */ | ||
167 | + mms->remap_irq = qemu_allocate_irq(remap_irq_fn, mms, 0); | ||
168 | + qdev_connect_gpio_out_named(DEVICE(&mms->scc), "remap", 0, | ||
169 | + mms->remap_irq); | ||
170 | + } | ||
171 | + | ||
172 | armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, | ||
173 | boot_ram_size(mms)); | ||
174 | } | 117 | } |
175 | @@ -XXX,XX +XXX,XX @@ static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address, | 118 | |
176 | *iregion = region; | 119 | static void aspeed_scu_reset(DeviceState *dev) |
120 | @@ -XXX,XX +XXX,XX @@ static void aspeed_scu_reset(DeviceState *dev) | ||
121 | s->regs[HW_STRAP1] = s->hw_strap1; | ||
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); | ||
177 | } | 131 | } |
178 | 132 | ||
179 | +static char *mps2_get_remap(Object *obj, Error **errp) | 133 | static uint32_t aspeed_silicon_revs[] = { |
180 | +{ | 134 | diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c |
181 | + MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj); | 135 | index XXXXXXX..XXXXXXX 100644 |
182 | + const char *val = mms->remap ? "QSPI" : "BRAM"; | 136 | --- a/hw/timer/aspeed_timer.c |
183 | + return g_strdup(val); | 137 | +++ b/hw/timer/aspeed_timer.c |
184 | +} | 138 | @@ -XXX,XX +XXX,XX @@ static inline uint32_t calculate_rate(struct AspeedTimer *t) |
185 | + | ||
186 | +static void mps2_set_remap(Object *obj, const char *value, Error **errp) | ||
187 | +{ | ||
188 | + MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj); | ||
189 | + | ||
190 | + if (!strcmp(value, "BRAM")) { | ||
191 | + mms->remap = false; | ||
192 | + } else if (!strcmp(value, "QSPI")) { | ||
193 | + mms->remap = true; | ||
194 | + } else { | ||
195 | + error_setg(errp, "Invalid remap value"); | ||
196 | + error_append_hint(errp, "Valid values are BRAM and QSPI.\n"); | ||
197 | + } | ||
198 | +} | ||
199 | + | ||
200 | +static void mps2_machine_reset(MachineState *machine) | ||
201 | +{ | ||
202 | + MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine); | ||
203 | + | ||
204 | + /* | ||
205 | + * Set the initial memory mapping before triggering the reset of | ||
206 | + * the rest of the system, so that the guest image loader and CPU | ||
207 | + * reset see the correct mapping. | ||
208 | + */ | ||
209 | + remap_memory(mms, mms->remap); | ||
210 | + qemu_devices_reset(); | ||
211 | +} | ||
212 | + | ||
213 | static void mps2tz_class_init(ObjectClass *oc, void *data) | ||
214 | { | 139 | { |
215 | MachineClass *mc = MACHINE_CLASS(oc); | 140 | AspeedTimerCtrlState *s = timer_to_ctrl(t); |
216 | IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc); | 141 | |
217 | 142 | - return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ : s->scu->apb_freq; | |
218 | mc->init = mps2tz_common_init; | 143 | + return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ : |
219 | + mc->reset = mps2_machine_reset; | 144 | + aspeed_scu_get_apb_freq(s->scu); |
220 | iic->check = mps2_tz_idau_check; | ||
221 | } | 145 | } |
222 | 146 | ||
223 | @@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data) | 147 | static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t now_ns) |
224 | mmc->raminfo = an524_raminfo; | ||
225 | mmc->armsse_type = TYPE_SSE200; | ||
226 | mps2tz_set_default_ram_info(mmc); | ||
227 | + | ||
228 | + object_class_property_add_str(oc, "remap", mps2_get_remap, mps2_set_remap); | ||
229 | + object_class_property_set_description(oc, "remap", | ||
230 | + "Set memory mapping. Valid values " | ||
231 | + "are BRAM (default) and QSPI."); | ||
232 | } | ||
233 | |||
234 | static void mps3tz_an547_class_init(ObjectClass *oc, void *data) | ||
235 | -- | 148 | -- |
236 | 2.20.1 | 149 | 2.20.1 |
237 | 150 | ||
238 | 151 | diff view generated by jsdifflib |
1 | From: Guenter Roeck <linux@roeck-us.net> | 1 | From: "Emilio G. Cota" <cota@braap.org> |
---|---|---|---|
2 | 2 | ||
3 | Commit dfc388797cc4 ("hw/arm: xlnx: Set all boards' GEM 'phy-addr' | 3 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
4 | property value to 23") configured the PHY address for xilinx-zynq-a9 | 4 | Signed-off-by: Emilio G. Cota <cota@braap.org> |
5 | to 23. When trying to boot xilinx-zynq-a9 with zynq-zc702.dtb or | 5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
6 | zynq-zc706.dtb, this results in the following error message when | 6 | Signed-off-by: Alex Bennée <alex.bennee@linaro.org> |
7 | trying to use the Ethernet interface. | ||
8 | |||
9 | macb e000b000.ethernet eth0: Could not attach PHY (-19) | ||
10 | |||
11 | The devicetree files for ZC702 and ZC706 configure PHY address 7. The | ||
12 | documentation for the ZC702 and ZC706 evaluation boards suggest that the | ||
13 | PHY address is 7, not 23. Other boards use PHY address 0, 1, 3, or 7. | ||
14 | I was unable to find a documentation or a devicetree file suggesting | ||
15 | or using PHY address 23. The Ethernet interface starts working with | ||
16 | zynq-zc702.dtb and zynq-zc706.dtb when setting the PHY address to 7, | ||
17 | so let's use it. | ||
18 | |||
19 | Cc: Bin Meng <bin.meng@windriver.com> | ||
20 | Signed-off-by: Guenter Roeck <linux@roeck-us.net> | ||
21 | Reviewed-by: Bin Meng <bmeng.cn@gmail.com> | ||
22 | Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
23 | Message-id: 20210504124140.1100346-1-linux@roeck-us.net | ||
24 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
25 | --- | 8 | --- |
26 | hw/arm/xilinx_zynq.c | 2 +- | 9 | accel/tcg/atomic_template.h | 2 +- |
27 | 1 file changed, 1 insertion(+), 1 deletion(-) | 10 | 1 file changed, 1 insertion(+), 1 deletion(-) |
28 | 11 | ||
29 | diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c | 12 | diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h |
30 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
31 | --- a/hw/arm/xilinx_zynq.c | 14 | --- a/accel/tcg/atomic_template.h |
32 | +++ b/hw/arm/xilinx_zynq.c | 15 | +++ b/accel/tcg/atomic_template.h |
33 | @@ -XXX,XX +XXX,XX @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq) | 16 | @@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, |
34 | qemu_check_nic_model(nd, TYPE_CADENCE_GEM); | 17 | |
35 | qdev_set_nic_properties(dev, nd); | 18 | #define GEN_ATOMIC_HELPER(X) \ |
36 | } | 19 | ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ |
37 | - object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort); | 20 | - ABI_TYPE val EXTRA_ARGS) \ |
38 | + object_property_set_int(OBJECT(dev), "phy-addr", 7, &error_abort); | 21 | + ABI_TYPE val EXTRA_ARGS) \ |
39 | s = SYS_BUS_DEVICE(dev); | 22 | { \ |
40 | sysbus_realize_and_unref(s, &error_fatal); | 23 | ATOMIC_MMU_DECLS; \ |
41 | sysbus_mmio_map(s, 0, base); | 24 | DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \ |
42 | -- | 25 | -- |
43 | 2.20.1 | 26 | 2.20.1 |
44 | 27 | ||
45 | 28 | diff view generated by jsdifflib |
1 | We want to split out the .c.inc files which are currently included | 1 | The qemu-ga documentation is currently in qemu-ga.texi in |
---|---|---|---|
2 | into translate.c so they are separate compilation units. To do this | 2 | Texinfo format, which we present to the user as: |
3 | we need to make some functions which are currently file-local to | 3 | * a qemu-ga manpage |
4 | translate.c have global scope; create a translate-a32.h paralleling | 4 | * a section of the main qemu-doc HTML documentation |
5 | the existing translate-a64.h as a place for these declarations to | ||
6 | live, so that code moved into the new compilation units can call | ||
7 | them. | ||
8 | 5 | ||
9 | The functions made global here are those required by the | 6 | Convert the documentation to rST format, and present it to |
10 | m-nocp.decode functions, except that I have converted the whole | 7 | the user as: |
11 | family of {read,write}_neon_element* and also both the load_cpu and | 8 | * a qemu-ga manpage |
12 | store_cpu functions for consistency, even though m-nocp only wants a | 9 | * part of the interop/ Sphinx manual |
13 | few functions from each. | ||
14 | 10 | ||
15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
16 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | 12 | Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com> |
17 | Message-id: 20210430132740.10391-4-peter.maydell@linaro.org | 13 | Tested-by: Michael Roth <mdroth@linux.vnet.ibm.com> |
14 | Message-id: 20190905131040.8350-1-peter.maydell@linaro.org | ||
18 | --- | 15 | --- |
19 | target/arm/translate-a32.h | 57 ++++++++++++++++++++++++++++++++++ | 16 | Makefile | 24 ++++--- |
20 | target/arm/translate.c | 39 +++++------------------ | 17 | MAINTAINERS | 2 +- |
21 | target/arm/translate-vfp.c.inc | 2 +- | 18 | docs/conf.py | 18 ++--- |
22 | 3 files changed, 65 insertions(+), 33 deletions(-) | 19 | docs/interop/conf.py | 7 ++ |
23 | create mode 100644 target/arm/translate-a32.h | 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 | ||
24 | 27 | ||
25 | diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h | 28 | diff --git a/Makefile b/Makefile |
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/Makefile | ||
31 | +++ b/Makefile | ||
32 | @@ -XXX,XX +XXX,XX @@ endif | ||
33 | endif | ||
34 | |||
35 | ifdef BUILD_DOCS | ||
36 | -DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8 | ||
37 | +DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 docs/interop/qemu-ga.8 | ||
38 | DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7 | ||
39 | DOCS+=docs/interop/qemu-ga-ref.html docs/interop/qemu-ga-ref.txt docs/interop/qemu-ga-ref.7 | ||
40 | DOCS+=docs/qemu-block-drivers.7 | ||
41 | @@ -XXX,XX +XXX,XX @@ DESCS= | ||
42 | endif | ||
43 | |||
44 | # Note that we manually filter-out the non-Sphinx documentation which | ||
45 | -# is currently built into the docs/interop directory in the build tree. | ||
46 | +# is currently built into the docs/interop directory in the build tree, | ||
47 | +# and also any sphinx-built manpages. | ||
48 | define install-manual = | ||
49 | for d in $$(cd $(MANUAL_BUILDDIR) && find $1 -type d); do $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)/$$d"; done | ||
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 | ||
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 | ||
52 | endef | ||
53 | |||
54 | # Note that we deliberately do not install the "devel" manual: it is | ||
55 | @@ -XXX,XX +XXX,XX @@ ifdef CONFIG_TRACE_SYSTEMTAP | ||
56 | $(INSTALL_DATA) scripts/qemu-trace-stap.1 "$(DESTDIR)$(mandir)/man1" | ||
57 | endif | ||
58 | ifneq (,$(findstring qemu-ga,$(TOOLS))) | ||
59 | - $(INSTALL_DATA) qemu-ga.8 "$(DESTDIR)$(mandir)/man8" | ||
60 | + $(INSTALL_DATA) docs/interop/qemu-ga.8 "$(DESTDIR)$(mandir)/man8" | ||
61 | $(INSTALL_DATA) docs/interop/qemu-ga-ref.html "$(DESTDIR)$(qemu_docdir)" | ||
62 | $(INSTALL_DATA) docs/interop/qemu-ga-ref.txt "$(DESTDIR)$(qemu_docdir)" | ||
63 | $(INSTALL_DATA) docs/interop/qemu-ga-ref.7 "$(DESTDIR)$(mandir)/man7" | ||
64 | @@ -XXX,XX +XXX,XX @@ docs/version.texi: $(SRC_PATH)/VERSION config-host.mak | ||
65 | sphinxdocs: $(MANUAL_BUILDDIR)/devel/index.html $(MANUAL_BUILDDIR)/interop/index.html $(MANUAL_BUILDDIR)/specs/index.html | ||
66 | |||
67 | # Canned command to build a single manual | ||
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") | ||
69 | +# Arguments: $1 = manual name, $2 = Sphinx builder ('html' or 'man') | ||
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") | ||
71 | # We assume all RST files in the manual's directory are used in it | ||
72 | manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst) $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py | ||
73 | |||
74 | $(MANUAL_BUILDDIR)/devel/index.html: $(call manual-deps,devel) | ||
75 | - $(call build-manual,devel) | ||
76 | + $(call build-manual,devel,html) | ||
77 | |||
78 | $(MANUAL_BUILDDIR)/interop/index.html: $(call manual-deps,interop) | ||
79 | - $(call build-manual,interop) | ||
80 | + $(call build-manual,interop,html) | ||
81 | |||
82 | $(MANUAL_BUILDDIR)/specs/index.html: $(call manual-deps,specs) | ||
83 | - $(call build-manual,specs) | ||
84 | + $(call build-manual,specs,html) | ||
85 | + | ||
86 | +$(MANUAL_BUILDDIR)/interop/qemu-ga.8: $(call manual-deps,interop) | ||
87 | + $(call build-manual,interop,man) | ||
88 | |||
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 | ||
26 | new file mode 100644 | 184 | new file mode 100644 |
27 | index XXXXXXX..XXXXXXX | 185 | index XXXXXXX..XXXXXXX |
28 | --- /dev/null | 186 | --- /dev/null |
29 | +++ b/target/arm/translate-a32.h | 187 | +++ b/docs/interop/qemu-ga.rst |
30 | @@ -XXX,XX +XXX,XX @@ | 188 | @@ -XXX,XX +XXX,XX @@ |
31 | +/* | 189 | +QEMU Guest Agent |
32 | + * AArch32 translation, common definitions. | 190 | +================ |
33 | + * | 191 | + |
34 | + * Copyright (c) 2021 Linaro, Ltd. | 192 | +Synopsis |
35 | + * | 193 | +-------- |
36 | + * This library is free software; you can redistribute it and/or | 194 | + |
37 | + * modify it under the terms of the GNU Lesser General Public | 195 | +**qemu-ga** [*OPTIONS*] |
38 | + * License as published by the Free Software Foundation; either | 196 | + |
39 | + * version 2.1 of the License, or (at your option) any later version. | 197 | +Description |
40 | + * | 198 | +----------- |
41 | + * This library is distributed in the hope that it will be useful, | 199 | + |
42 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | 200 | +The QEMU Guest Agent is a daemon intended to be run within virtual |
43 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 201 | +machines. It allows the hypervisor host to perform various operations |
44 | + * Lesser General Public License for more details. | 202 | +in the guest, such as: |
45 | + * | 203 | + |
46 | + * You should have received a copy of the GNU Lesser General Public | 204 | +- get information from the guest |
47 | + * License along with this library; if not, see <http://www.gnu.org/licenses/>. | 205 | +- set the guest's system time |
48 | + */ | 206 | +- read/write a file |
49 | + | 207 | +- sync and freeze the filesystems |
50 | +#ifndef TARGET_ARM_TRANSLATE_A64_H | 208 | +- suspend the guest |
51 | +#define TARGET_ARM_TRANSLATE_A64_H | 209 | +- reconfigure guest local processors |
52 | + | 210 | +- set user's password |
53 | +void load_reg_var(DisasContext *s, TCGv_i32 var, int reg); | 211 | +- ... |
54 | +void arm_gen_condlabel(DisasContext *s); | 212 | + |
55 | +bool vfp_access_check(DisasContext *s); | 213 | +qemu-ga will read a system configuration file on startup (located at |
56 | +void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop); | 214 | +|CONFDIR|\ ``/qemu-ga.conf`` by default), then parse remaining |
57 | +void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop); | 215 | +configuration options on the command line. For the same key, the last |
58 | +void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop); | 216 | +option wins, but the lists accumulate (see below for configuration |
59 | +void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop); | 217 | +file format). |
60 | + | 218 | + |
61 | +static inline TCGv_i32 load_cpu_offset(int offset) | 219 | +Options |
62 | +{ | 220 | +------- |
63 | + TCGv_i32 tmp = tcg_temp_new_i32(); | 221 | + |
64 | + tcg_gen_ld_i32(tmp, cpu_env, offset); | 222 | +.. program:: qemu-ga |
65 | + return tmp; | 223 | + |
66 | +} | 224 | +.. option:: -m, --method=METHOD |
67 | + | 225 | + |
68 | +#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name)) | 226 | + Transport method: one of ``unix-listen``, ``virtio-serial``, or |
69 | + | 227 | + ``isa-serial`` (``virtio-serial`` is the default). |
70 | +static inline void store_cpu_offset(TCGv_i32 var, int offset) | 228 | + |
71 | +{ | 229 | +.. option:: -p, --path=PATH |
72 | + tcg_gen_st_i32(var, cpu_env, offset); | 230 | + |
73 | + tcg_temp_free_i32(var); | 231 | + Device/socket path (the default for virtio-serial is |
74 | +} | 232 | + ``/dev/virtio-ports/org.qemu.guest_agent.0``, |
75 | + | 233 | + the default for isa-serial is ``/dev/ttyS0``) |
76 | +#define store_cpu_field(var, name) \ | 234 | + |
77 | + store_cpu_offset(var, offsetof(CPUARMState, name)) | 235 | +.. option:: -l, --logfile=PATH |
78 | + | 236 | + |
79 | +/* Create a new temporary and set it to the value of a CPU register. */ | 237 | + Set log file path (default is stderr). |
80 | +static inline TCGv_i32 load_reg(DisasContext *s, int reg) | 238 | + |
81 | +{ | 239 | +.. option:: -f, --pidfile=PATH |
82 | + TCGv_i32 tmp = tcg_temp_new_i32(); | 240 | + |
83 | + load_reg_var(s, tmp, reg); | 241 | + Specify pid file (default is ``/var/run/qemu-ga.pid``). |
84 | + return tmp; | 242 | + |
85 | +} | 243 | +.. option:: -F, --fsfreeze-hook=PATH |
86 | + | 244 | + |
87 | +#endif | 245 | + Enable fsfreeze hook. Accepts an optional argument that specifies |
88 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 246 | + script to run on freeze/thaw. Script will be called with |
89 | index XXXXXXX..XXXXXXX 100644 | 247 | + 'freeze'/'thaw' arguments accordingly (default is |
90 | --- a/target/arm/translate.c | 248 | + |CONFDIR|\ ``/fsfreeze-hook``). If using -F with an argument, do |
91 | +++ b/target/arm/translate.c | 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 | ||
92 | @@ -XXX,XX +XXX,XX @@ | 343 | @@ -XXX,XX +XXX,XX @@ |
93 | #define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8) | 344 | -@example |
94 | 345 | -@c man begin SYNOPSIS | |
95 | #include "translate.h" | 346 | -@command{qemu-ga} [@var{OPTIONS}] |
96 | +#include "translate-a32.h" | 347 | -@c man end |
97 | 348 | -@end example | |
98 | #if defined(CONFIG_USER_ONLY) | 349 | - |
99 | #define IS_USER(s) 1 | 350 | -@c man begin DESCRIPTION |
100 | @@ -XXX,XX +XXX,XX @@ void arm_translate_init(void) | 351 | - |
101 | } | 352 | -The QEMU Guest Agent is a daemon intended to be run within virtual |
102 | 353 | -machines. It allows the hypervisor host to perform various operations | |
103 | /* Generate a label used for skipping this instruction */ | 354 | -in the guest, such as: |
104 | -static void arm_gen_condlabel(DisasContext *s) | 355 | - |
105 | +void arm_gen_condlabel(DisasContext *s) | 356 | -@itemize |
106 | { | 357 | -@item |
107 | if (!s->condjmp) { | 358 | -get information from the guest |
108 | s->condlabel = gen_new_label(); | 359 | -@item |
109 | @@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s) | 360 | -set the guest's system time |
110 | } | 361 | -@item |
111 | } | 362 | -read/write a file |
112 | 363 | -@item | |
113 | -static inline TCGv_i32 load_cpu_offset(int offset) | 364 | -sync and freeze the filesystems |
114 | -{ | 365 | -@item |
115 | - TCGv_i32 tmp = tcg_temp_new_i32(); | 366 | -suspend the guest |
116 | - tcg_gen_ld_i32(tmp, cpu_env, offset); | 367 | -@item |
117 | - return tmp; | 368 | -reconfigure guest local processors |
118 | -} | 369 | -@item |
119 | - | 370 | -set user's password |
120 | -#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name)) | 371 | -@item |
121 | - | 372 | -... |
122 | -static inline void store_cpu_offset(TCGv_i32 var, int offset) | 373 | -@end itemize |
123 | -{ | 374 | - |
124 | - tcg_gen_st_i32(var, cpu_env, offset); | 375 | -qemu-ga will read a system configuration file on startup (located at |
125 | - tcg_temp_free_i32(var); | 376 | -@file{@value{CONFDIR}/qemu-ga.conf} by default), then parse remaining |
126 | -} | 377 | -configuration options on the command line. For the same key, the last |
127 | - | 378 | -option wins, but the lists accumulate (see below for configuration |
128 | -#define store_cpu_field(var, name) \ | 379 | -file format). |
129 | - store_cpu_offset(var, offsetof(CPUARMState, name)) | 380 | - |
130 | - | 381 | -@c man end |
131 | /* The architectural value of PC. */ | 382 | - |
132 | static uint32_t read_pc(DisasContext *s) | 383 | -@c man begin OPTIONS |
133 | { | 384 | -@table @option |
134 | @@ -XXX,XX +XXX,XX @@ static uint32_t read_pc(DisasContext *s) | 385 | -@item -m, --method=@var{method} |
135 | } | 386 | - Transport method: one of @samp{unix-listen}, @samp{virtio-serial}, or |
136 | 387 | - @samp{isa-serial} (@samp{virtio-serial} is the default). | |
137 | /* Set a variable to the value of a CPU register. */ | 388 | - |
138 | -static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg) | 389 | -@item -p, --path=@var{path} |
139 | +void load_reg_var(DisasContext *s, TCGv_i32 var, int reg) | 390 | - Device/socket path (the default for virtio-serial is |
140 | { | 391 | - @samp{/dev/virtio-ports/org.qemu.guest_agent.0}, |
141 | if (reg == 15) { | 392 | - the default for isa-serial is @samp{/dev/ttyS0}) |
142 | tcg_gen_movi_i32(var, read_pc(s)); | 393 | - |
143 | @@ -XXX,XX +XXX,XX @@ static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg) | 394 | -@item -l, --logfile=@var{path} |
144 | } | 395 | - Set log file path (default is stderr). |
145 | } | 396 | - |
146 | 397 | -@item -f, --pidfile=@var{path} | |
147 | -/* Create a new temporary and set it to the value of a CPU register. */ | 398 | - Specify pid file (default is @samp{/var/run/qemu-ga.pid}). |
148 | -static inline TCGv_i32 load_reg(DisasContext *s, int reg) | 399 | - |
149 | -{ | 400 | -@item -F, --fsfreeze-hook=@var{path} |
150 | - TCGv_i32 tmp = tcg_temp_new_i32(); | 401 | - Enable fsfreeze hook. Accepts an optional argument that specifies |
151 | - load_reg_var(s, tmp, reg); | 402 | - script to run on freeze/thaw. Script will be called with |
152 | - return tmp; | 403 | - 'freeze'/'thaw' arguments accordingly (default is |
153 | -} | 404 | - @samp{@value{CONFDIR}/fsfreeze-hook}). If using -F with an argument, do |
154 | - | 405 | - not follow -F with a space (for example: |
155 | /* | 406 | - @samp{-F/var/run/fsfreezehook.sh}). |
156 | * Create a new temp, REG + OFS, except PC is ALIGN(PC, 4). | 407 | - |
157 | * This is used for load/store for which use of PC implies (literal), | 408 | -@item -t, --statedir=@var{path} |
158 | @@ -XXX,XX +XXX,XX @@ static inline void vfp_store_reg32(TCGv_i32 var, int reg) | 409 | - Specify the directory to store state information (absolute paths only, |
159 | tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg)); | 410 | - default is @samp{/var/run}). |
160 | } | 411 | - |
161 | 412 | -@item -v, --verbose | |
162 | -static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop) | 413 | - Log extra debugging information. |
163 | +void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop) | 414 | - |
164 | { | 415 | -@item -V, --version |
165 | long off = neon_element_offset(reg, ele, memop); | 416 | - Print version information and exit. |
166 | 417 | - | |
167 | @@ -XXX,XX +XXX,XX @@ static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop) | 418 | -@item -d, --daemon |
168 | } | 419 | - Daemonize after startup (detach from terminal). |
169 | } | 420 | - |
170 | 421 | -@item -b, --blacklist=@var{list} | |
171 | -static void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop) | 422 | - Comma-separated list of RPCs to disable (no spaces, @samp{?} to list |
172 | +void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop) | 423 | - available RPCs). |
173 | { | 424 | - |
174 | long off = neon_element_offset(reg, ele, memop); | 425 | -@item -D, --dump-conf |
175 | 426 | - Dump the configuration in a format compatible with @file{qemu-ga.conf} | |
176 | @@ -XXX,XX +XXX,XX @@ static void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop) | 427 | - and exit. |
177 | } | 428 | - |
178 | } | 429 | -@item -h, --help |
179 | 430 | - Display this help and exit. | |
180 | -static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop) | 431 | -@end table |
181 | +void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop) | 432 | - |
182 | { | 433 | -@c man end |
183 | long off = neon_element_offset(reg, ele, memop); | 434 | - |
184 | 435 | -@c man begin FILES | |
185 | @@ -XXX,XX +XXX,XX @@ static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop) | 436 | - |
186 | } | 437 | -The syntax of the @file{qemu-ga.conf} configuration file follows the |
187 | } | 438 | -Desktop Entry Specification, here is a quick summary: it consists of |
188 | 439 | -groups of key-value pairs, interspersed with comments. | |
189 | -static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop) | 440 | - |
190 | +void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop) | 441 | -@example |
191 | { | 442 | -# qemu-ga configuration sample |
192 | long off = neon_element_offset(reg, ele, memop); | 443 | -[general] |
193 | 444 | -daemonize = 0 | |
194 | diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc | 445 | -pidfile = /var/run/qemu-ga.pid |
195 | index XXXXXXX..XXXXXXX 100644 | 446 | -verbose = 0 |
196 | --- a/target/arm/translate-vfp.c.inc | 447 | -method = virtio-serial |
197 | +++ b/target/arm/translate-vfp.c.inc | 448 | -path = /dev/virtio-ports/org.qemu.guest_agent.0 |
198 | @@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled) | 449 | -statedir = /var/run |
199 | * The most usual kind of VFP access check, for everything except | 450 | -@end example |
200 | * FMXR/FMRX to the always-available special registers. | 451 | - |
201 | */ | 452 | -The list of keys follows the command line options: |
202 | -static bool vfp_access_check(DisasContext *s) | 453 | -@table @option |
203 | +bool vfp_access_check(DisasContext *s) | 454 | -@item daemon= boolean |
204 | { | 455 | -@item method= string |
205 | return full_vfp_access_check(s, false); | 456 | -@item path= string |
206 | } | 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 | ||
207 | -- | 481 | -- |
208 | 2.20.1 | 482 | 2.20.1 |
209 | 483 | ||
210 | 484 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Make the remaining functions which are needed by translate-vfp.c.inc | ||
2 | global. | ||
3 | 1 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20210430132740.10391-8-peter.maydell@linaro.org | ||
8 | --- | ||
9 | target/arm/translate-a32.h | 18 ++++++++++++++++++ | ||
10 | target/arm/translate.c | 25 ++++++++----------------- | ||
11 | 2 files changed, 26 insertions(+), 17 deletions(-) | ||
12 | |||
13 | diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/arm/translate-a32.h | ||
16 | +++ b/target/arm/translate-a32.h | ||
17 | @@ -XXX,XX +XXX,XX @@ void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop); | ||
18 | void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop); | ||
19 | void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop); | ||
20 | void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop); | ||
21 | +TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs); | ||
22 | +void gen_set_cpsr(TCGv_i32 var, uint32_t mask); | ||
23 | +void gen_set_condexec(DisasContext *s); | ||
24 | +void gen_set_pc_im(DisasContext *s, target_ulong val); | ||
25 | +void gen_lookup_tb(DisasContext *s); | ||
26 | +long vfp_reg_offset(bool dp, unsigned reg); | ||
27 | +long neon_full_reg_offset(unsigned reg); | ||
28 | |||
29 | static inline TCGv_i32 load_cpu_offset(int offset) | ||
30 | { | ||
31 | @@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg) | ||
32 | return tmp; | ||
33 | } | ||
34 | |||
35 | +void store_reg(DisasContext *s, int reg, TCGv_i32 var); | ||
36 | + | ||
37 | void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val, | ||
38 | TCGv_i32 a32, int index, MemOp opc); | ||
39 | void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val, | ||
40 | @@ -XXX,XX +XXX,XX @@ DO_GEN_ST(32, MO_UL) | ||
41 | #undef DO_GEN_LD | ||
42 | #undef DO_GEN_ST | ||
43 | |||
44 | +#if defined(CONFIG_USER_ONLY) | ||
45 | +#define IS_USER(s) 1 | ||
46 | +#else | ||
47 | +#define IS_USER(s) (s->user) | ||
48 | +#endif | ||
49 | + | ||
50 | +/* Set NZCV flags from the high 4 bits of var. */ | ||
51 | +#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV) | ||
52 | + | ||
53 | #endif | ||
54 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/target/arm/translate.c | ||
57 | +++ b/target/arm/translate.c | ||
58 | @@ -XXX,XX +XXX,XX @@ | ||
59 | #include "translate.h" | ||
60 | #include "translate-a32.h" | ||
61 | |||
62 | -#if defined(CONFIG_USER_ONLY) | ||
63 | -#define IS_USER(s) 1 | ||
64 | -#else | ||
65 | -#define IS_USER(s) (s->user) | ||
66 | -#endif | ||
67 | - | ||
68 | /* These are TCG temporaries used only by the legacy iwMMXt decoder */ | ||
69 | static TCGv_i64 cpu_V0, cpu_V1, cpu_M0; | ||
70 | /* These are TCG globals which alias CPUARMState fields */ | ||
71 | @@ -XXX,XX +XXX,XX @@ void load_reg_var(DisasContext *s, TCGv_i32 var, int reg) | ||
72 | * This is used for load/store for which use of PC implies (literal), | ||
73 | * or ADD that implies ADR. | ||
74 | */ | ||
75 | -static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs) | ||
76 | +TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs) | ||
77 | { | ||
78 | TCGv_i32 tmp = tcg_temp_new_i32(); | ||
79 | |||
80 | @@ -XXX,XX +XXX,XX @@ static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs) | ||
81 | |||
82 | /* Set a CPU register. The source must be a temporary and will be | ||
83 | marked as dead. */ | ||
84 | -static void store_reg(DisasContext *s, int reg, TCGv_i32 var) | ||
85 | +void store_reg(DisasContext *s, int reg, TCGv_i32 var) | ||
86 | { | ||
87 | if (reg == 15) { | ||
88 | /* In Thumb mode, we must ignore bit 0. | ||
89 | @@ -XXX,XX +XXX,XX @@ static void store_sp_checked(DisasContext *s, TCGv_i32 var) | ||
90 | #define gen_sxtb16(var) gen_helper_sxtb16(var, var) | ||
91 | #define gen_uxtb16(var) gen_helper_uxtb16(var, var) | ||
92 | |||
93 | - | ||
94 | -static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask) | ||
95 | +void gen_set_cpsr(TCGv_i32 var, uint32_t mask) | ||
96 | { | ||
97 | TCGv_i32 tmp_mask = tcg_const_i32(mask); | ||
98 | gen_helper_cpsr_write(cpu_env, var, tmp_mask); | ||
99 | tcg_temp_free_i32(tmp_mask); | ||
100 | } | ||
101 | -/* Set NZCV flags from the high 4 bits of var. */ | ||
102 | -#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV) | ||
103 | |||
104 | static void gen_exception_internal(int excp) | ||
105 | { | ||
106 | @@ -XXX,XX +XXX,XX @@ void arm_gen_test_cc(int cc, TCGLabel *label) | ||
107 | arm_free_cc(&cmp); | ||
108 | } | ||
109 | |||
110 | -static inline void gen_set_condexec(DisasContext *s) | ||
111 | +void gen_set_condexec(DisasContext *s) | ||
112 | { | ||
113 | if (s->condexec_mask) { | ||
114 | uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); | ||
115 | @@ -XXX,XX +XXX,XX @@ static inline void gen_set_condexec(DisasContext *s) | ||
116 | } | ||
117 | } | ||
118 | |||
119 | -static inline void gen_set_pc_im(DisasContext *s, target_ulong val) | ||
120 | +void gen_set_pc_im(DisasContext *s, target_ulong val) | ||
121 | { | ||
122 | tcg_gen_movi_i32(cpu_R[15], val); | ||
123 | } | ||
124 | @@ -XXX,XX +XXX,XX @@ static void gen_exception_el(DisasContext *s, int excp, uint32_t syn, | ||
125 | } | ||
126 | |||
127 | /* Force a TB lookup after an instruction that changes the CPU state. */ | ||
128 | -static inline void gen_lookup_tb(DisasContext *s) | ||
129 | +void gen_lookup_tb(DisasContext *s) | ||
130 | { | ||
131 | tcg_gen_movi_i32(cpu_R[15], s->base.pc_next); | ||
132 | s->base.is_jmp = DISAS_EXIT; | ||
133 | @@ -XXX,XX +XXX,XX @@ static inline void gen_hlt(DisasContext *s, int imm) | ||
134 | /* | ||
135 | * Return the offset of a "full" NEON Dreg. | ||
136 | */ | ||
137 | -static long neon_full_reg_offset(unsigned reg) | ||
138 | +long neon_full_reg_offset(unsigned reg) | ||
139 | { | ||
140 | return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]); | ||
141 | } | ||
142 | @@ -XXX,XX +XXX,XX @@ static long neon_element_offset(int reg, int element, MemOp memop) | ||
143 | } | ||
144 | |||
145 | /* Return the offset of a VFP Dreg (dp = true) or VFP Sreg (dp = false). */ | ||
146 | -static long vfp_reg_offset(bool dp, unsigned reg) | ||
147 | +long vfp_reg_offset(bool dp, unsigned reg) | ||
148 | { | ||
149 | if (dp) { | ||
150 | return neon_element_offset(reg, 0, MO_64); | ||
151 | -- | ||
152 | 2.20.1 | ||
153 | |||
154 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Switch translate-vfp.c.inc from being #included into translate.c | ||
2 | to being its own compilation unit. | ||
3 | 1 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20210430132740.10391-9-peter.maydell@linaro.org | ||
8 | --- | ||
9 | target/arm/translate-a32.h | 2 ++ | ||
10 | target/arm/{translate-vfp.c.inc => translate-vfp.c} | 12 +++++++----- | ||
11 | target/arm/translate.c | 3 +-- | ||
12 | target/arm/meson.build | 5 +++-- | ||
13 | 4 files changed, 13 insertions(+), 9 deletions(-) | ||
14 | rename target/arm/{translate-vfp.c.inc => translate-vfp.c} (99%) | ||
15 | |||
16 | diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/target/arm/translate-a32.h | ||
19 | +++ b/target/arm/translate-a32.h | ||
20 | @@ -XXX,XX +XXX,XX @@ | ||
21 | |||
22 | /* Prototypes for autogenerated disassembler functions */ | ||
23 | bool disas_m_nocp(DisasContext *dc, uint32_t insn); | ||
24 | +bool disas_vfp(DisasContext *s, uint32_t insn); | ||
25 | +bool disas_vfp_uncond(DisasContext *s, uint32_t insn); | ||
26 | |||
27 | void load_reg_var(DisasContext *s, TCGv_i32 var, int reg); | ||
28 | void arm_gen_condlabel(DisasContext *s); | ||
29 | diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c | ||
30 | similarity index 99% | ||
31 | rename from target/arm/translate-vfp.c.inc | ||
32 | rename to target/arm/translate-vfp.c | ||
33 | index XXXXXXX..XXXXXXX 100644 | ||
34 | --- a/target/arm/translate-vfp.c.inc | ||
35 | +++ b/target/arm/translate-vfp.c | ||
36 | @@ -XXX,XX +XXX,XX @@ | ||
37 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
38 | */ | ||
39 | |||
40 | -/* | ||
41 | - * This file is intended to be included from translate.c; it uses | ||
42 | - * some macros and definitions provided by that file. | ||
43 | - * It might be possible to convert it to a standalone .c file eventually. | ||
44 | - */ | ||
45 | +#include "qemu/osdep.h" | ||
46 | +#include "tcg/tcg-op.h" | ||
47 | +#include "tcg/tcg-op-gvec.h" | ||
48 | +#include "exec/exec-all.h" | ||
49 | +#include "exec/gen-icount.h" | ||
50 | +#include "translate.h" | ||
51 | +#include "translate-a32.h" | ||
52 | |||
53 | /* Include the generated VFP decoder */ | ||
54 | #include "decode-vfp.c.inc" | ||
55 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
56 | index XXXXXXX..XXXXXXX 100644 | ||
57 | --- a/target/arm/translate.c | ||
58 | +++ b/target/arm/translate.c | ||
59 | @@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg) | ||
60 | |||
61 | #define ARM_CP_RW_BIT (1 << 20) | ||
62 | |||
63 | -/* Include the VFP and Neon decoders */ | ||
64 | -#include "translate-vfp.c.inc" | ||
65 | +/* Include the Neon decoder */ | ||
66 | #include "translate-neon.c.inc" | ||
67 | |||
68 | static inline void iwmmxt_load_reg(TCGv_i64 var, int reg) | ||
69 | diff --git a/target/arm/meson.build b/target/arm/meson.build | ||
70 | index XXXXXXX..XXXXXXX 100644 | ||
71 | --- a/target/arm/meson.build | ||
72 | +++ b/target/arm/meson.build | ||
73 | @@ -XXX,XX +XXX,XX @@ gen = [ | ||
74 | decodetree.process('neon-shared.decode', extra_args: '--static-decode=disas_neon_shared'), | ||
75 | decodetree.process('neon-dp.decode', extra_args: '--static-decode=disas_neon_dp'), | ||
76 | decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'), | ||
77 | - decodetree.process('vfp.decode', extra_args: '--static-decode=disas_vfp'), | ||
78 | - decodetree.process('vfp-uncond.decode', extra_args: '--static-decode=disas_vfp_uncond'), | ||
79 | + decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'), | ||
80 | + decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'), | ||
81 | decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'), | ||
82 | decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'), | ||
83 | decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'), | ||
84 | @@ -XXX,XX +XXX,XX @@ arm_ss.add(files( | ||
85 | 'tlb_helper.c', | ||
86 | 'translate.c', | ||
87 | 'translate-m-nocp.c', | ||
88 | + 'translate-vfp.c', | ||
89 | 'vec_helper.c', | ||
90 | 'vfp_helper.c', | ||
91 | 'cpu_tcg.c', | ||
92 | -- | ||
93 | 2.20.1 | ||
94 | |||
95 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The function vfp_reg_ptr() is used only in translate-neon.c.inc; | ||
2 | move it there. | ||
3 | 1 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20210430132740.10391-10-peter.maydell@linaro.org | ||
8 | --- | ||
9 | target/arm/translate.c | 7 ------- | ||
10 | target/arm/translate-neon.c.inc | 7 +++++++ | ||
11 | 2 files changed, 7 insertions(+), 7 deletions(-) | ||
12 | |||
13 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/arm/translate.c | ||
16 | +++ b/target/arm/translate.c | ||
17 | @@ -XXX,XX +XXX,XX @@ void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop) | ||
18 | } | ||
19 | } | ||
20 | |||
21 | -static TCGv_ptr vfp_reg_ptr(bool dp, int reg) | ||
22 | -{ | ||
23 | - TCGv_ptr ret = tcg_temp_new_ptr(); | ||
24 | - tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg)); | ||
25 | - return ret; | ||
26 | -} | ||
27 | - | ||
28 | #define ARM_CP_RW_BIT (1 << 20) | ||
29 | |||
30 | /* Include the Neon decoder */ | ||
31 | diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc | ||
32 | index XXXXXXX..XXXXXXX 100644 | ||
33 | --- a/target/arm/translate-neon.c.inc | ||
34 | +++ b/target/arm/translate-neon.c.inc | ||
35 | @@ -XXX,XX +XXX,XX @@ static inline int neon_3same_fp_size(DisasContext *s, int x) | ||
36 | #include "decode-neon-ls.c.inc" | ||
37 | #include "decode-neon-shared.c.inc" | ||
38 | |||
39 | +static TCGv_ptr vfp_reg_ptr(bool dp, int reg) | ||
40 | +{ | ||
41 | + TCGv_ptr ret = tcg_temp_new_ptr(); | ||
42 | + tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg)); | ||
43 | + return ret; | ||
44 | +} | ||
45 | + | ||
46 | static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop) | ||
47 | { | ||
48 | long offset = neon_element_offset(reg, ele, mop & MO_SIZE); | ||
49 | -- | ||
50 | 2.20.1 | ||
51 | |||
52 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The VFPGenFixPointFn typedef is unused; delete it. | ||
2 | 1 | ||
3 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
4 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Message-id: 20210430132740.10391-11-peter.maydell@linaro.org | ||
7 | --- | ||
8 | target/arm/translate.c | 2 -- | ||
9 | 1 file changed, 2 deletions(-) | ||
10 | |||
11 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/target/arm/translate.c | ||
14 | +++ b/target/arm/translate.c | ||
15 | @@ -XXX,XX +XXX,XX @@ static const char * const regnames[] = | ||
16 | /* Function prototypes for gen_ functions calling Neon helpers. */ | ||
17 | typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32, | ||
18 | TCGv_i32, TCGv_i32); | ||
19 | -/* Function prototypes for gen_ functions for fix point conversions */ | ||
20 | -typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); | ||
21 | |||
22 | /* initialize TCG globals. */ | ||
23 | void arm_translate_init(void) | ||
24 | -- | ||
25 | 2.20.1 | ||
26 | |||
27 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Move the NeonGenThreeOpEnvFn typedef to translate.h together | ||
2 | with the other similar typedefs. | ||
3 | 1 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
7 | Message-id: 20210430132740.10391-12-peter.maydell@linaro.org | ||
8 | --- | ||
9 | target/arm/translate.h | 2 ++ | ||
10 | target/arm/translate.c | 3 --- | ||
11 | 2 files changed, 2 insertions(+), 3 deletions(-) | ||
12 | |||
13 | diff --git a/target/arm/translate.h b/target/arm/translate.h | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/arm/translate.h | ||
16 | +++ b/target/arm/translate.h | ||
17 | @@ -XXX,XX +XXX,XX @@ typedef void NeonGenOneOpFn(TCGv_i32, TCGv_i32); | ||
18 | typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32); | ||
19 | typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32); | ||
20 | typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32); | ||
21 | +typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32, | ||
22 | + TCGv_i32, TCGv_i32); | ||
23 | typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64); | ||
24 | typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64); | ||
25 | typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64); | ||
26 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/target/arm/translate.c | ||
29 | +++ b/target/arm/translate.c | ||
30 | @@ -XXX,XX +XXX,XX @@ static const char * const regnames[] = | ||
31 | { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | ||
32 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" }; | ||
33 | |||
34 | -/* Function prototypes for gen_ functions calling Neon helpers. */ | ||
35 | -typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32, | ||
36 | - TCGv_i32, TCGv_i32); | ||
37 | |||
38 | /* initialize TCG globals. */ | ||
39 | void arm_translate_init(void) | ||
40 | -- | ||
41 | 2.20.1 | ||
42 | |||
43 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Make the remaining functions needed by the translate-neon code | ||
2 | global. | ||
3 | 1 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20210430132740.10391-13-peter.maydell@linaro.org | ||
8 | --- | ||
9 | target/arm/translate-a32.h | 8 ++++++++ | ||
10 | target/arm/translate.c | 10 ++-------- | ||
11 | 2 files changed, 10 insertions(+), 8 deletions(-) | ||
12 | |||
13 | diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/arm/translate-a32.h | ||
16 | +++ b/target/arm/translate-a32.h | ||
17 | @@ -XXX,XX +XXX,XX @@ void gen_set_pc_im(DisasContext *s, target_ulong val); | ||
18 | void gen_lookup_tb(DisasContext *s); | ||
19 | long vfp_reg_offset(bool dp, unsigned reg); | ||
20 | long neon_full_reg_offset(unsigned reg); | ||
21 | +long neon_element_offset(int reg, int element, MemOp memop); | ||
22 | +void gen_rev16(TCGv_i32 dest, TCGv_i32 var); | ||
23 | |||
24 | static inline TCGv_i32 load_cpu_offset(int offset) | ||
25 | { | ||
26 | @@ -XXX,XX +XXX,XX @@ DO_GEN_ST(32, MO_UL) | ||
27 | /* Set NZCV flags from the high 4 bits of var. */ | ||
28 | #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV) | ||
29 | |||
30 | +/* Swap low and high halfwords. */ | ||
31 | +static inline void gen_swap_half(TCGv_i32 dest, TCGv_i32 var) | ||
32 | +{ | ||
33 | + tcg_gen_rotri_i32(dest, var, 16); | ||
34 | +} | ||
35 | + | ||
36 | #endif | ||
37 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/target/arm/translate.c | ||
40 | +++ b/target/arm/translate.c | ||
41 | @@ -XXX,XX +XXX,XX @@ static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b) | ||
42 | } | ||
43 | |||
44 | /* Byteswap each halfword. */ | ||
45 | -static void gen_rev16(TCGv_i32 dest, TCGv_i32 var) | ||
46 | +void gen_rev16(TCGv_i32 dest, TCGv_i32 var) | ||
47 | { | ||
48 | TCGv_i32 tmp = tcg_temp_new_i32(); | ||
49 | TCGv_i32 mask = tcg_const_i32(0x00ff00ff); | ||
50 | @@ -XXX,XX +XXX,XX @@ static void gen_revsh(TCGv_i32 dest, TCGv_i32 var) | ||
51 | tcg_gen_ext16s_i32(dest, var); | ||
52 | } | ||
53 | |||
54 | -/* Swap low and high halfwords. */ | ||
55 | -static void gen_swap_half(TCGv_i32 dest, TCGv_i32 var) | ||
56 | -{ | ||
57 | - tcg_gen_rotri_i32(dest, var, 16); | ||
58 | -} | ||
59 | - | ||
60 | /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. | ||
61 | tmp = (t0 ^ t1) & 0x8000; | ||
62 | t0 &= ~0x8000; | ||
63 | @@ -XXX,XX +XXX,XX @@ long neon_full_reg_offset(unsigned reg) | ||
64 | * Return the offset of a 2**SIZE piece of a NEON register, at index ELE, | ||
65 | * where 0 is the least significant end of the register. | ||
66 | */ | ||
67 | -static long neon_element_offset(int reg, int element, MemOp memop) | ||
68 | +long neon_element_offset(int reg, int element, MemOp memop) | ||
69 | { | ||
70 | int element_size = 1 << (memop & MO_SIZE); | ||
71 | int ofs = element * element_size; | ||
72 | -- | ||
73 | 2.20.1 | ||
74 | |||
75 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Switch translate-neon.c.inc from being #included into translate.c | ||
2 | to being its own compilation unit. | ||
3 | 1 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20210430132740.10391-14-peter.maydell@linaro.org | ||
8 | --- | ||
9 | target/arm/translate-a32.h | 3 +++ | ||
10 | .../arm/{translate-neon.c.inc => translate-neon.c} | 12 +++++++----- | ||
11 | target/arm/translate.c | 3 --- | ||
12 | target/arm/meson.build | 7 ++++--- | ||
13 | 4 files changed, 14 insertions(+), 11 deletions(-) | ||
14 | rename target/arm/{translate-neon.c.inc => translate-neon.c} (99%) | ||
15 | |||
16 | diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/target/arm/translate-a32.h | ||
19 | +++ b/target/arm/translate-a32.h | ||
20 | @@ -XXX,XX +XXX,XX @@ | ||
21 | bool disas_m_nocp(DisasContext *dc, uint32_t insn); | ||
22 | bool disas_vfp(DisasContext *s, uint32_t insn); | ||
23 | bool disas_vfp_uncond(DisasContext *s, uint32_t insn); | ||
24 | +bool disas_neon_dp(DisasContext *s, uint32_t insn); | ||
25 | +bool disas_neon_ls(DisasContext *s, uint32_t insn); | ||
26 | +bool disas_neon_shared(DisasContext *s, uint32_t insn); | ||
27 | |||
28 | void load_reg_var(DisasContext *s, TCGv_i32 var, int reg); | ||
29 | void arm_gen_condlabel(DisasContext *s); | ||
30 | diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c | ||
31 | similarity index 99% | ||
32 | rename from target/arm/translate-neon.c.inc | ||
33 | rename to target/arm/translate-neon.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/target/arm/translate-neon.c.inc | ||
36 | +++ b/target/arm/translate-neon.c | ||
37 | @@ -XXX,XX +XXX,XX @@ | ||
38 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
39 | */ | ||
40 | |||
41 | -/* | ||
42 | - * This file is intended to be included from translate.c; it uses | ||
43 | - * some macros and definitions provided by that file. | ||
44 | - * It might be possible to convert it to a standalone .c file eventually. | ||
45 | - */ | ||
46 | +#include "qemu/osdep.h" | ||
47 | +#include "tcg/tcg-op.h" | ||
48 | +#include "tcg/tcg-op-gvec.h" | ||
49 | +#include "exec/exec-all.h" | ||
50 | +#include "exec/gen-icount.h" | ||
51 | +#include "translate.h" | ||
52 | +#include "translate-a32.h" | ||
53 | |||
54 | static inline int plus1(DisasContext *s, int x) | ||
55 | { | ||
56 | diff --git a/target/arm/translate.c b/target/arm/translate.c | ||
57 | index XXXXXXX..XXXXXXX 100644 | ||
58 | --- a/target/arm/translate.c | ||
59 | +++ b/target/arm/translate.c | ||
60 | @@ -XXX,XX +XXX,XX @@ void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop) | ||
61 | |||
62 | #define ARM_CP_RW_BIT (1 << 20) | ||
63 | |||
64 | -/* Include the Neon decoder */ | ||
65 | -#include "translate-neon.c.inc" | ||
66 | - | ||
67 | static inline void iwmmxt_load_reg(TCGv_i64 var, int reg) | ||
68 | { | ||
69 | tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg])); | ||
70 | diff --git a/target/arm/meson.build b/target/arm/meson.build | ||
71 | index XXXXXXX..XXXXXXX 100644 | ||
72 | --- a/target/arm/meson.build | ||
73 | +++ b/target/arm/meson.build | ||
74 | @@ -XXX,XX +XXX,XX @@ | ||
75 | gen = [ | ||
76 | decodetree.process('sve.decode', extra_args: '--decode=disas_sve'), | ||
77 | - decodetree.process('neon-shared.decode', extra_args: '--static-decode=disas_neon_shared'), | ||
78 | - decodetree.process('neon-dp.decode', extra_args: '--static-decode=disas_neon_dp'), | ||
79 | - decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'), | ||
80 | + decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'), | ||
81 | + decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'), | ||
82 | + decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'), | ||
83 | decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'), | ||
84 | decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'), | ||
85 | decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'), | ||
86 | @@ -XXX,XX +XXX,XX @@ arm_ss.add(files( | ||
87 | 'tlb_helper.c', | ||
88 | 'translate.c', | ||
89 | 'translate-m-nocp.c', | ||
90 | + 'translate-neon.c', | ||
91 | 'translate-vfp.c', | ||
92 | 'vec_helper.c', | ||
93 | 'vfp_helper.c', | ||
94 | -- | ||
95 | 2.20.1 | ||
96 | |||
97 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The WFI insn is not system-mode only, though it doesn't usually make | ||
2 | a huge amount of sense for userspace code to execute it. Currently | ||
3 | if you try it in qemu-arm then the helper function will raise an | ||
4 | EXCP_HLT exception, which is not covered by the switch in cpu_loop() | ||
5 | and results in an abort: | ||
6 | 1 | ||
7 | qemu: unhandled CPU exception 0x10001 - aborting | ||
8 | R00=00000001 R01=408003e4 R02=408003ec R03=000102ec | ||
9 | R04=00010a28 R05=00010158 R06=00087460 R07=00010158 | ||
10 | R08=00000000 R09=00000000 R10=00085b7c R11=408002a4 | ||
11 | R12=408002b8 R13=408002a0 R14=0001057c R15=000102f8 | ||
12 | PSR=60000010 -ZC- A usr32 | ||
13 | qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x7fcbfa4f0a12 | ||
14 | |||
15 | Make the WFI helper function return immediately in the usermode | ||
16 | emulator. This turns WFI into a NOP, which is OK because: | ||
17 | * architecturally "WFI is a NOP" is a permitted implementation | ||
18 | * aarch64 Linux kernels use the SCTLR_EL1.nTWI bit to trap | ||
19 | userspace WFI and NOP it (though aarch32 kernels currently | ||
20 | just let WFI do whatever it would do) | ||
21 | |||
22 | We could in theory make the translate.c code special case user-mode | ||
23 | emulation and NOP the insn entirely rather than making the helper | ||
24 | do nothing, but because no real world code will be trying to | ||
25 | execute WFI we don't care about efficiency and the helper provides | ||
26 | a single place where we can make the change rather than having | ||
27 | to touch multiple places in translate.c and translate-a64.c. | ||
28 | |||
29 | Fixes: https://bugs.launchpad.net/qemu/+bug/1926759 | ||
30 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
31 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
32 | Message-id: 20210430162212.825-1-peter.maydell@linaro.org | ||
33 | --- | ||
34 | target/arm/op_helper.c | 12 ++++++++++++ | ||
35 | 1 file changed, 12 insertions(+) | ||
36 | |||
37 | diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/target/arm/op_helper.c | ||
40 | +++ b/target/arm/op_helper.c | ||
41 | @@ -XXX,XX +XXX,XX @@ static inline int check_wfx_trap(CPUARMState *env, bool is_wfe) | ||
42 | |||
43 | void HELPER(wfi)(CPUARMState *env, uint32_t insn_len) | ||
44 | { | ||
45 | +#ifdef CONFIG_USER_ONLY | ||
46 | + /* | ||
47 | + * WFI in the user-mode emulator is technically permitted but not | ||
48 | + * something any real-world code would do. AArch64 Linux kernels | ||
49 | + * trap it via SCTRL_EL1.nTWI and make it an (expensive) NOP; | ||
50 | + * AArch32 kernels don't trap it so it will delay a bit. | ||
51 | + * For QEMU, make it NOP here, because trying to raise EXCP_HLT | ||
52 | + * would trigger an abort. | ||
53 | + */ | ||
54 | + return; | ||
55 | +#else | ||
56 | CPUState *cs = env_cpu(env); | ||
57 | int target_el = check_wfx_trap(env, false); | ||
58 | |||
59 | @@ -XXX,XX +XXX,XX @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len) | ||
60 | cs->exception_index = EXCP_HLT; | ||
61 | cs->halted = 1; | ||
62 | cpu_loop_exit(cs); | ||
63 | +#endif | ||
64 | } | ||
65 | |||
66 | void HELPER(wfe)(CPUARMState *env) | ||
67 | -- | ||
68 | 2.20.1 | ||
69 | |||
70 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The omap_mmc_reset() function resets its SD card via | ||
2 | device_legacy_reset(). We know that the SD card does not have a qbus | ||
3 | of its own, so the new device_cold_reset() function (which resets | ||
4 | both the device and its child buses) is equivalent here to | ||
5 | device_legacy_reset() and we can just switch to the new API. | ||
6 | 1 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
9 | Message-id: 20210430222348.8514-1-peter.maydell@linaro.org | ||
10 | --- | ||
11 | hw/sd/omap_mmc.c | 2 +- | ||
12 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/sd/omap_mmc.c | ||
17 | +++ b/hw/sd/omap_mmc.c | ||
18 | @@ -XXX,XX +XXX,XX @@ void omap_mmc_reset(struct omap_mmc_s *host) | ||
19 | * into any bus, and we must reset it manually. When omap_mmc is | ||
20 | * QOMified this must move into the QOM reset function. | ||
21 | */ | ||
22 | - device_legacy_reset(DEVICE(host->card)); | ||
23 | + device_cold_reset(DEVICE(host->card)); | ||
24 | } | ||
25 | |||
26 | static uint64_t omap_mmc_read(void *opaque, hwaddr offset, | ||
27 | -- | ||
28 | 2.20.1 | ||
29 | |||
30 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Both os-win32.h and os-posix.h include system header files. Instead | ||
2 | of having osdep.h include them inside its 'extern "C"' block, make | ||
3 | these headers handle that themselves, so that we don't include the | ||
4 | system headers inside 'extern "C"'. | ||
5 | 1 | ||
6 | This doesn't fix any current problems, but it's conceptually the | ||
7 | right way to handle system headers. | ||
8 | |||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
11 | --- | ||
12 | include/qemu/osdep.h | 8 ++++---- | ||
13 | include/sysemu/os-posix.h | 8 ++++++++ | ||
14 | include/sysemu/os-win32.h | 8 ++++++++ | ||
15 | 3 files changed, 20 insertions(+), 4 deletions(-) | ||
16 | |||
17 | diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/include/qemu/osdep.h | ||
20 | +++ b/include/qemu/osdep.h | ||
21 | @@ -XXX,XX +XXX,XX @@ QEMU_EXTERN_C int daemon(int, int); | ||
22 | */ | ||
23 | #include "glib-compat.h" | ||
24 | |||
25 | -#ifdef __cplusplus | ||
26 | -extern "C" { | ||
27 | -#endif | ||
28 | - | ||
29 | #ifdef _WIN32 | ||
30 | #include "sysemu/os-win32.h" | ||
31 | #endif | ||
32 | @@ -XXX,XX +XXX,XX @@ extern "C" { | ||
33 | #include "sysemu/os-posix.h" | ||
34 | #endif | ||
35 | |||
36 | +#ifdef __cplusplus | ||
37 | +extern "C" { | ||
38 | +#endif | ||
39 | + | ||
40 | #include "qemu/typedefs.h" | ||
41 | |||
42 | /* | ||
43 | diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/include/sysemu/os-posix.h | ||
46 | +++ b/include/sysemu/os-posix.h | ||
47 | @@ -XXX,XX +XXX,XX @@ | ||
48 | #include <sys/sysmacros.h> | ||
49 | #endif | ||
50 | |||
51 | +#ifdef __cplusplus | ||
52 | +extern "C" { | ||
53 | +#endif | ||
54 | + | ||
55 | void os_set_line_buffering(void); | ||
56 | void os_set_proc_name(const char *s); | ||
57 | void os_setup_signal_handling(void); | ||
58 | @@ -XXX,XX +XXX,XX @@ static inline void qemu_funlockfile(FILE *f) | ||
59 | funlockfile(f); | ||
60 | } | ||
61 | |||
62 | +#ifdef __cplusplus | ||
63 | +} | ||
64 | +#endif | ||
65 | + | ||
66 | #endif | ||
67 | diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h | ||
68 | index XXXXXXX..XXXXXXX 100644 | ||
69 | --- a/include/sysemu/os-win32.h | ||
70 | +++ b/include/sysemu/os-win32.h | ||
71 | @@ -XXX,XX +XXX,XX @@ | ||
72 | #include <windows.h> | ||
73 | #include <ws2tcpip.h> | ||
74 | |||
75 | +#ifdef __cplusplus | ||
76 | +extern "C" { | ||
77 | +#endif | ||
78 | + | ||
79 | #if defined(_WIN64) | ||
80 | /* On w64, setjmp is implemented by _setjmp which needs a second parameter. | ||
81 | * If this parameter is NULL, longjump does no stack unwinding. | ||
82 | @@ -XXX,XX +XXX,XX @@ ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags); | ||
83 | ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags, | ||
84 | struct sockaddr *addr, socklen_t *addrlen); | ||
85 | |||
86 | +#ifdef __cplusplus | ||
87 | +} | ||
88 | +#endif | ||
89 | + | ||
90 | #endif | ||
91 | -- | ||
92 | 2.20.1 | ||
93 | |||
94 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Make bswap.h handle being included outside an 'extern "C"' block: | ||
2 | all system headers are included first, then all declarations are | ||
3 | put inside an 'extern "C"' block. | ||
4 | 1 | ||
5 | This requires a little rearrangement as currently we have an ifdef | ||
6 | ladder that has some system includes and some local declarations | ||
7 | or definitions, and we need to separate those out. | ||
8 | |||
9 | We want to do this because dis-asm.h includes bswap.h, dis-asm.h | ||
10 | may need to be included from C++ files, and system headers should | ||
11 | not be included within 'extern "C"' blocks. | ||
12 | |||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
15 | --- | ||
16 | include/qemu/bswap.h | 26 ++++++++++++++++++++++---- | ||
17 | 1 file changed, 22 insertions(+), 4 deletions(-) | ||
18 | |||
19 | diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/include/qemu/bswap.h | ||
22 | +++ b/include/qemu/bswap.h | ||
23 | @@ -XXX,XX +XXX,XX @@ | ||
24 | #ifndef BSWAP_H | ||
25 | #define BSWAP_H | ||
26 | |||
27 | -#include "fpu/softfloat-types.h" | ||
28 | - | ||
29 | #ifdef CONFIG_MACHINE_BSWAP_H | ||
30 | # include <sys/endian.h> | ||
31 | # include <machine/bswap.h> | ||
32 | @@ -XXX,XX +XXX,XX @@ | ||
33 | # include <endian.h> | ||
34 | #elif defined(CONFIG_BYTESWAP_H) | ||
35 | # include <byteswap.h> | ||
36 | +#define BSWAP_FROM_BYTESWAP | ||
37 | +# else | ||
38 | +#define BSWAP_FROM_FALLBACKS | ||
39 | +#endif /* ! CONFIG_MACHINE_BSWAP_H */ | ||
40 | |||
41 | +#ifdef __cplusplus | ||
42 | +extern "C" { | ||
43 | +#endif | ||
44 | + | ||
45 | +#include "fpu/softfloat-types.h" | ||
46 | + | ||
47 | +#ifdef BSWAP_FROM_BYTESWAP | ||
48 | static inline uint16_t bswap16(uint16_t x) | ||
49 | { | ||
50 | return bswap_16(x); | ||
51 | @@ -XXX,XX +XXX,XX @@ static inline uint64_t bswap64(uint64_t x) | ||
52 | { | ||
53 | return bswap_64(x); | ||
54 | } | ||
55 | -# else | ||
56 | +#endif | ||
57 | + | ||
58 | +#ifdef BSWAP_FROM_FALLBACKS | ||
59 | static inline uint16_t bswap16(uint16_t x) | ||
60 | { | ||
61 | return (((x & 0x00ff) << 8) | | ||
62 | @@ -XXX,XX +XXX,XX @@ static inline uint64_t bswap64(uint64_t x) | ||
63 | ((x & 0x00ff000000000000ULL) >> 40) | | ||
64 | ((x & 0xff00000000000000ULL) >> 56)); | ||
65 | } | ||
66 | -#endif /* ! CONFIG_MACHINE_BSWAP_H */ | ||
67 | +#endif | ||
68 | + | ||
69 | +#undef BSWAP_FROM_BYTESWAP | ||
70 | +#undef BSWAP_FROM_FALLBACKS | ||
71 | |||
72 | static inline void bswap16s(uint16_t *s) | ||
73 | { | ||
74 | @@ -XXX,XX +XXX,XX @@ DO_STN_LDN_P(be) | ||
75 | #undef le_bswaps | ||
76 | #undef be_bswaps | ||
77 | |||
78 | +#ifdef __cplusplus | ||
79 | +} | ||
80 | +#endif | ||
81 | + | ||
82 | #endif /* BSWAP_H */ | ||
83 | -- | ||
84 | 2.20.1 | ||
85 | |||
86 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Make dis-asm.h handle being included outside an 'extern "C"' block; | ||
2 | this allows us to remove the 'extern "C"' blocks that our two C++ | ||
3 | files that include it are using. | ||
4 | 1 | ||
5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | --- | ||
8 | include/disas/dis-asm.h | 12 ++++++++++-- | ||
9 | disas/arm-a64.cc | 2 -- | ||
10 | disas/nanomips.cpp | 2 -- | ||
11 | 3 files changed, 10 insertions(+), 6 deletions(-) | ||
12 | |||
13 | diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/include/disas/dis-asm.h | ||
16 | +++ b/include/disas/dis-asm.h | ||
17 | @@ -XXX,XX +XXX,XX @@ | ||
18 | #ifndef DISAS_DIS_ASM_H | ||
19 | #define DISAS_DIS_ASM_H | ||
20 | |||
21 | +#include "qemu/bswap.h" | ||
22 | + | ||
23 | +#ifdef __cplusplus | ||
24 | +extern "C" { | ||
25 | +#endif | ||
26 | + | ||
27 | typedef void *PTR; | ||
28 | typedef uint64_t bfd_vma; | ||
29 | typedef int64_t bfd_signed_vma; | ||
30 | @@ -XXX,XX +XXX,XX @@ bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size); | ||
31 | |||
32 | /* from libbfd */ | ||
33 | |||
34 | -#include "qemu/bswap.h" | ||
35 | - | ||
36 | static inline bfd_vma bfd_getl64(const bfd_byte *addr) | ||
37 | { | ||
38 | return ldq_le_p(addr); | ||
39 | @@ -XXX,XX +XXX,XX @@ static inline bfd_vma bfd_getb16(const bfd_byte *addr) | ||
40 | |||
41 | typedef bool bfd_boolean; | ||
42 | |||
43 | +#ifdef __cplusplus | ||
44 | +} | ||
45 | +#endif | ||
46 | + | ||
47 | #endif /* DISAS_DIS_ASM_H */ | ||
48 | diff --git a/disas/arm-a64.cc b/disas/arm-a64.cc | ||
49 | index XXXXXXX..XXXXXXX 100644 | ||
50 | --- a/disas/arm-a64.cc | ||
51 | +++ b/disas/arm-a64.cc | ||
52 | @@ -XXX,XX +XXX,XX @@ | ||
53 | */ | ||
54 | |||
55 | #include "qemu/osdep.h" | ||
56 | -extern "C" { | ||
57 | #include "disas/dis-asm.h" | ||
58 | -} | ||
59 | |||
60 | #include "vixl/a64/disasm-a64.h" | ||
61 | |||
62 | diff --git a/disas/nanomips.cpp b/disas/nanomips.cpp | ||
63 | index XXXXXXX..XXXXXXX 100644 | ||
64 | --- a/disas/nanomips.cpp | ||
65 | +++ b/disas/nanomips.cpp | ||
66 | @@ -XXX,XX +XXX,XX @@ | ||
67 | */ | ||
68 | |||
69 | #include "qemu/osdep.h" | ||
70 | -extern "C" { | ||
71 | #include "disas/dis-asm.h" | ||
72 | -} | ||
73 | |||
74 | #include <cstring> | ||
75 | #include <stdexcept> | ||
76 | -- | ||
77 | 2.20.1 | ||
78 | |||
79 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The MPS2 SCC device doesn't have any documentation of its properties; | ||
2 | add a "QEMU interface" format comment describing them. | ||
3 | 1 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
6 | Message-id: 20210504120912.23094-2-peter.maydell@linaro.org | ||
7 | --- | ||
8 | include/hw/misc/mps2-scc.h | 12 ++++++++++++ | ||
9 | 1 file changed, 12 insertions(+) | ||
10 | |||
11 | diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/include/hw/misc/mps2-scc.h | ||
14 | +++ b/include/hw/misc/mps2-scc.h | ||
15 | @@ -XXX,XX +XXX,XX @@ | ||
16 | * (at your option) any later version. | ||
17 | */ | ||
18 | |||
19 | +/* | ||
20 | + * This is a model of the Serial Communication Controller (SCC) | ||
21 | + * block found in most MPS FPGA images. | ||
22 | + * | ||
23 | + * QEMU interface: | ||
24 | + * + sysbus MMIO region 0: the register bank | ||
25 | + * + QOM property "scc-cfg4": value of the read-only CFG4 register | ||
26 | + * + QOM property "scc-aid": value of the read-only SCC_AID register | ||
27 | + * + QOM property "scc-id": value of the read-only SCC_ID register | ||
28 | + * + QOM property array "oscclk": reset values of the OSCCLK registers | ||
29 | + * (which are accessed via the SYS_CFG channel provided by this device) | ||
30 | + */ | ||
31 | #ifndef MPS2_SCC_H | ||
32 | #define MPS2_SCC_H | ||
33 | |||
34 | -- | ||
35 | 2.20.1 | ||
36 | |||
37 | diff view generated by jsdifflib |