1
arm queue; dunno if this will be the last before softfreeze
1
The following changes since commit 53f306f316549d20c76886903181413d20842423:
2
or not, but anyway probably the last large one. New orangepi-pc
3
board model is the big item here.
4
2
5
thanks
3
Merge remote-tracking branch 'remotes/ehabkost-gl/tags/x86-next-pull-request' into staging (2021-06-21 11:26:04 +0100)
6
-- PMM
7
8
The following changes since commit 67d9ef7d541c3d21a25796c51c26da096a433565:
9
10
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-docs-20200312' into staging (2020-03-12 15:20:52 +0000)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200312
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210621
15
8
16
for you to fetch changes up to aca53be34ac3e7cac5f39396a51a338860a5a837:
9
for you to fetch changes up to a83f1d9263d281f938a3984cda7104d55affd43a:
17
10
18
target/arm: kvm: Inject events at the last stage of sync (2020-03-12 16:31:10 +0000)
11
docs/system: arm: Add nRF boards description (2021-06-21 17:24:33 +0100)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
target-arm queue:
14
target-arm queue:
22
* Fix various bugs that might result in an assert() due to
15
* Don't require 'virt' board to be compiled in for ACPI GHES code
23
incorrect hflags for M-profile CPUs
16
* docs: Document which architecture extensions we emulate
24
* Fix Aspeed SMC Controller user-mode select handling
17
* Fix bugs in M-profile FPCXT_NS accesses
25
* Report correct (with-tag) address in fault address register
18
* First slice of MVE patches
26
when TBI is enabled
19
* Implement MTE3
27
* cubieboard: make sure SOC object isn't leaked
20
* docs/system: arm: Add nRF boards description
28
* fsl-imx25: Wire up eSDHC controllers
29
* fsl-imx25: Wire up USB controllers
30
* New board model: orangepi-pc (OrangePi PC)
31
* ARM/KVM: if user doesn't select GIC version and the
32
host kernel can only provide GICv3, use that, rather
33
than defaulting to "fail because GICv2 isn't possible"
34
* kvm: Only do KVM_SET_VCPU_EVENTS at the last stage of sync
35
21
36
----------------------------------------------------------------
22
----------------------------------------------------------------
37
Beata Michalska (1):
23
Alexandre Iooss (1):
38
target/arm: kvm: Inject events at the last stage of sync
24
docs/system: arm: Add nRF boards description
39
25
40
Cédric Le Goater (2):
26
Peter Collingbourne (1):
41
aspeed/smc: Add some tracing
27
target/arm: Implement MTE3
42
aspeed/smc: Fix User mode select/unselect scheme
43
28
44
Eric Auger (6):
29
Peter Maydell (55):
45
hw/arm/virt: Document 'max' value in gic-version property description
30
hw/acpi: Provide stub version of acpi_ghes_record_errors()
46
hw/arm/virt: Introduce VirtGICType enum type
31
hw/acpi: Provide function acpi_ghes_present()
47
hw/arm/virt: Introduce finalize_gic_version()
32
target/arm: Use acpi_ghes_present() to see if we report ACPI memory errors
48
target/arm/kvm: Let kvm_arm_vgic_probe() return a bitmap
33
docs/system/arm: Document which architecture extensions we emulate
49
hw/arm/virt: kvm: Restructure finalize_gic_version()
34
target/arm/translate-vfp.c: Whitespace fixes
50
hw/arm/virt: kvm: allow gicv3 by default if v2 cannot work
35
target/arm: Handle FPU being disabled in FPCXT_NS accesses
36
target/arm: Don't NOCP fault for FPCXT_NS accesses
37
target/arm: Handle writeback in VLDR/VSTR sysreg with no memory access
38
target/arm: Factor FP context update code out into helper function
39
target/arm: Split vfp_access_check() into A and M versions
40
target/arm: Handle FPU check for FPCXT_NS insns via vfp_access_check_m()
41
target/arm: Implement MVE VLDR/VSTR (non-widening forms)
42
target/arm: Implement widening/narrowing MVE VLDR/VSTR insns
43
target/arm: Implement MVE VCLZ
44
target/arm: Implement MVE VCLS
45
target/arm: Implement MVE VREV16, VREV32, VREV64
46
target/arm: Implement MVE VMVN (register)
47
target/arm: Implement MVE VABS
48
target/arm: Implement MVE VNEG
49
tcg: Make gen_dup_i32/i64() public as tcg_gen_dup_i32/i64
50
target/arm: Implement MVE VDUP
51
target/arm: Implement MVE VAND, VBIC, VORR, VORN, VEOR
52
target/arm: Implement MVE VADD, VSUB, VMUL
53
target/arm: Implement MVE VMULH
54
target/arm: Implement MVE VRMULH
55
target/arm: Implement MVE VMAX, VMIN
56
target/arm: Implement MVE VABD
57
target/arm: Implement MVE VHADD, VHSUB
58
target/arm: Implement MVE VMULL
59
target/arm: Implement MVE VMLALDAV
60
target/arm: Implement MVE VMLSLDAV
61
target/arm: Implement MVE VRMLALDAVH, VRMLSLDAVH
62
target/arm: Implement MVE VADD (scalar)
63
target/arm: Implement MVE VSUB, VMUL (scalar)
64
target/arm: Implement MVE VHADD, VHSUB (scalar)
65
target/arm: Implement MVE VBRSR
66
target/arm: Implement MVE VPST
67
target/arm: Implement MVE VQADD and VQSUB
68
target/arm: Implement MVE VQDMULH and VQRDMULH (scalar)
69
target/arm: Implement MVE VQDMULL scalar
70
target/arm: Implement MVE VQDMULH, VQRDMULH (vector)
71
target/arm: Implement MVE VQADD, VQSUB (vector)
72
target/arm: Implement MVE VQSHL (vector)
73
target/arm: Implement MVE VQRSHL
74
target/arm: Implement MVE VSHL insn
75
target/arm: Implement MVE VRSHL
76
target/arm: Implement MVE VQDMLADH and VQRDMLADH
77
target/arm: Implement MVE VQDMLSDH and VQRDMLSDH
78
target/arm: Implement MVE VQDMULL (vector)
79
target/arm: Implement MVE VRHADD
80
target/arm: Implement MVE VADC, VSBC
81
target/arm: Implement MVE VCADD
82
target/arm: Implement MVE VHCADD
83
target/arm: Implement MVE VADDV
84
target/arm: Make VMOV scalar <-> gpreg beatwise for MVE
51
85
52
Guenter Roeck (2):
86
docs/system/arm/emulation.rst | 103 ++++
53
hw/arm/fsl-imx25: Wire up eSDHC controllers
87
docs/system/arm/nrf.rst | 51 ++
54
hw/arm/fsl-imx25: Wire up USB controllers
88
docs/system/target-arm.rst | 7 +
89
include/hw/acpi/ghes.h | 9 +
90
include/tcg/tcg-op.h | 8 +
91
include/tcg/tcg.h | 1 -
92
target/arm/helper-mve.h | 357 +++++++++++++
93
target/arm/helper.h | 2 +
94
target/arm/internals.h | 11 +
95
target/arm/translate-a32.h | 3 +
96
target/arm/translate.h | 10 +
97
target/arm/m-nocp.decode | 24 +
98
target/arm/mve.decode | 240 +++++++++
99
target/arm/vfp.decode | 14 -
100
hw/acpi/ghes-stub.c | 22 +
101
hw/acpi/ghes.c | 17 +
102
target/arm/cpu64.c | 2 +-
103
target/arm/kvm64.c | 6 +-
104
target/arm/mte_helper.c | 82 +--
105
target/arm/mve_helper.c | 1160 +++++++++++++++++++++++++++++++++++++++++
106
target/arm/translate-m-nocp.c | 550 +++++++++++++++++++
107
target/arm/translate-mve.c | 759 +++++++++++++++++++++++++++
108
target/arm/translate-vfp.c | 741 +++++++-------------------
109
tcg/tcg-op-gvec.c | 20 +-
110
MAINTAINERS | 1 +
111
hw/acpi/meson.build | 6 +-
112
target/arm/meson.build | 1 +
113
27 files changed, 3578 insertions(+), 629 deletions(-)
114
create mode 100644 docs/system/arm/emulation.rst
115
create mode 100644 docs/system/arm/nrf.rst
116
create mode 100644 target/arm/helper-mve.h
117
create mode 100644 hw/acpi/ghes-stub.c
118
create mode 100644 target/arm/mve_helper.c
55
119
56
Igor Mammedov (1):
57
hw/arm/cubieboard: make sure SOC object isn't leaked
58
59
Niek Linnenbank (13):
60
hw/arm: add Allwinner H3 System-on-Chip
61
hw/arm: add Xunlong Orange Pi PC machine
62
hw/arm/allwinner-h3: add Clock Control Unit
63
hw/arm/allwinner-h3: add USB host controller
64
hw/arm/allwinner-h3: add System Control module
65
hw/arm/allwinner: add CPU Configuration module
66
hw/arm/allwinner: add Security Identifier device
67
hw/arm/allwinner: add SD/MMC host controller
68
hw/arm/allwinner-h3: add EMAC ethernet device
69
hw/arm/allwinner-h3: add Boot ROM support
70
hw/arm/allwinner-h3: add SDRAM controller device
71
hw/arm/allwinner: add RTC device support
72
docs: add Orange Pi PC document
73
74
Peter Maydell (4):
75
hw/intc/armv7m_nvic: Rebuild hflags on reset
76
target/arm: Update hflags in trans_CPS_v7m()
77
target/arm: Recalculate hflags correctly after writes to CONTROL
78
target/arm: Fix some comment typos
79
80
Philippe Mathieu-Daudé (5):
81
tests/boot_linux_console: Add a quick test for the OrangePi PC board
82
tests/boot_linux_console: Add initrd test for the Orange Pi PC board
83
tests/boot_linux_console: Add a SD card test for the OrangePi PC board
84
tests/boot_linux_console: Add a SLOW test booting Ubuntu on OrangePi PC
85
tests/boot_linux_console: Test booting NetBSD via U-Boot on OrangePi PC
86
87
Richard Henderson (2):
88
target/arm: Check addresses for disabled regimes
89
target/arm: Disable clean_data_tbi for system mode
90
91
Makefile.objs | 1 +
92
hw/arm/Makefile.objs | 1 +
93
hw/misc/Makefile.objs | 5 +
94
hw/net/Makefile.objs | 1 +
95
hw/rtc/Makefile.objs | 1 +
96
hw/sd/Makefile.objs | 1 +
97
hw/usb/hcd-ehci.h | 1 +
98
include/hw/arm/allwinner-a10.h | 4 +
99
include/hw/arm/allwinner-h3.h | 161 ++++++
100
include/hw/arm/fsl-imx25.h | 18 +
101
include/hw/arm/virt.h | 12 +-
102
include/hw/misc/allwinner-cpucfg.h | 52 ++
103
include/hw/misc/allwinner-h3-ccu.h | 66 +++
104
include/hw/misc/allwinner-h3-dramc.h | 106 ++++
105
include/hw/misc/allwinner-h3-sysctrl.h | 67 +++
106
include/hw/misc/allwinner-sid.h | 60 +++
107
include/hw/net/allwinner-sun8i-emac.h | 99 ++++
108
include/hw/rtc/allwinner-rtc.h | 134 +++++
109
include/hw/sd/allwinner-sdhost.h | 135 +++++
110
target/arm/helper.h | 1 +
111
target/arm/kvm_arm.h | 3 +
112
hw/arm/allwinner-a10.c | 19 +
113
hw/arm/allwinner-h3.c | 465 ++++++++++++++++++
114
hw/arm/cubieboard.c | 18 +
115
hw/arm/fsl-imx25.c | 56 +++
116
hw/arm/imx25_pdk.c | 16 +
117
hw/arm/orangepi.c | 130 +++++
118
hw/arm/virt.c | 145 ++++--
119
hw/intc/armv7m_nvic.c | 6 +
120
hw/misc/allwinner-cpucfg.c | 282 +++++++++++
121
hw/misc/allwinner-h3-ccu.c | 242 +++++++++
122
hw/misc/allwinner-h3-dramc.c | 358 ++++++++++++++
123
hw/misc/allwinner-h3-sysctrl.c | 140 ++++++
124
hw/misc/allwinner-sid.c | 168 +++++++
125
hw/net/allwinner-sun8i-emac.c | 871 +++++++++++++++++++++++++++++++++
126
hw/rtc/allwinner-rtc.c | 411 ++++++++++++++++
127
hw/sd/allwinner-sdhost.c | 854 ++++++++++++++++++++++++++++++++
128
hw/ssi/aspeed_smc.c | 56 ++-
129
hw/usb/hcd-ehci-sysbus.c | 17 +
130
target/arm/helper.c | 49 +-
131
target/arm/kvm.c | 14 +-
132
target/arm/kvm32.c | 15 +-
133
target/arm/kvm64.c | 15 +-
134
target/arm/translate-a64.c | 11 +
135
target/arm/translate.c | 14 +-
136
MAINTAINERS | 9 +
137
default-configs/arm-softmmu.mak | 1 +
138
docs/system/arm/orangepi.rst | 253 ++++++++++
139
docs/system/target-arm.rst | 2 +
140
hw/arm/Kconfig | 12 +
141
hw/misc/trace-events | 19 +
142
hw/net/Kconfig | 3 +
143
hw/net/trace-events | 10 +
144
hw/rtc/trace-events | 4 +
145
hw/sd/trace-events | 7 +
146
hw/ssi/trace-events | 10 +
147
tests/acceptance/boot_linux_console.py | 230 +++++++++
148
57 files changed, 5787 insertions(+), 74 deletions(-)
149
create mode 100644 include/hw/arm/allwinner-h3.h
150
create mode 100644 include/hw/misc/allwinner-cpucfg.h
151
create mode 100644 include/hw/misc/allwinner-h3-ccu.h
152
create mode 100644 include/hw/misc/allwinner-h3-dramc.h
153
create mode 100644 include/hw/misc/allwinner-h3-sysctrl.h
154
create mode 100644 include/hw/misc/allwinner-sid.h
155
create mode 100644 include/hw/net/allwinner-sun8i-emac.h
156
create mode 100644 include/hw/rtc/allwinner-rtc.h
157
create mode 100644 include/hw/sd/allwinner-sdhost.h
158
create mode 100644 hw/arm/allwinner-h3.c
159
create mode 100644 hw/arm/orangepi.c
160
create mode 100644 hw/misc/allwinner-cpucfg.c
161
create mode 100644 hw/misc/allwinner-h3-ccu.c
162
create mode 100644 hw/misc/allwinner-h3-dramc.c
163
create mode 100644 hw/misc/allwinner-h3-sysctrl.c
164
create mode 100644 hw/misc/allwinner-sid.c
165
create mode 100644 hw/net/allwinner-sun8i-emac.c
166
create mode 100644 hw/rtc/allwinner-rtc.c
167
create mode 100644 hw/sd/allwinner-sdhost.c
168
create mode 100644 docs/system/arm/orangepi.rst
169
create mode 100644 hw/ssi/trace-events
170
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Generic code in target/arm wants to call acpi_ghes_record_errors();
2
provide a stub version so that we don't fail to link when
3
CONFIG_ACPI_APEI is not set. This requires us to add a new
4
ghes-stub.c file to contain it and the meson.build mechanics
5
to use it when appropriate.
2
6
3
The Xunlong Orange Pi PC is an Allwinner H3 System on Chip
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
based embedded computer with mainline support in both U-Boot
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
and Linux. The board comes with a Quad Core Cortex A7 @ 1.3GHz,
9
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
6
1GiB RAM, 100Mbit ethernet, USB, SD/MMC, USB, HDMI and
10
Message-id: 20210603171259.27962-2-peter.maydell@linaro.org
7
various other I/O. This commit add support for the Xunlong
11
---
8
Orange Pi PC machine.
12
hw/acpi/ghes-stub.c | 17 +++++++++++++++++
13
hw/acpi/meson.build | 6 +++---
14
2 files changed, 20 insertions(+), 3 deletions(-)
15
create mode 100644 hw/acpi/ghes-stub.c
9
16
10
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
17
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
11
Tested-by: KONRAD Frederic <frederic.konrad@adacore.com>
12
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Acked-by: Igor Mammedov <imammedo@redhat.com>
16
Message-id: 20200311221854.30370-3-nieklinnenbank@gmail.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/arm/Makefile.objs | 2 +-
20
hw/arm/orangepi.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
21
MAINTAINERS | 1 +
22
3 files changed, 94 insertions(+), 1 deletion(-)
23
create mode 100644 hw/arm/orangepi.c
24
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/Makefile.objs
28
+++ b/hw/arm/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DIGIC) += digic.o
30
obj-$(CONFIG_OMAP) += omap1.o omap2.o
31
obj-$(CONFIG_STRONGARM) += strongarm.o
32
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
33
-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o orangepi.o
35
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
36
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
37
obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
38
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
39
new file mode 100644
18
new file mode 100644
40
index XXXXXXX..XXXXXXX
19
index XXXXXXX..XXXXXXX
41
--- /dev/null
20
--- /dev/null
42
+++ b/hw/arm/orangepi.c
21
+++ b/hw/acpi/ghes-stub.c
43
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
44
+/*
23
+/*
45
+ * Orange Pi emulation
24
+ * Support for generating APEI tables and recording CPER for Guests:
25
+ * stub functions.
46
+ *
26
+ *
47
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
27
+ * Copyright (c) 2021 Linaro, Ltd
48
+ *
28
+ *
49
+ * This program is free software: you can redistribute it and/or modify
29
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
50
+ * it under the terms of the GNU General Public License as published by
30
+ * See the COPYING file in the top-level directory.
51
+ * the Free Software Foundation, either version 2 of the License, or
52
+ * (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful,
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
61
+ */
31
+ */
62
+
32
+
63
+#include "qemu/osdep.h"
33
+#include "qemu/osdep.h"
64
+#include "qemu/units.h"
34
+#include "hw/acpi/ghes.h"
65
+#include "exec/address-spaces.h"
66
+#include "qapi/error.h"
67
+#include "cpu.h"
68
+#include "hw/sysbus.h"
69
+#include "hw/boards.h"
70
+#include "hw/qdev-properties.h"
71
+#include "hw/arm/allwinner-h3.h"
72
+#include "sysemu/sysemu.h"
73
+
35
+
74
+static struct arm_boot_info orangepi_binfo = {
36
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
75
+ .nb_cpus = AW_H3_NUM_CPUS,
76
+};
77
+
78
+static void orangepi_init(MachineState *machine)
79
+{
37
+{
80
+ AwH3State *h3;
38
+ return -1;
81
+
82
+ /* BIOS is not supported by this board */
83
+ if (bios_name) {
84
+ error_report("BIOS not supported for this machine");
85
+ exit(1);
86
+ }
87
+
88
+ /* This board has fixed size RAM */
89
+ if (machine->ram_size != 1 * GiB) {
90
+ error_report("This machine can only be used with 1GiB of RAM");
91
+ exit(1);
92
+ }
93
+
94
+ /* Only allow Cortex-A7 for this board */
95
+ if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a7")) != 0) {
96
+ error_report("This board can only be used with cortex-a7 CPU");
97
+ exit(1);
98
+ }
99
+
100
+ h3 = AW_H3(object_new(TYPE_AW_H3));
101
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(h3),
102
+ &error_abort);
103
+ object_unref(OBJECT(h3));
104
+
105
+ /* Setup timer properties */
106
+ object_property_set_int(OBJECT(h3), 32768, "clk0-freq",
107
+ &error_abort);
108
+ object_property_set_int(OBJECT(h3), 24 * 1000 * 1000, "clk1-freq",
109
+ &error_abort);
110
+
111
+ /* Mark H3 object realized */
112
+ object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
113
+
114
+ /* SDRAM */
115
+ memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
116
+ machine->ram);
117
+
118
+ orangepi_binfo.loader_start = h3->memmap[AW_H3_SDRAM];
119
+ orangepi_binfo.ram_size = machine->ram_size;
120
+ arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
121
+}
39
+}
122
+
40
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
123
+static void orangepi_machine_init(MachineClass *mc)
124
+{
125
+ mc->desc = "Orange Pi PC";
126
+ mc->init = orangepi_init;
127
+ mc->min_cpus = AW_H3_NUM_CPUS;
128
+ mc->max_cpus = AW_H3_NUM_CPUS;
129
+ mc->default_cpus = AW_H3_NUM_CPUS;
130
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
131
+ mc->default_ram_size = 1 * GiB;
132
+ mc->default_ram_id = "orangepi.ram";
133
+}
134
+
135
+DEFINE_MACHINE("orangepi-pc", orangepi_machine_init)
136
diff --git a/MAINTAINERS b/MAINTAINERS
137
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
138
--- a/MAINTAINERS
42
--- a/hw/acpi/meson.build
139
+++ b/MAINTAINERS
43
+++ b/hw/acpi/meson.build
140
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
44
@@ -XXX,XX +XXX,XX @@ acpi_ss.add(when: 'CONFIG_ACPI_PCI', if_true: files('pci.c'))
141
S: Maintained
45
acpi_ss.add(when: 'CONFIG_ACPI_VMGENID', if_true: files('vmgenid.c'))
142
F: hw/*/allwinner-h3*
46
acpi_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device.c'))
143
F: include/hw/*/allwinner-h3*
47
acpi_ss.add(when: 'CONFIG_ACPI_HMAT', if_true: files('hmat.c'))
144
+F: hw/arm/orangepi.c
48
-acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'))
145
49
+acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'), if_false: files('ghes-stub.c'))
146
ARM PrimeCell and CMSDK devices
50
acpi_ss.add(when: 'CONFIG_ACPI_X86', if_true: files('core.c', 'piix4.c', 'pcihp.c'), if_false: files('acpi-stub.c'))
147
M: Peter Maydell <peter.maydell@linaro.org>
51
acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c'))
52
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
53
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
54
acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
55
-softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c'))
56
+softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c'))
57
softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
58
softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c',
59
- 'acpi-x86-stub.c', 'ipmi-stub.c'))
60
+ 'acpi-x86-stub.c', 'ipmi-stub.c', 'ghes-stub.c'))
148
--
61
--
149
2.20.1
62
2.20.1
150
63
151
64
diff view generated by jsdifflib
New patch
1
Allow code elsewhere in the system to check whether the ACPI GHES
2
table is present, so it can determine whether it is OK to try to
3
record an error by calling acpi_ghes_record_errors().
1
4
5
(We don't need to migrate the new 'present' field in AcpiGhesState,
6
because it is set once at system initialization and doesn't change.)
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
11
Message-id: 20210603171259.27962-3-peter.maydell@linaro.org
12
---
13
include/hw/acpi/ghes.h | 9 +++++++++
14
hw/acpi/ghes-stub.c | 5 +++++
15
hw/acpi/ghes.c | 17 +++++++++++++++++
16
3 files changed, 31 insertions(+)
17
18
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/acpi/ghes.h
21
+++ b/include/hw/acpi/ghes.h
22
@@ -XXX,XX +XXX,XX @@ enum {
23
24
typedef struct AcpiGhesState {
25
uint64_t ghes_addr_le;
26
+ bool present; /* True if GHES is present at all on this board */
27
} AcpiGhesState;
28
29
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
30
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
31
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
32
GArray *hardware_errors);
33
int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
34
+
35
+/**
36
+ * acpi_ghes_present: Report whether ACPI GHES table is present
37
+ *
38
+ * Returns: true if the system has an ACPI GHES table and it is
39
+ * safe to call acpi_ghes_record_errors() to record a memory error.
40
+ */
41
+bool acpi_ghes_present(void);
42
#endif
43
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/acpi/ghes-stub.c
46
+++ b/hw/acpi/ghes-stub.c
47
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
48
{
49
return -1;
50
}
51
+
52
+bool acpi_ghes_present(void)
53
+{
54
+ return false;
55
+}
56
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/acpi/ghes.c
59
+++ b/hw/acpi/ghes.c
60
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
61
/* Create a read-write fw_cfg file for Address */
62
fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
63
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
64
+
65
+ ags->present = true;
66
}
67
68
int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
69
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
70
71
return ret;
72
}
73
+
74
+bool acpi_ghes_present(void)
75
+{
76
+ AcpiGedState *acpi_ged_state;
77
+ AcpiGhesState *ags;
78
+
79
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
80
+ NULL));
81
+
82
+ if (!acpi_ged_state) {
83
+ return false;
84
+ }
85
+ ags = &acpi_ged_state->ghes_state;
86
+ return ags->present;
87
+}
88
--
89
2.20.1
90
91
diff view generated by jsdifflib
1
From: Beata Michalska <beata.michalska@linaro.org>
1
The virt_is_acpi_enabled() function is specific to the virt board, as
2
is the check for its 'ras' property. Use the new acpi_ghes_present()
3
function to check whether we should report memory errors via
4
acpi_ghes_record_errors().
2
5
3
KVM_SET_VCPU_EVENTS might actually lead to vcpu registers being modified.
6
This avoids a link error if QEMU was built without support for the
4
As such this should be the last step of sync to avoid potential overwriting
7
virt board, and provides a mechanism that can be used by any future
5
of whatever changes KVM might have done.
8
board models that want to add ACPI memory error reporting support
9
(they only need to call acpi_ghes_add_fw_cfg()).
6
10
7
Signed-off-by: Beata Michalska <beata.michalska@linaro.org>
8
Reviewed-by: Andrew Jones <drjones@redhat.com>
9
Message-id: 20200312003401.29017-2-beata.michalska@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
14
Message-id: 20210603171259.27962-4-peter.maydell@linaro.org
11
---
15
---
12
target/arm/kvm32.c | 15 ++++++++++-----
16
target/arm/kvm64.c | 6 +-----
13
target/arm/kvm64.c | 15 ++++++++++-----
17
1 file changed, 1 insertion(+), 5 deletions(-)
14
2 files changed, 20 insertions(+), 10 deletions(-)
15
18
16
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm32.c
19
+++ b/target/arm/kvm32.c
20
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
21
return ret;
22
}
23
24
- ret = kvm_put_vcpu_events(cpu);
25
- if (ret) {
26
- return ret;
27
- }
28
-
29
write_cpustate_to_list(cpu, true);
30
31
if (!write_list_to_kvmstate(cpu, level)) {
32
return EINVAL;
33
}
34
35
+ /*
36
+ * Setting VCPU events should be triggered after syncing the registers
37
+ * to avoid overwriting potential changes made by KVM upon calling
38
+ * KVM_SET_VCPU_EVENTS ioctl
39
+ */
40
+ ret = kvm_put_vcpu_events(cpu);
41
+ if (ret) {
42
+ return ret;
43
+ }
44
+
45
kvm_arm_sync_mpstate_to_kvm(cpu);
46
47
return ret;
48
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
19
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
49
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/kvm64.c
21
--- a/target/arm/kvm64.c
51
+++ b/target/arm/kvm64.c
22
+++ b/target/arm/kvm64.c
52
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
23
@@ -XXX,XX +XXX,XX @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
53
return ret;
24
{
54
}
25
ram_addr_t ram_addr;
55
26
hwaddr paddr;
56
- ret = kvm_put_vcpu_events(cpu);
27
- Object *obj = qdev_get_machine();
57
- if (ret) {
28
- VirtMachineState *vms = VIRT_MACHINE(obj);
58
- return ret;
29
- bool acpi_enabled = virt_is_acpi_enabled(vms);
59
- }
30
60
-
31
assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
61
write_cpustate_to_list(cpu, true);
32
62
33
- if (acpi_enabled && addr &&
63
if (!write_list_to_kvmstate(cpu, level)) {
34
- object_property_get_bool(obj, "ras", NULL)) {
64
return -EINVAL;
35
+ if (acpi_ghes_present() && addr) {
65
}
36
ram_addr = qemu_ram_addr_from_host(addr);
66
37
if (ram_addr != RAM_ADDR_INVALID &&
67
+ /*
38
kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
68
+ * Setting VCPU events should be triggered after syncing the registers
69
+ * to avoid overwriting potential changes made by KVM upon calling
70
+ * KVM_SET_VCPU_EVENTS ioctl
71
+ */
72
+ ret = kvm_put_vcpu_events(cpu);
73
+ if (ret) {
74
+ return ret;
75
+ }
76
+
77
kvm_arm_sync_mpstate_to_kvm(cpu);
78
79
return ret;
80
--
39
--
81
2.20.1
40
2.20.1
82
41
83
42
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
These days the Arm architecture has a wide range of fine-grained
2
optional extra architectural features. We implement quite a lot
3
of these but by no means all of them. Document what we do implement,
4
so that users can find out without having to dig through back-issues
5
of our Changelog on the wiki.
2
6
3
Mention 'max' value in the gic-version property description.
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20210617140328.28622-1-peter.maydell@linaro.org
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
12
docs/system/arm/emulation.rst | 102 ++++++++++++++++++++++++++++++++++
13
docs/system/target-arm.rst | 6 ++
14
2 files changed, 108 insertions(+)
15
create mode 100644 docs/system/arm/emulation.rst
4
16
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
new file mode 100644
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
19
index XXXXXXX..XXXXXXX
8
Message-id: 20200311131618.7187-2-eric.auger@redhat.com
20
--- /dev/null
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
+++ b/docs/system/arm/emulation.rst
10
---
22
@@ -XXX,XX +XXX,XX @@
11
hw/arm/virt.c | 3 ++-
23
+A-profile CPU architecture support
12
1 file changed, 2 insertions(+), 1 deletion(-)
24
+==================================
13
25
+
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
26
+QEMU's TCG emulation includes support for the Armv5, Armv6, Armv7 and
27
+Armv8 versions of the A-profile architecture. It also has support for
28
+the following architecture extensions:
29
+
30
+- FEAT_AA32BF16 (AArch32 BFloat16 instructions)
31
+- FEAT_AA32HPD (AArch32 hierarchical permission disables)
32
+- FEAT_AA32I8MM (AArch32 Int8 matrix multiplication instructions)
33
+- FEAT_AES (AESD and AESE instructions)
34
+- FEAT_BF16 (AArch64 BFloat16 instructions)
35
+- FEAT_BTI (Branch Target Identification)
36
+- FEAT_DIT (Data Independent Timing instructions)
37
+- FEAT_DPB (DC CVAP instruction)
38
+- FEAT_DotProd (Advanced SIMD dot product instructions)
39
+- FEAT_FCMA (Floating-point complex number instructions)
40
+- FEAT_FHM (Floating-point half-precision multiplication instructions)
41
+- FEAT_FP16 (Half-precision floating-point data processing)
42
+- FEAT_FRINTTS (Floating-point to integer instructions)
43
+- FEAT_FlagM (Flag manipulation instructions v2)
44
+- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
45
+- FEAT_HPDS (Hierarchical permission disables)
46
+- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
47
+- FEAT_JSCVT (JavaScript conversion instructions)
48
+- FEAT_LOR (Limited ordering regions)
49
+- FEAT_LRCPC (Load-acquire RCpc instructions)
50
+- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
51
+- FEAT_LSE (Large System Extensions)
52
+- FEAT_MTE (Memory Tagging Extension)
53
+- FEAT_MTE2 (Memory Tagging Extension)
54
+- FEAT_PAN (Privileged access never)
55
+- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
56
+- FEAT_PAuth (Pointer authentication)
57
+- FEAT_PMULL (PMULL, PMULL2 instructions)
58
+- FEAT_PMUv3p1 (PMU Extensions v3.1)
59
+- FEAT_PMUv3p4 (PMU Extensions v3.4)
60
+- FEAT_RDM (Advanced SIMD rounding double multiply accumulate instructions)
61
+- FEAT_RNG (Random number generator)
62
+- FEAT_SB (Speculation Barrier)
63
+- FEAT_SEL2 (Secure EL2)
64
+- FEAT_SHA1 (SHA1 instructions)
65
+- FEAT_SHA256 (SHA256 instructions)
66
+- FEAT_SHA3 (Advanced SIMD SHA3 instructions)
67
+- FEAT_SHA512 (Advanced SIMD SHA512 instructions)
68
+- FEAT_SM3 (Advanced SIMD SM3 instructions)
69
+- FEAT_SM4 (Advanced SIMD SM4 instructions)
70
+- FEAT_SPECRES (Speculation restriction instructions)
71
+- FEAT_SSBS (Speculative Store Bypass Safe)
72
+- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
73
+- FEAT_TLBIRANGE (TLB invalidate range instructions)
74
+- FEAT_TTCNP (Translation table Common not private translations)
75
+- FEAT_TTST (Small translation tables)
76
+- FEAT_UAO (Unprivileged Access Override control)
77
+- FEAT_VHE (Virtualization Host Extensions)
78
+- FEAT_VMID16 (16-bit VMID)
79
+- FEAT_XNX (Translation table stage 2 Unprivileged Execute-never)
80
+- SVE (The Scalable Vector Extension)
81
+- SVE2 (The Scalable Vector Extension v2)
82
+
83
+For information on the specifics of these extensions, please refer
84
+to the `Armv8-A Arm Architecture Reference Manual
85
+<https://developer.arm.com/documentation/ddi0487/latest>`_.
86
+
87
+When a specific named CPU is being emulated, only those features which
88
+are present in hardware for that CPU are emulated. (If a feature is
89
+not in the list above then it is not supported, even if the real
90
+hardware should have it.) The ``max`` CPU enables all features.
91
+
92
+R-profile CPU architecture support
93
+==================================
94
+
95
+QEMU's TCG emulation support for R-profile CPUs is currently limited.
96
+We emulate only the Cortex-R5 and Cortex-R5F CPUs.
97
+
98
+M-profile CPU architecture support
99
+==================================
100
+
101
+QEMU's TCG emulation includes support for Armv6-M, Armv7-M, Armv8-M, and
102
+Armv8.1-M versions of the M-profile architucture. It also has support
103
+for the following architecture extensions:
104
+
105
+- FP (Floating-point Extension)
106
+- FPCXT (FPCXT access instructions)
107
+- HP (Half-precision floating-point instructions)
108
+- LOB (Low Overhead loops and Branch future)
109
+- M (Main Extension)
110
+- MPU (Memory Protection Unit Extension)
111
+- PXN (Privileged Execute Never)
112
+- RAS (Reliability, Serviceability and Availability): "minimum RAS Extension" only
113
+- S (Security Extension)
114
+- ST (System Timer Extension)
115
+
116
+For information on the specifics of these extensions, please refer
117
+to the `Armv8-M Arm Architecture Reference Manual
118
+<https://developer.arm.com/documentation/ddi0553/latest>`_.
119
+
120
+When a specific named CPU is being emulated, only those features which
121
+are present in hardware for that CPU are emulated. (If a feature is
122
+not in the list above then it is not supported, even if the real
123
+hardware should have it.) There is no equivalent of the ``max`` CPU for
124
+M-profile.
125
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
15
index XXXXXXX..XXXXXXX 100644
126
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/virt.c
127
--- a/docs/system/target-arm.rst
17
+++ b/hw/arm/virt.c
128
+++ b/docs/system/target-arm.rst
18
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
129
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
19
virt_set_gic_version, NULL);
130
arm/virt
20
object_property_set_description(obj, "gic-version",
131
arm/xlnx-versal-virt
21
"Set GIC version. "
132
22
- "Valid values are 2, 3 and host", NULL);
133
+Emulated CPU architecture support
23
+ "Valid values are 2, 3, host and max",
134
+=================================
24
+ NULL);
135
+
25
136
+.. toctree::
26
vms->highmem_ecam = !vmc->no_highmem_ecam;
137
+ arm/emulation
138
+
139
Arm CPU features
140
================
27
141
28
--
142
--
29
2.20.1
143
2.20.1
30
144
31
145
diff view generated by jsdifflib
New patch
1
In the code for handling VFP system register accesses there is some
2
stray whitespace after a unary '-' operator, and also some incorrect
3
indent in a couple of function prototypes. We're about to move this
4
code to another file, so fix the code style issues first so
5
checkpatch doesn't complain about the code-movement patch.
1
6
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210618141019.10671-2-peter.maydell@linaro.org
11
---
12
target/arm/translate-vfp.c | 11 +++++------
13
1 file changed, 5 insertions(+), 6 deletions(-)
14
15
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-vfp.c
18
+++ b/target/arm/translate-vfp.c
19
@@ -XXX,XX +XXX,XX @@ static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
20
}
21
22
static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
23
-
24
fp_sysreg_loadfn *loadfn,
25
- void *opaque)
26
+ void *opaque)
27
{
28
/* Do a write to an M-profile floating point system register */
29
TCGv_i32 tmp;
30
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
31
}
32
33
static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
34
- fp_sysreg_storefn *storefn,
35
- void *opaque)
36
+ fp_sysreg_storefn *storefn,
37
+ void *opaque)
38
{
39
/* Do a read from an M-profile floating point system register */
40
TCGv_i32 tmp;
41
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
42
TCGv_i32 addr;
43
44
if (!a->a) {
45
- offset = - offset;
46
+ offset = -offset;
47
}
48
49
addr = load_reg(s, a->rn);
50
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
51
TCGv_i32 value = tcg_temp_new_i32();
52
53
if (!a->a) {
54
- offset = - offset;
55
+ offset = -offset;
56
}
57
58
addr = load_reg(s, a->rn);
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
New patch
1
If the guest makes an FPCXT_NS access when the FPU is disabled,
2
one of two things happens:
3
* if there is no active FP context, then the insn behaves the
4
same way as if the FPU was enabled: writes ignored, reads
5
same value as FPDSCR_NS
6
* if there is an active FP context, then we take a NOCP
7
exception
1
8
9
Add code to the sysreg read/write functions which emits
10
code to take the NOCP exception in the latter case.
11
12
At the moment this will never be used, because the NOCP checks in
13
m-nocp.decode happen first, and so the trans functions are never
14
called when the FPU is disabled. The code will be needed when we
15
move the sysreg access insns to before the NOCP patterns in the
16
following commit.
17
18
Cc: qemu-stable@nongnu.org
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20210618141019.10671-3-peter.maydell@linaro.org
22
---
23
target/arm/translate-vfp.c | 32 ++++++++++++++++++++++++++++++--
24
1 file changed, 30 insertions(+), 2 deletions(-)
25
26
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/translate-vfp.c
29
+++ b/target/arm/translate-vfp.c
30
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
31
lab_end = gen_new_label();
32
/* fpInactive case: write is a NOP, so branch to end */
33
gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
34
- /* !fpInactive: PreserveFPState(), and reads same as FPCXT_S */
35
+ /*
36
+ * !fpInactive: if FPU disabled, take NOCP exception;
37
+ * otherwise PreserveFPState(), and then FPCXT_NS writes
38
+ * behave the same as FPCXT_S writes.
39
+ */
40
+ if (s->fp_excp_el) {
41
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
42
+ syn_uncategorized(), s->fp_excp_el);
43
+ /*
44
+ * This was only a conditional exception, so override
45
+ * gen_exception_insn()'s default to DISAS_NORETURN
46
+ */
47
+ s->base.is_jmp = DISAS_NEXT;
48
+ break;
49
+ }
50
gen_preserve_fp_state(s);
51
/* fall through */
52
case ARM_VFP_FPCXT_S:
53
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
54
tcg_gen_br(lab_end);
55
56
gen_set_label(lab_active);
57
- /* !fpInactive: Reads the same as FPCXT_S, but side effects differ */
58
+ /*
59
+ * !fpInactive: if FPU disabled, take NOCP exception;
60
+ * otherwise PreserveFPState(), and then FPCXT_NS
61
+ * reads the same as FPCXT_S.
62
+ */
63
+ if (s->fp_excp_el) {
64
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
65
+ syn_uncategorized(), s->fp_excp_el);
66
+ /*
67
+ * This was only a conditional exception, so override
68
+ * gen_exception_insn()'s default to DISAS_NORETURN
69
+ */
70
+ s->base.is_jmp = DISAS_NEXT;
71
+ break;
72
+ }
73
gen_preserve_fp_state(s);
74
tmp = tcg_temp_new_i32();
75
sfpa = tcg_temp_new_i32();
76
--
77
2.20.1
78
79
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
The M-profile architecture requires that accesses to FPCXT_NS when
2
there is no active FP state must not take a NOCP fault even if the
3
FPU is disabled. We were not implementing this correctly, because
4
in our decode we catch the NOCP faults early in m-nocp.decode.
2
5
3
The Allwinner Sun8i System on Chip family includes an Ethernet MAC (EMAC)
6
Fix this bug by moving all the handling of M-profile FP system
4
which provides 10M/100M/1000M Ethernet connectivity. This commit
7
register accesses from vfp.decode into m-nocp.decode and putting
5
adds support for the Allwinner EMAC from the Sun8i family (H2+, H3, A33, etc),
8
it above the NOCP blocks. This provides the correct behaviour:
6
including emulation for the following functionality:
9
* for accesses other than FPCXT_NS the trans functions call
10
vfp_access_check(), which will check for FPU disabled and
11
raise a NOCP exception if necessary
12
* for FPCXT_NS we have the special case code that doesn't
13
call vfp_access_check()
14
* when these trans functions want to raise an UNDEF they return
15
false, so the decoder will fall through into the NOCP blocks.
16
This means that NOCP correctly takes precedence over UNDEF
17
for these insns. (This is a difference from the other insns
18
handled by m-nocp.decode, where UNDEF takes precedence and
19
which we implement by having those trans functions call
20
unallocated_encoding() in the appropriate places.)
7
21
8
* DMA transfers
22
[Note for backport to stable: this commit has a semantic dependency
9
* MII interface
23
on commit 9a486856e9173af, which was not marked as cc-stable because
10
* Transmit CRC calculation
24
we didn't know we'd need it for a for-stable bugfix.]
11
25
12
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
26
Cc: qemu-stable@nongnu.org
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20200311221854.30370-10-nieklinnenbank@gmail.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20210618141019.10671-4-peter.maydell@linaro.org
16
---
30
---
17
hw/net/Makefile.objs | 1 +
31
target/arm/translate-a32.h | 1 +
18
include/hw/arm/allwinner-h3.h | 3 +
32
target/arm/m-nocp.decode | 24 ++
19
include/hw/net/allwinner-sun8i-emac.h | 99 +++
33
target/arm/vfp.decode | 14 -
20
hw/arm/allwinner-h3.c | 16 +-
34
target/arm/translate-m-nocp.c | 514 +++++++++++++++++++++++++++++++++
21
hw/arm/orangepi.c | 3 +
35
target/arm/translate-vfp.c | 517 +---------------------------------
22
hw/net/allwinner-sun8i-emac.c | 871 ++++++++++++++++++++++++++
36
5 files changed, 542 insertions(+), 528 deletions(-)
23
hw/arm/Kconfig | 1 +
24
hw/net/Kconfig | 3 +
25
hw/net/trace-events | 10 +
26
9 files changed, 1006 insertions(+), 1 deletion(-)
27
create mode 100644 include/hw/net/allwinner-sun8i-emac.h
28
create mode 100644 hw/net/allwinner-sun8i-emac.c
29
37
30
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
38
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
31
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/net/Makefile.objs
40
--- a/target/arm/translate-a32.h
33
+++ b/hw/net/Makefile.objs
41
+++ b/target/arm/translate-a32.h
34
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XGMAC) += xgmac.o
42
@@ -XXX,XX +XXX,XX @@ bool disas_neon_shared(DisasContext *s, uint32_t insn);
35
common-obj-$(CONFIG_MIPSNET) += mipsnet.o
43
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
36
common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
44
void arm_gen_condlabel(DisasContext *s);
37
common-obj-$(CONFIG_ALLWINNER_EMAC) += allwinner_emac.o
45
bool vfp_access_check(DisasContext *s);
38
+common-obj-$(CONFIG_ALLWINNER_SUN8I_EMAC) += allwinner-sun8i-emac.o
46
+void gen_preserve_fp_state(DisasContext *s);
39
common-obj-$(CONFIG_IMX_FEC) += imx_fec.o
47
void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
40
48
void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
41
common-obj-$(CONFIG_CADENCE) += cadence_gem.o
49
void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
42
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
50
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
43
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
44
--- a/include/hw/arm/allwinner-h3.h
52
--- a/target/arm/m-nocp.decode
45
+++ b/include/hw/arm/allwinner-h3.h
53
+++ b/target/arm/m-nocp.decode
46
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@
47
#include "hw/misc/allwinner-h3-sysctrl.h"
55
48
#include "hw/misc/allwinner-sid.h"
56
&nocp cp
49
#include "hw/sd/allwinner-sdhost.h"
57
50
+#include "hw/net/allwinner-sun8i-emac.h"
58
+# M-profile VLDR/VSTR to sysreg
51
#include "target/arm/cpu.h"
59
+%vldr_sysreg 22:1 13:3
52
60
+%imm7_0x4 0:7 !function=times_4
53
/**
61
+
54
@@ -XXX,XX +XXX,XX @@ enum {
62
+&vldr_sysreg rn reg imm a w p
55
AW_H3_UART1,
63
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
56
AW_H3_UART2,
64
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
57
AW_H3_UART3,
65
+
58
+ AW_H3_EMAC,
66
{
59
AW_H3_GIC_DIST,
67
# Special cases which do not take an early NOCP: VLLDM and VLSTM
60
AW_H3_GIC_CPU,
68
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
61
AW_H3_GIC_HYP,
62
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
63
AwH3SysCtrlState sysctrl;
64
AwSidState sid;
65
AwSdHostState mmc0;
66
+ AwSun8iEmacState emac;
67
GICState gic;
68
MemoryRegion sram_a1;
69
MemoryRegion sram_a2;
70
diff --git a/include/hw/net/allwinner-sun8i-emac.h b/include/hw/net/allwinner-sun8i-emac.h
71
new file mode 100644
72
index XXXXXXX..XXXXXXX
73
--- /dev/null
74
+++ b/include/hw/net/allwinner-sun8i-emac.h
75
@@ -XXX,XX +XXX,XX @@
69
@@ -XXX,XX +XXX,XX @@
70
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
71
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
72
73
+ # FP system register accesses: these are a special case because accesses
74
+ # to FPCXT_NS succeed even if the FPU is disabled. We therefore need
75
+ # to handle them before the big NOCP blocks. Note that within these
76
+ # insns NOCP still has higher priority than UNDEFs; this is implemented
77
+ # by their returning 'false' for UNDEF so as to fall through into the
78
+ # NOCP check (in contrast to VLLDM etc, which call unallocated_encoding()
79
+ # for the UNDEFs there that must take precedence over NOCP.)
80
+
81
+ VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
82
+
83
+ # P=0 W=0 is SEE "Related encodings", so split into two patterns
84
+ VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
85
+ VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
86
+ VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
87
+ VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
88
+
89
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
90
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
91
# From v8.1M onwards this range will also NOCP:
92
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/vfp.decode
95
+++ b/target/arm/vfp.decode
96
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
97
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
98
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
99
100
-# M-profile VLDR/VSTR to sysreg
101
-%vldr_sysreg 22:1 13:3
102
-%imm7_0x4 0:7 !function=times_4
103
-
104
-&vldr_sysreg rn reg imm a w p
105
-@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
106
- reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
107
-
108
-# P=0 W=0 is SEE "Related encodings", so split into two patterns
109
-VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
110
-VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
111
-VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
112
-VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
113
-
114
# We split the load/store multiple up into two patterns to avoid
115
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
116
# grouping:
117
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/translate-m-nocp.c
120
+++ b/target/arm/translate-m-nocp.c
121
@@ -XXX,XX +XXX,XX @@
122
123
#include "qemu/osdep.h"
124
#include "tcg/tcg-op.h"
125
+#include "tcg/tcg-op-gvec.h"
126
#include "translate.h"
127
#include "translate-a32.h"
128
129
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
130
return true;
131
}
132
76
+/*
133
+/*
77
+ * Allwinner Sun8i Ethernet MAC emulation
134
+ * M-profile provides two different sets of instructions that can
78
+ *
135
+ * access floating point system registers: VMSR/VMRS (which move
79
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
136
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
80
+ *
137
+ * move directly to/from memory). In some cases there are also side
81
+ * This program is free software: you can redistribute it and/or modify
138
+ * effects which must happen after any write to memory (which could
82
+ * it under the terms of the GNU General Public License as published by
139
+ * cause an exception). So we implement the common logic for the
83
+ * the Free Software Foundation, either version 2 of the License, or
140
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
84
+ * (at your option) any later version.
141
+ * which take pointers to callback functions which will perform the
85
+ *
142
+ * actual "read/write general purpose register" and "read/write
86
+ * This program is distributed in the hope that it will be useful,
143
+ * memory" operations.
87
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
88
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89
+ * GNU General Public License for more details.
90
+ *
91
+ * You should have received a copy of the GNU General Public License
92
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
93
+ */
144
+ */
94
+
145
+
95
+#ifndef HW_NET_ALLWINNER_SUN8I_EMAC_H
146
+/*
96
+#define HW_NET_ALLWINNER_SUN8I_EMAC_H
147
+ * Emit code to store the sysreg to its final destination; frees the
97
+
148
+ * TCG temp 'value' it is passed.
98
+#include "qom/object.h"
99
+#include "net/net.h"
100
+#include "hw/sysbus.h"
101
+
102
+/**
103
+ * Object model
104
+ * @{
105
+ */
149
+ */
106
+
150
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
107
+#define TYPE_AW_SUN8I_EMAC "allwinner-sun8i-emac"
151
+/*
108
+#define AW_SUN8I_EMAC(obj) \
152
+ * Emit code to load the value to be copied to the sysreg; returns
109
+ OBJECT_CHECK(AwSun8iEmacState, (obj), TYPE_AW_SUN8I_EMAC)
153
+ * a new TCG temporary
110
+
111
+/** @} */
112
+
113
+/**
114
+ * Allwinner Sun8i EMAC object instance state
115
+ */
154
+ */
116
+typedef struct AwSun8iEmacState {
155
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
117
+ /*< private >*/
156
+
118
+ SysBusDevice parent_obj;
157
+/* Common decode/access checks for fp sysreg read/write */
119
+ /*< public >*/
158
+typedef enum FPSysRegCheckResult {
120
+
159
+ FPSysRegCheckFailed, /* caller should return false */
121
+ /** Maps I/O registers in physical memory */
160
+ FPSysRegCheckDone, /* caller should return true */
122
+ MemoryRegion iomem;
161
+ FPSysRegCheckContinue, /* caller should continue generating code */
123
+
162
+} FPSysRegCheckResult;
124
+ /** Interrupt output signal to notify CPU */
163
+
125
+ qemu_irq irq;
164
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
126
+
165
+{
127
+ /** Generic Network Interface Controller (NIC) for networking API */
166
+ if (!dc_isar_feature(aa32_fpsp_v2, s) && !dc_isar_feature(aa32_mve, s)) {
128
+ NICState *nic;
167
+ return FPSysRegCheckFailed;
129
+
168
+ }
130
+ /** Generic Network Interface Controller (NIC) configuration */
169
+
131
+ NICConf conf;
170
+ switch (regno) {
132
+
171
+ case ARM_VFP_FPSCR:
133
+ /**
172
+ case QEMU_VFP_FPSCR_NZCV:
134
+ * @name Media Independent Interface (MII)
173
+ break;
135
+ * @{
174
+ case ARM_VFP_FPSCR_NZCVQC:
175
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
176
+ return FPSysRegCheckFailed;
177
+ }
178
+ break;
179
+ case ARM_VFP_FPCXT_S:
180
+ case ARM_VFP_FPCXT_NS:
181
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
182
+ return FPSysRegCheckFailed;
183
+ }
184
+ if (!s->v8m_secure) {
185
+ return FPSysRegCheckFailed;
186
+ }
187
+ break;
188
+ case ARM_VFP_VPR:
189
+ case ARM_VFP_P0:
190
+ if (!dc_isar_feature(aa32_mve, s)) {
191
+ return FPSysRegCheckFailed;
192
+ }
193
+ break;
194
+ default:
195
+ return FPSysRegCheckFailed;
196
+ }
197
+
198
+ /*
199
+ * FPCXT_NS is a special case: it has specific handling for
200
+ * "current FP state is inactive", and must do the PreserveFPState()
201
+ * but not the usual full set of actions done by ExecuteFPCheck().
202
+ * So we don't call vfp_access_check() and the callers must handle this.
136
+ */
203
+ */
137
+
204
+ if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s)) {
138
+ uint8_t mii_phy_addr; /**< PHY address */
205
+ return FPSysRegCheckDone;
139
+ uint32_t mii_cr; /**< Control */
206
+ }
140
+ uint32_t mii_st; /**< Status */
207
+ return FPSysRegCheckContinue;
141
+ uint32_t mii_adv; /**< Advertised Abilities */
208
+}
142
+
209
+
143
+ /** @} */
210
+static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
144
+
211
+ TCGLabel *label)
145
+ /**
212
+{
146
+ * @name Hardware Registers
213
+ /*
147
+ * @{
214
+ * FPCXT_NS is a special case: it has specific handling for
215
+ * "current FP state is inactive", and must do the PreserveFPState()
216
+ * but not the usual full set of actions done by ExecuteFPCheck().
217
+ * We don't have a TB flag that matches the fpInactive check, so we
218
+ * do it at runtime as we don't expect FPCXT_NS accesses to be frequent.
219
+ *
220
+ * Emit code that checks fpInactive and does a conditional
221
+ * branch to label based on it:
222
+ * if cond is TCG_COND_NE then branch if fpInactive != 0 (ie if inactive)
223
+ * if cond is TCG_COND_EQ then branch if fpInactive == 0 (ie if active)
148
+ */
224
+ */
149
+
225
+ assert(cond == TCG_COND_EQ || cond == TCG_COND_NE);
150
+ uint32_t basic_ctl0; /**< Basic Control 0 */
226
+
151
+ uint32_t basic_ctl1; /**< Basic Control 1 */
227
+ /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
152
+ uint32_t int_en; /**< Interrupt Enable */
228
+ TCGv_i32 aspen, fpca;
153
+ uint32_t int_sta; /**< Interrupt Status */
229
+ aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
154
+ uint32_t frm_flt; /**< Receive Frame Filter */
230
+ fpca = load_cpu_field(v7m.control[M_REG_S]);
155
+
231
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
156
+ uint32_t rx_ctl0; /**< Receive Control 0 */
232
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
157
+ uint32_t rx_ctl1; /**< Receive Control 1 */
233
+ tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
158
+ uint32_t rx_desc_head; /**< Receive Descriptor List Address */
234
+ tcg_gen_or_i32(fpca, fpca, aspen);
159
+ uint32_t rx_desc_curr; /**< Current Receive Descriptor Address */
235
+ tcg_gen_brcondi_i32(tcg_invert_cond(cond), fpca, 0, label);
160
+
236
+ tcg_temp_free_i32(aspen);
161
+ uint32_t tx_ctl0; /**< Transmit Control 0 */
237
+ tcg_temp_free_i32(fpca);
162
+ uint32_t tx_ctl1; /**< Transmit Control 1 */
238
+}
163
+ uint32_t tx_desc_head; /**< Transmit Descriptor List Address */
239
+
164
+ uint32_t tx_desc_curr; /**< Current Transmit Descriptor Address */
240
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
165
+ uint32_t tx_flowctl; /**< Transmit Flow Control */
241
+ fp_sysreg_loadfn *loadfn,
166
+
242
+ void *opaque)
167
+ uint32_t mii_cmd; /**< Management Interface Command */
168
+ uint32_t mii_data; /**< Management Interface Data */
169
+
170
+ /** @} */
171
+
172
+} AwSun8iEmacState;
173
+
174
+#endif /* HW_NET_ALLWINNER_SUN8I_H */
175
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/hw/arm/allwinner-h3.c
178
+++ b/hw/arm/allwinner-h3.c
179
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
180
[AW_H3_UART1] = 0x01c28400,
181
[AW_H3_UART2] = 0x01c28800,
182
[AW_H3_UART3] = 0x01c28c00,
183
+ [AW_H3_EMAC] = 0x01c30000,
184
[AW_H3_GIC_DIST] = 0x01c81000,
185
[AW_H3_GIC_CPU] = 0x01c82000,
186
[AW_H3_GIC_HYP] = 0x01c84000,
187
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
188
{ "twi1", 0x01c2b000, 1 * KiB },
189
{ "twi2", 0x01c2b400, 1 * KiB },
190
{ "scr", 0x01c2c400, 1 * KiB },
191
- { "emac", 0x01c30000, 64 * KiB },
192
{ "gpu", 0x01c40000, 64 * KiB },
193
{ "hstmr", 0x01c60000, 4 * KiB },
194
{ "dramcom", 0x01c62000, 4 * KiB },
195
@@ -XXX,XX +XXX,XX @@ enum {
196
AW_H3_GIC_SPI_OHCI2 = 77,
197
AW_H3_GIC_SPI_EHCI3 = 78,
198
AW_H3_GIC_SPI_OHCI3 = 79,
199
+ AW_H3_GIC_SPI_EMAC = 82
200
};
201
202
/* Allwinner H3 general constants */
203
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
204
205
sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
206
TYPE_AW_SDHOST_SUN5I);
207
+
208
+ sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac),
209
+ TYPE_AW_SUN8I_EMAC);
210
}
211
212
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
213
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
214
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
215
"sd-bus", &error_abort);
216
217
+ /* EMAC */
218
+ if (nd_table[0].used) {
219
+ qemu_check_nic_model(&nd_table[0], TYPE_AW_SUN8I_EMAC);
220
+ qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]);
221
+ }
222
+ qdev_init_nofail(DEVICE(&s->emac));
223
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->emac), 0, s->memmap[AW_H3_EMAC]);
224
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0,
225
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_EMAC));
226
+
227
/* Universal Serial Bus */
228
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
229
qdev_get_gpio_in(DEVICE(&s->gic),
230
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/hw/arm/orangepi.c
233
+++ b/hw/arm/orangepi.c
234
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
235
warn_report("Security Identifier value does not include H3 prefix");
236
}
237
238
+ /* Setup EMAC properties */
239
+ object_property_set_int(OBJECT(&h3->emac), 1, "phy-addr", &error_abort);
240
+
241
/* Mark H3 object realized */
242
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
243
244
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
245
new file mode 100644
246
index XXXXXXX..XXXXXXX
247
--- /dev/null
248
+++ b/hw/net/allwinner-sun8i-emac.c
249
@@ -XXX,XX +XXX,XX @@
250
+/*
251
+ * Allwinner Sun8i Ethernet MAC emulation
252
+ *
253
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
254
+ *
255
+ * This program is free software: you can redistribute it and/or modify
256
+ * it under the terms of the GNU General Public License as published by
257
+ * the Free Software Foundation, either version 2 of the License, or
258
+ * (at your option) any later version.
259
+ *
260
+ * This program is distributed in the hope that it will be useful,
261
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
262
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
263
+ * GNU General Public License for more details.
264
+ *
265
+ * You should have received a copy of the GNU General Public License
266
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
267
+ */
268
+
269
+#include "qemu/osdep.h"
270
+#include "qemu/units.h"
271
+#include "hw/sysbus.h"
272
+#include "migration/vmstate.h"
273
+#include "net/net.h"
274
+#include "hw/irq.h"
275
+#include "hw/qdev-properties.h"
276
+#include "qemu/log.h"
277
+#include "trace.h"
278
+#include "net/checksum.h"
279
+#include "qemu/module.h"
280
+#include "exec/cpu-common.h"
281
+#include "hw/net/allwinner-sun8i-emac.h"
282
+
283
+/* EMAC register offsets */
284
+enum {
285
+ REG_BASIC_CTL_0 = 0x0000, /* Basic Control 0 */
286
+ REG_BASIC_CTL_1 = 0x0004, /* Basic Control 1 */
287
+ REG_INT_STA = 0x0008, /* Interrupt Status */
288
+ REG_INT_EN = 0x000C, /* Interrupt Enable */
289
+ REG_TX_CTL_0 = 0x0010, /* Transmit Control 0 */
290
+ REG_TX_CTL_1 = 0x0014, /* Transmit Control 1 */
291
+ REG_TX_FLOW_CTL = 0x001C, /* Transmit Flow Control */
292
+ REG_TX_DMA_DESC_LIST = 0x0020, /* Transmit Descriptor List Address */
293
+ REG_RX_CTL_0 = 0x0024, /* Receive Control 0 */
294
+ REG_RX_CTL_1 = 0x0028, /* Receive Control 1 */
295
+ REG_RX_DMA_DESC_LIST = 0x0034, /* Receive Descriptor List Address */
296
+ REG_FRM_FLT = 0x0038, /* Receive Frame Filter */
297
+ REG_RX_HASH_0 = 0x0040, /* Receive Hash Table 0 */
298
+ REG_RX_HASH_1 = 0x0044, /* Receive Hash Table 1 */
299
+ REG_MII_CMD = 0x0048, /* Management Interface Command */
300
+ REG_MII_DATA = 0x004C, /* Management Interface Data */
301
+ REG_ADDR_HIGH = 0x0050, /* MAC Address High */
302
+ REG_ADDR_LOW = 0x0054, /* MAC Address Low */
303
+ REG_TX_DMA_STA = 0x00B0, /* Transmit DMA Status */
304
+ REG_TX_CUR_DESC = 0x00B4, /* Transmit Current Descriptor */
305
+ REG_TX_CUR_BUF = 0x00B8, /* Transmit Current Buffer */
306
+ REG_RX_DMA_STA = 0x00C0, /* Receive DMA Status */
307
+ REG_RX_CUR_DESC = 0x00C4, /* Receive Current Descriptor */
308
+ REG_RX_CUR_BUF = 0x00C8, /* Receive Current Buffer */
309
+ REG_RGMII_STA = 0x00D0, /* RGMII Status */
310
+};
311
+
312
+/* EMAC register flags */
313
+enum {
314
+ BASIC_CTL0_100Mbps = (0b11 << 2),
315
+ BASIC_CTL0_FD = (1 << 0),
316
+ BASIC_CTL1_SOFTRST = (1 << 0),
317
+};
318
+
319
+enum {
320
+ INT_STA_RGMII_LINK = (1 << 16),
321
+ INT_STA_RX_EARLY = (1 << 13),
322
+ INT_STA_RX_OVERFLOW = (1 << 12),
323
+ INT_STA_RX_TIMEOUT = (1 << 11),
324
+ INT_STA_RX_DMA_STOP = (1 << 10),
325
+ INT_STA_RX_BUF_UA = (1 << 9),
326
+ INT_STA_RX = (1 << 8),
327
+ INT_STA_TX_EARLY = (1 << 5),
328
+ INT_STA_TX_UNDERFLOW = (1 << 4),
329
+ INT_STA_TX_TIMEOUT = (1 << 3),
330
+ INT_STA_TX_BUF_UA = (1 << 2),
331
+ INT_STA_TX_DMA_STOP = (1 << 1),
332
+ INT_STA_TX = (1 << 0),
333
+};
334
+
335
+enum {
336
+ INT_EN_RX_EARLY = (1 << 13),
337
+ INT_EN_RX_OVERFLOW = (1 << 12),
338
+ INT_EN_RX_TIMEOUT = (1 << 11),
339
+ INT_EN_RX_DMA_STOP = (1 << 10),
340
+ INT_EN_RX_BUF_UA = (1 << 9),
341
+ INT_EN_RX = (1 << 8),
342
+ INT_EN_TX_EARLY = (1 << 5),
343
+ INT_EN_TX_UNDERFLOW = (1 << 4),
344
+ INT_EN_TX_TIMEOUT = (1 << 3),
345
+ INT_EN_TX_BUF_UA = (1 << 2),
346
+ INT_EN_TX_DMA_STOP = (1 << 1),
347
+ INT_EN_TX = (1 << 0),
348
+};
349
+
350
+enum {
351
+ TX_CTL0_TX_EN = (1 << 31),
352
+ TX_CTL1_TX_DMA_START = (1 << 31),
353
+ TX_CTL1_TX_DMA_EN = (1 << 30),
354
+ TX_CTL1_TX_FLUSH = (1 << 0),
355
+};
356
+
357
+enum {
358
+ RX_CTL0_RX_EN = (1 << 31),
359
+ RX_CTL0_STRIP_FCS = (1 << 28),
360
+ RX_CTL0_CRC_IPV4 = (1 << 27),
361
+};
362
+
363
+enum {
364
+ RX_CTL1_RX_DMA_START = (1 << 31),
365
+ RX_CTL1_RX_DMA_EN = (1 << 30),
366
+ RX_CTL1_RX_MD = (1 << 1),
367
+};
368
+
369
+enum {
370
+ RX_FRM_FLT_DIS_ADDR = (1 << 31),
371
+};
372
+
373
+enum {
374
+ MII_CMD_PHY_ADDR_SHIFT = (12),
375
+ MII_CMD_PHY_ADDR_MASK = (0xf000),
376
+ MII_CMD_PHY_REG_SHIFT = (4),
377
+ MII_CMD_PHY_REG_MASK = (0xf0),
378
+ MII_CMD_PHY_RW = (1 << 1),
379
+ MII_CMD_PHY_BUSY = (1 << 0),
380
+};
381
+
382
+enum {
383
+ TX_DMA_STA_STOP = (0b000),
384
+ TX_DMA_STA_RUN_FETCH = (0b001),
385
+ TX_DMA_STA_WAIT_STA = (0b010),
386
+};
387
+
388
+enum {
389
+ RX_DMA_STA_STOP = (0b000),
390
+ RX_DMA_STA_RUN_FETCH = (0b001),
391
+ RX_DMA_STA_WAIT_FRM = (0b011),
392
+};
393
+
394
+/* EMAC register reset values */
395
+enum {
396
+ REG_BASIC_CTL_1_RST = 0x08000000,
397
+};
398
+
399
+/* EMAC constants */
400
+enum {
401
+ AW_SUN8I_EMAC_MIN_PKT_SZ = 64
402
+};
403
+
404
+/* Transmit/receive frame descriptor */
405
+typedef struct FrameDescriptor {
406
+ uint32_t status;
407
+ uint32_t status2;
408
+ uint32_t addr;
409
+ uint32_t next;
410
+} FrameDescriptor;
411
+
412
+/* Frame descriptor flags */
413
+enum {
414
+ DESC_STATUS_CTL = (1 << 31),
415
+ DESC_STATUS2_BUF_SIZE_MASK = (0x7ff),
416
+};
417
+
418
+/* Transmit frame descriptor flags */
419
+enum {
420
+ TX_DESC_STATUS_LENGTH_ERR = (1 << 14),
421
+ TX_DESC_STATUS2_FIRST_DESC = (1 << 29),
422
+ TX_DESC_STATUS2_LAST_DESC = (1 << 30),
423
+ TX_DESC_STATUS2_CHECKSUM_MASK = (0x3 << 27),
424
+};
425
+
426
+/* Receive frame descriptor flags */
427
+enum {
428
+ RX_DESC_STATUS_FIRST_DESC = (1 << 9),
429
+ RX_DESC_STATUS_LAST_DESC = (1 << 8),
430
+ RX_DESC_STATUS_FRM_LEN_MASK = (0x3fff0000),
431
+ RX_DESC_STATUS_FRM_LEN_SHIFT = (16),
432
+ RX_DESC_STATUS_NO_BUF = (1 << 14),
433
+ RX_DESC_STATUS_HEADER_ERR = (1 << 7),
434
+ RX_DESC_STATUS_LENGTH_ERR = (1 << 4),
435
+ RX_DESC_STATUS_CRC_ERR = (1 << 1),
436
+ RX_DESC_STATUS_PAYLOAD_ERR = (1 << 0),
437
+ RX_DESC_STATUS2_RX_INT_CTL = (1 << 31),
438
+};
439
+
440
+/* MII register offsets */
441
+enum {
442
+ MII_REG_CR = (0x0), /* Control */
443
+ MII_REG_ST = (0x1), /* Status */
444
+ MII_REG_ID_HIGH = (0x2), /* Identifier High */
445
+ MII_REG_ID_LOW = (0x3), /* Identifier Low */
446
+ MII_REG_ADV = (0x4), /* Advertised abilities */
447
+ MII_REG_LPA = (0x5), /* Link partner abilities */
448
+};
449
+
450
+/* MII register flags */
451
+enum {
452
+ MII_REG_CR_RESET = (1 << 15),
453
+ MII_REG_CR_POWERDOWN = (1 << 11),
454
+ MII_REG_CR_10Mbit = (0),
455
+ MII_REG_CR_100Mbit = (1 << 13),
456
+ MII_REG_CR_1000Mbit = (1 << 6),
457
+ MII_REG_CR_AUTO_NEG = (1 << 12),
458
+ MII_REG_CR_AUTO_NEG_RESTART = (1 << 9),
459
+ MII_REG_CR_FULLDUPLEX = (1 << 8),
460
+};
461
+
462
+enum {
463
+ MII_REG_ST_100BASE_T4 = (1 << 15),
464
+ MII_REG_ST_100BASE_X_FD = (1 << 14),
465
+ MII_REG_ST_100BASE_X_HD = (1 << 13),
466
+ MII_REG_ST_10_FD = (1 << 12),
467
+ MII_REG_ST_10_HD = (1 << 11),
468
+ MII_REG_ST_100BASE_T2_FD = (1 << 10),
469
+ MII_REG_ST_100BASE_T2_HD = (1 << 9),
470
+ MII_REG_ST_AUTONEG_COMPLETE = (1 << 5),
471
+ MII_REG_ST_AUTONEG_AVAIL = (1 << 3),
472
+ MII_REG_ST_LINK_UP = (1 << 2),
473
+};
474
+
475
+enum {
476
+ MII_REG_LPA_10_HD = (1 << 5),
477
+ MII_REG_LPA_10_FD = (1 << 6),
478
+ MII_REG_LPA_100_HD = (1 << 7),
479
+ MII_REG_LPA_100_FD = (1 << 8),
480
+ MII_REG_LPA_PAUSE = (1 << 10),
481
+ MII_REG_LPA_ASYMPAUSE = (1 << 11),
482
+};
483
+
484
+/* MII constants */
485
+enum {
486
+ MII_PHY_ID_HIGH = 0x0044,
487
+ MII_PHY_ID_LOW = 0x1400,
488
+};
489
+
490
+static void allwinner_sun8i_emac_mii_set_link(AwSun8iEmacState *s,
491
+ bool link_active)
492
+{
243
+{
493
+ if (link_active) {
244
+ /* Do a write to an M-profile floating point system register */
494
+ s->mii_st |= MII_REG_ST_LINK_UP;
245
+ TCGv_i32 tmp;
495
+ } else {
246
+ TCGLabel *lab_end = NULL;
496
+ s->mii_st &= ~MII_REG_ST_LINK_UP;
247
+
497
+ }
248
+ switch (fp_sysreg_checks(s, regno)) {
498
+}
249
+ case FPSysRegCheckFailed:
499
+
250
+ return false;
500
+static void allwinner_sun8i_emac_mii_reset(AwSun8iEmacState *s,
251
+ case FPSysRegCheckDone:
501
+ bool link_active)
252
+ return true;
502
+{
253
+ case FPSysRegCheckContinue:
503
+ s->mii_cr = MII_REG_CR_100Mbit | MII_REG_CR_AUTO_NEG |
254
+ break;
504
+ MII_REG_CR_FULLDUPLEX;
255
+ }
505
+ s->mii_st = MII_REG_ST_100BASE_T4 | MII_REG_ST_100BASE_X_FD |
256
+
506
+ MII_REG_ST_100BASE_X_HD | MII_REG_ST_10_FD | MII_REG_ST_10_HD |
257
+ switch (regno) {
507
+ MII_REG_ST_100BASE_T2_FD | MII_REG_ST_100BASE_T2_HD |
258
+ case ARM_VFP_FPSCR:
508
+ MII_REG_ST_AUTONEG_COMPLETE | MII_REG_ST_AUTONEG_AVAIL;
259
+ tmp = loadfn(s, opaque);
509
+ s->mii_adv = 0;
260
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
510
+
261
+ tcg_temp_free_i32(tmp);
511
+ allwinner_sun8i_emac_mii_set_link(s, link_active);
262
+ gen_lookup_tb(s);
512
+}
263
+ break;
513
+
264
+ case ARM_VFP_FPSCR_NZCVQC:
514
+static void allwinner_sun8i_emac_mii_cmd(AwSun8iEmacState *s)
265
+ {
515
+{
266
+ TCGv_i32 fpscr;
516
+ uint8_t addr, reg;
267
+ tmp = loadfn(s, opaque);
517
+
268
+ if (dc_isar_feature(aa32_mve, s)) {
518
+ addr = (s->mii_cmd & MII_CMD_PHY_ADDR_MASK) >> MII_CMD_PHY_ADDR_SHIFT;
269
+ /* QC is only present for MVE; otherwise RES0 */
519
+ reg = (s->mii_cmd & MII_CMD_PHY_REG_MASK) >> MII_CMD_PHY_REG_SHIFT;
270
+ TCGv_i32 qc = tcg_temp_new_i32();
520
+
271
+ tcg_gen_andi_i32(qc, tmp, FPCR_QC);
521
+ if (addr != s->mii_phy_addr) {
272
+ /*
522
+ return;
273
+ * The 4 vfp.qc[] fields need only be "zero" vs "non-zero";
523
+ }
274
+ * here writing the same value into all elements is simplest.
524
+
275
+ */
525
+ /* Read or write a PHY register? */
276
+ tcg_gen_gvec_dup_i32(MO_32, offsetof(CPUARMState, vfp.qc),
526
+ if (s->mii_cmd & MII_CMD_PHY_RW) {
277
+ 16, 16, qc);
527
+ trace_allwinner_sun8i_emac_mii_write_reg(reg, s->mii_data);
278
+ }
528
+
279
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
529
+ switch (reg) {
280
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
530
+ case MII_REG_CR:
281
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
531
+ if (s->mii_data & MII_REG_CR_RESET) {
282
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
532
+ allwinner_sun8i_emac_mii_reset(s, s->mii_st &
283
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
533
+ MII_REG_ST_LINK_UP);
284
+ tcg_temp_free_i32(tmp);
534
+ } else {
285
+ break;
535
+ s->mii_cr = s->mii_data & ~(MII_REG_CR_RESET |
286
+ }
536
+ MII_REG_CR_AUTO_NEG_RESTART);
287
+ case ARM_VFP_FPCXT_NS:
537
+ }
288
+ lab_end = gen_new_label();
538
+ break;
289
+ /* fpInactive case: write is a NOP, so branch to end */
539
+ case MII_REG_ADV:
290
+ gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
540
+ s->mii_adv = s->mii_data;
291
+ /*
541
+ break;
292
+ * !fpInactive: if FPU disabled, take NOCP exception;
542
+ case MII_REG_ID_HIGH:
293
+ * otherwise PreserveFPState(), and then FPCXT_NS writes
543
+ case MII_REG_ID_LOW:
294
+ * behave the same as FPCXT_S writes.
544
+ case MII_REG_LPA:
295
+ */
545
+ break;
296
+ if (s->fp_excp_el) {
546
+ default:
297
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
547
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: write access to "
298
+ syn_uncategorized(), s->fp_excp_el);
548
+ "unknown MII register 0x%x\n", reg);
299
+ /*
300
+ * This was only a conditional exception, so override
301
+ * gen_exception_insn()'s default to DISAS_NORETURN
302
+ */
303
+ s->base.is_jmp = DISAS_NEXT;
549
+ break;
304
+ break;
550
+ }
305
+ }
551
+ } else {
306
+ gen_preserve_fp_state(s);
552
+ switch (reg) {
307
+ /* fall through */
553
+ case MII_REG_CR:
308
+ case ARM_VFP_FPCXT_S:
554
+ s->mii_data = s->mii_cr;
309
+ {
555
+ break;
310
+ TCGv_i32 sfpa, control;
556
+ case MII_REG_ST:
311
+ /*
557
+ s->mii_data = s->mii_st;
312
+ * Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
558
+ break;
313
+ * bits [27:0] from value and zeroes bits [31:28].
559
+ case MII_REG_ID_HIGH:
314
+ */
560
+ s->mii_data = MII_PHY_ID_HIGH;
315
+ tmp = loadfn(s, opaque);
561
+ break;
316
+ sfpa = tcg_temp_new_i32();
562
+ case MII_REG_ID_LOW:
317
+ tcg_gen_shri_i32(sfpa, tmp, 31);
563
+ s->mii_data = MII_PHY_ID_LOW;
318
+ control = load_cpu_field(v7m.control[M_REG_S]);
564
+ break;
319
+ tcg_gen_deposit_i32(control, control, sfpa,
565
+ case MII_REG_ADV:
320
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
566
+ s->mii_data = s->mii_adv;
321
+ store_cpu_field(control, v7m.control[M_REG_S]);
567
+ break;
322
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
568
+ case MII_REG_LPA:
323
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
569
+ s->mii_data = MII_REG_LPA_10_HD | MII_REG_LPA_10_FD |
324
+ tcg_temp_free_i32(tmp);
570
+ MII_REG_LPA_100_HD | MII_REG_LPA_100_FD |
325
+ tcg_temp_free_i32(sfpa);
571
+ MII_REG_LPA_PAUSE | MII_REG_LPA_ASYMPAUSE;
326
+ break;
572
+ break;
327
+ }
573
+ default:
328
+ case ARM_VFP_VPR:
574
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: read access to "
329
+ /* Behaves as NOP if not privileged */
575
+ "unknown MII register 0x%x\n", reg);
330
+ if (IS_USER(s)) {
576
+ s->mii_data = 0;
577
+ break;
331
+ break;
578
+ }
332
+ }
579
+
333
+ tmp = loadfn(s, opaque);
580
+ trace_allwinner_sun8i_emac_mii_read_reg(reg, s->mii_data);
334
+ store_cpu_field(tmp, v7m.vpr);
581
+ }
335
+ break;
336
+ case ARM_VFP_P0:
337
+ {
338
+ TCGv_i32 vpr;
339
+ tmp = loadfn(s, opaque);
340
+ vpr = load_cpu_field(v7m.vpr);
341
+ tcg_gen_deposit_i32(vpr, vpr, tmp,
342
+ R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
343
+ store_cpu_field(vpr, v7m.vpr);
344
+ tcg_temp_free_i32(tmp);
345
+ break;
346
+ }
347
+ default:
348
+ g_assert_not_reached();
349
+ }
350
+ if (lab_end) {
351
+ gen_set_label(lab_end);
352
+ }
353
+ return true;
582
+}
354
+}
583
+
355
+
584
+static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s)
356
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
357
+ fp_sysreg_storefn *storefn,
358
+ void *opaque)
585
+{
359
+{
586
+ qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0);
360
+ /* Do a read from an M-profile floating point system register */
587
+}
361
+ TCGv_i32 tmp;
588
+
362
+ TCGLabel *lab_end = NULL;
589
+static uint32_t allwinner_sun8i_emac_next_desc(FrameDescriptor *desc,
363
+ bool lookup_tb = false;
590
+ size_t min_size)
364
+
591
+{
365
+ switch (fp_sysreg_checks(s, regno)) {
592
+ uint32_t paddr = desc->next;
366
+ case FPSysRegCheckFailed:
593
+
367
+ return false;
594
+ cpu_physical_memory_read(paddr, desc, sizeof(*desc));
368
+ case FPSysRegCheckDone:
595
+
369
+ return true;
596
+ if ((desc->status & DESC_STATUS_CTL) &&
370
+ case FPSysRegCheckContinue:
597
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
371
+ break;
598
+ return paddr;
372
+ }
599
+ } else {
373
+
600
+ return 0;
374
+ if (regno == ARM_VFP_FPSCR_NZCVQC && !dc_isar_feature(aa32_mve, s)) {
601
+ }
375
+ /* QC is RES0 without MVE, so NZCVQC simplifies to NZCV */
602
+}
376
+ regno = QEMU_VFP_FPSCR_NZCV;
603
+
377
+ }
604
+static uint32_t allwinner_sun8i_emac_get_desc(FrameDescriptor *desc,
378
+
605
+ uint32_t start_addr,
379
+ switch (regno) {
606
+ size_t min_size)
380
+ case ARM_VFP_FPSCR:
607
+{
381
+ tmp = tcg_temp_new_i32();
608
+ uint32_t desc_addr = start_addr;
382
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
609
+
383
+ storefn(s, opaque, tmp);
610
+ /* Note that the list is a cycle. Last entry points back to the head. */
384
+ break;
611
+ while (desc_addr != 0) {
385
+ case ARM_VFP_FPSCR_NZCVQC:
612
+ cpu_physical_memory_read(desc_addr, desc, sizeof(*desc));
386
+ tmp = tcg_temp_new_i32();
613
+
387
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
614
+ if ((desc->status & DESC_STATUS_CTL) &&
388
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
615
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
389
+ storefn(s, opaque, tmp);
616
+ return desc_addr;
390
+ break;
617
+ } else if (desc->next == start_addr) {
391
+ case QEMU_VFP_FPSCR_NZCV:
618
+ break;
392
+ /*
619
+ } else {
393
+ * Read just NZCV; this is a special case to avoid the
620
+ desc_addr = desc->next;
394
+ * helper call for the "VMRS to CPSR.NZCV" insn.
621
+ }
395
+ */
622
+ }
396
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
623
+
397
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
624
+ return 0;
398
+ storefn(s, opaque, tmp);
625
+}
399
+ break;
626
+
400
+ case ARM_VFP_FPCXT_S:
627
+static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s,
401
+ {
628
+ FrameDescriptor *desc,
402
+ TCGv_i32 control, sfpa, fpscr;
629
+ size_t min_size)
403
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
630
+{
404
+ tmp = tcg_temp_new_i32();
631
+ return allwinner_sun8i_emac_get_desc(desc, s->rx_desc_curr, min_size);
405
+ sfpa = tcg_temp_new_i32();
632
+}
406
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
633
+
407
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
634
+static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
408
+ control = load_cpu_field(v7m.control[M_REG_S]);
635
+ FrameDescriptor *desc,
409
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
636
+ size_t min_size)
410
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
637
+{
411
+ tcg_gen_or_i32(tmp, tmp, sfpa);
638
+ return allwinner_sun8i_emac_get_desc(desc, s->tx_desc_head, min_size);
412
+ tcg_temp_free_i32(sfpa);
639
+}
413
+ /*
640
+
414
+ * Store result before updating FPSCR etc, in case
641
+static void allwinner_sun8i_emac_flush_desc(FrameDescriptor *desc,
415
+ * it is a memory write which causes an exception.
642
+ uint32_t phys_addr)
416
+ */
643
+{
417
+ storefn(s, opaque, tmp);
644
+ cpu_physical_memory_write(phys_addr, desc, sizeof(*desc));
418
+ /*
645
+}
419
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
646
+
420
+ * CONTROL.SFPA; so we'll end the TB here.
647
+static int allwinner_sun8i_emac_can_receive(NetClientState *nc)
421
+ */
648
+{
422
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
649
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
423
+ store_cpu_field(control, v7m.control[M_REG_S]);
650
+ FrameDescriptor desc;
424
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
651
+
425
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
652
+ return (s->rx_ctl0 & RX_CTL0_RX_EN) &&
426
+ tcg_temp_free_i32(fpscr);
653
+ (allwinner_sun8i_emac_rx_desc(s, &desc, 0) != 0);
427
+ lookup_tb = true;
654
+}
428
+ break;
655
+
429
+ }
656
+static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc,
430
+ case ARM_VFP_FPCXT_NS:
657
+ const uint8_t *buf,
431
+ {
658
+ size_t size)
432
+ TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
659
+{
433
+ TCGLabel *lab_active = gen_new_label();
660
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
434
+
661
+ FrameDescriptor desc;
435
+ lookup_tb = true;
662
+ size_t bytes_left = size;
436
+
663
+ size_t desc_bytes = 0;
437
+ gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
664
+ size_t pad_fcs_size = 4;
438
+ /* fpInactive case: reads as FPDSCR_NS */
665
+ size_t padding = 0;
439
+ TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
666
+
440
+ storefn(s, opaque, tmp);
667
+ if (!(s->rx_ctl0 & RX_CTL0_RX_EN)) {
441
+ lab_end = gen_new_label();
668
+ return -1;
442
+ tcg_gen_br(lab_end);
669
+ }
443
+
670
+
444
+ gen_set_label(lab_active);
671
+ s->rx_desc_curr = allwinner_sun8i_emac_rx_desc(s, &desc,
445
+ /*
672
+ AW_SUN8I_EMAC_MIN_PKT_SZ);
446
+ * !fpInactive: if FPU disabled, take NOCP exception;
673
+ if (!s->rx_desc_curr) {
447
+ * otherwise PreserveFPState(), and then FPCXT_NS
674
+ s->int_sta |= INT_STA_RX_BUF_UA;
448
+ * reads the same as FPCXT_S.
675
+ }
449
+ */
676
+
450
+ if (s->fp_excp_el) {
677
+ /* Keep filling RX descriptors until the whole frame is written */
451
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
678
+ while (s->rx_desc_curr && bytes_left > 0) {
452
+ syn_uncategorized(), s->fp_excp_el);
679
+ desc.status &= ~DESC_STATUS_CTL;
453
+ /*
680
+ desc.status &= ~RX_DESC_STATUS_FRM_LEN_MASK;
454
+ * This was only a conditional exception, so override
681
+
455
+ * gen_exception_insn()'s default to DISAS_NORETURN
682
+ if (bytes_left == size) {
456
+ */
683
+ desc.status |= RX_DESC_STATUS_FIRST_DESC;
457
+ s->base.is_jmp = DISAS_NEXT;
684
+ }
685
+
686
+ if ((desc.status2 & DESC_STATUS2_BUF_SIZE_MASK) <
687
+ (bytes_left + pad_fcs_size)) {
688
+ desc_bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
689
+ desc.status |= desc_bytes << RX_DESC_STATUS_FRM_LEN_SHIFT;
690
+ } else {
691
+ padding = pad_fcs_size;
692
+ if (bytes_left < AW_SUN8I_EMAC_MIN_PKT_SZ) {
693
+ padding += (AW_SUN8I_EMAC_MIN_PKT_SZ - bytes_left);
694
+ }
695
+
696
+ desc_bytes = (bytes_left);
697
+ desc.status |= RX_DESC_STATUS_LAST_DESC;
698
+ desc.status |= (bytes_left + padding)
699
+ << RX_DESC_STATUS_FRM_LEN_SHIFT;
700
+ }
701
+
702
+ cpu_physical_memory_write(desc.addr, buf, desc_bytes);
703
+ allwinner_sun8i_emac_flush_desc(&desc, s->rx_desc_curr);
704
+ trace_allwinner_sun8i_emac_receive(s->rx_desc_curr, desc.addr,
705
+ desc_bytes);
706
+
707
+ /* Check if frame needs to raise the receive interrupt */
708
+ if (!(desc.status2 & RX_DESC_STATUS2_RX_INT_CTL)) {
709
+ s->int_sta |= INT_STA_RX;
710
+ }
711
+
712
+ /* Increment variables */
713
+ buf += desc_bytes;
714
+ bytes_left -= desc_bytes;
715
+
716
+ /* Move to the next descriptor */
717
+ s->rx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 64);
718
+ if (!s->rx_desc_curr) {
719
+ /* Not enough buffer space available */
720
+ s->int_sta |= INT_STA_RX_BUF_UA;
721
+ s->rx_desc_curr = s->rx_desc_head;
722
+ break;
458
+ break;
723
+ }
459
+ }
724
+ }
460
+ gen_preserve_fp_state(s);
725
+
461
+ tmp = tcg_temp_new_i32();
726
+ /* Report receive DMA is finished */
462
+ sfpa = tcg_temp_new_i32();
727
+ s->rx_ctl1 &= ~RX_CTL1_RX_DMA_START;
463
+ fpscr = tcg_temp_new_i32();
728
+ allwinner_sun8i_emac_update_irq(s);
464
+ gen_helper_vfp_get_fpscr(fpscr, cpu_env);
729
+
465
+ tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK);
730
+ return size;
466
+ control = load_cpu_field(v7m.control[M_REG_S]);
731
+}
467
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
732
+
468
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
733
+static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
469
+ tcg_gen_or_i32(tmp, tmp, sfpa);
734
+{
470
+ tcg_temp_free_i32(control);
735
+ NetClientState *nc = qemu_get_queue(s->nic);
471
+ /* Store result before updating FPSCR, in case it faults */
736
+ FrameDescriptor desc;
472
+ storefn(s, opaque, tmp);
737
+ size_t bytes = 0;
473
+ /* If SFPA is zero then set FPSCR from FPDSCR_NS */
738
+ size_t packet_bytes = 0;
474
+ fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
739
+ size_t transmitted = 0;
475
+ zero = tcg_const_i32(0);
740
+ static uint8_t packet_buf[2048];
476
+ tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
741
+
477
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
742
+ s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc, 0);
478
+ tcg_temp_free_i32(zero);
743
+
479
+ tcg_temp_free_i32(sfpa);
744
+ /* Read all transmit descriptors */
480
+ tcg_temp_free_i32(fpdscr);
745
+ while (s->tx_desc_curr != 0) {
481
+ tcg_temp_free_i32(fpscr);
746
+
482
+ break;
747
+ /* Read from physical memory into packet buffer */
483
+ }
748
+ bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
484
+ case ARM_VFP_VPR:
749
+ if (bytes + packet_bytes > sizeof(packet_buf)) {
485
+ /* Behaves as NOP if not privileged */
750
+ desc.status |= TX_DESC_STATUS_LENGTH_ERR;
486
+ if (IS_USER(s)) {
751
+ break;
487
+ break;
752
+ }
488
+ }
753
+ cpu_physical_memory_read(desc.addr, packet_buf + packet_bytes, bytes);
489
+ tmp = load_cpu_field(v7m.vpr);
754
+ packet_bytes += bytes;
490
+ storefn(s, opaque, tmp);
755
+ desc.status &= ~DESC_STATUS_CTL;
491
+ break;
756
+ allwinner_sun8i_emac_flush_desc(&desc, s->tx_desc_curr);
492
+ case ARM_VFP_P0:
757
+
493
+ tmp = load_cpu_field(v7m.vpr);
758
+ /* After the last descriptor, send the packet */
494
+ tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
759
+ if (desc.status2 & TX_DESC_STATUS2_LAST_DESC) {
495
+ storefn(s, opaque, tmp);
760
+ if (desc.status2 & TX_DESC_STATUS2_CHECKSUM_MASK) {
496
+ break;
761
+ net_checksum_calculate(packet_buf, packet_bytes);
497
+ default:
762
+ }
498
+ g_assert_not_reached();
763
+
499
+ }
764
+ qemu_send_packet(nc, packet_buf, packet_bytes);
500
+
765
+ trace_allwinner_sun8i_emac_transmit(s->tx_desc_curr, desc.addr,
501
+ if (lab_end) {
766
+ bytes);
502
+ gen_set_label(lab_end);
767
+
503
+ }
768
+ packet_bytes = 0;
504
+ if (lookup_tb) {
769
+ transmitted++;
505
+ gen_lookup_tb(s);
506
+ }
507
+ return true;
508
+}
509
+
510
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
511
+{
512
+ arg_VMSR_VMRS *a = opaque;
513
+
514
+ if (a->rt == 15) {
515
+ /* Set the 4 flag bits in the CPSR */
516
+ gen_set_nzcv(value);
517
+ tcg_temp_free_i32(value);
518
+ } else {
519
+ store_reg(s, a->rt, value);
520
+ }
521
+}
522
+
523
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
524
+{
525
+ arg_VMSR_VMRS *a = opaque;
526
+
527
+ return load_reg(s, a->rt);
528
+}
529
+
530
+static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
531
+{
532
+ /*
533
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
534
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
535
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
536
+ * we only care about the top 4 bits of FPSCR there.
537
+ */
538
+ if (a->rt == 15) {
539
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
540
+ a->reg = QEMU_VFP_FPSCR_NZCV;
541
+ } else {
542
+ return false;
770
+ }
543
+ }
771
+ s->tx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 0);
544
+ }
772
+ }
545
+
773
+
546
+ if (a->l) {
774
+ /* Raise transmit completed interrupt */
547
+ /* VMRS, move FP system register to gp register */
775
+ if (transmitted > 0) {
548
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
776
+ s->int_sta |= INT_STA_TX;
549
+ } else {
777
+ s->tx_ctl1 &= ~TX_CTL1_TX_DMA_START;
550
+ /* VMSR, move gp register to FP system register */
778
+ allwinner_sun8i_emac_update_irq(s);
551
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
779
+ }
552
+ }
780
+}
553
+}
781
+
554
+
782
+static void allwinner_sun8i_emac_reset(DeviceState *dev)
555
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
783
+{
556
+{
784
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(dev);
557
+ arg_vldr_sysreg *a = opaque;
785
+ NetClientState *nc = qemu_get_queue(s->nic);
558
+ uint32_t offset = a->imm;
786
+
559
+ TCGv_i32 addr;
787
+ trace_allwinner_sun8i_emac_reset();
560
+
788
+
561
+ if (!a->a) {
789
+ s->mii_cmd = 0;
562
+ offset = -offset;
790
+ s->mii_data = 0;
563
+ }
791
+ s->basic_ctl0 = 0;
564
+
792
+ s->basic_ctl1 = REG_BASIC_CTL_1_RST;
565
+ addr = load_reg(s, a->rn);
793
+ s->int_en = 0;
566
+ if (a->p) {
794
+ s->int_sta = 0;
567
+ tcg_gen_addi_i32(addr, addr, offset);
795
+ s->frm_flt = 0;
568
+ }
796
+ s->rx_ctl0 = 0;
569
+
797
+ s->rx_ctl1 = RX_CTL1_RX_MD;
570
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
798
+ s->rx_desc_head = 0;
571
+ gen_helper_v8m_stackcheck(cpu_env, addr);
799
+ s->rx_desc_curr = 0;
572
+ }
800
+ s->tx_ctl0 = 0;
573
+
801
+ s->tx_ctl1 = 0;
574
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
802
+ s->tx_desc_head = 0;
575
+ MO_UL | MO_ALIGN | s->be_data);
803
+ s->tx_desc_curr = 0;
576
+ tcg_temp_free_i32(value);
804
+ s->tx_flowctl = 0;
577
+
805
+
578
+ if (a->w) {
806
+ allwinner_sun8i_emac_mii_reset(s, !nc->link_down);
579
+ /* writeback */
580
+ if (!a->p) {
581
+ tcg_gen_addi_i32(addr, addr, offset);
582
+ }
583
+ store_reg(s, a->rn, addr);
584
+ } else {
585
+ tcg_temp_free_i32(addr);
586
+ }
807
+}
587
+}
808
+
588
+
809
+static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset,
589
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
810
+ unsigned size)
811
+{
590
+{
812
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(opaque);
591
+ arg_vldr_sysreg *a = opaque;
813
+ uint64_t value = 0;
592
+ uint32_t offset = a->imm;
814
+ FrameDescriptor desc;
593
+ TCGv_i32 addr;
815
+
594
+ TCGv_i32 value = tcg_temp_new_i32();
816
+ switch (offset) {
595
+
817
+ case REG_BASIC_CTL_0: /* Basic Control 0 */
596
+ if (!a->a) {
818
+ value = s->basic_ctl0;
597
+ offset = -offset;
819
+ break;
598
+ }
820
+ case REG_BASIC_CTL_1: /* Basic Control 1 */
599
+
821
+ value = s->basic_ctl1;
600
+ addr = load_reg(s, a->rn);
822
+ break;
601
+ if (a->p) {
823
+ case REG_INT_STA: /* Interrupt Status */
602
+ tcg_gen_addi_i32(addr, addr, offset);
824
+ value = s->int_sta;
603
+ }
825
+ break;
604
+
826
+ case REG_INT_EN: /* Interupt Enable */
605
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
827
+ value = s->int_en;
606
+ gen_helper_v8m_stackcheck(cpu_env, addr);
828
+ break;
607
+ }
829
+ case REG_TX_CTL_0: /* Transmit Control 0 */
608
+
830
+ value = s->tx_ctl0;
609
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
831
+ break;
610
+ MO_UL | MO_ALIGN | s->be_data);
832
+ case REG_TX_CTL_1: /* Transmit Control 1 */
611
+
833
+ value = s->tx_ctl1;
612
+ if (a->w) {
834
+ break;
613
+ /* writeback */
835
+ case REG_TX_FLOW_CTL: /* Transmit Flow Control */
614
+ if (!a->p) {
836
+ value = s->tx_flowctl;
615
+ tcg_gen_addi_i32(addr, addr, offset);
837
+ break;
838
+ case REG_TX_DMA_DESC_LIST: /* Transmit Descriptor List Address */
839
+ value = s->tx_desc_head;
840
+ break;
841
+ case REG_RX_CTL_0: /* Receive Control 0 */
842
+ value = s->rx_ctl0;
843
+ break;
844
+ case REG_RX_CTL_1: /* Receive Control 1 */
845
+ value = s->rx_ctl1;
846
+ break;
847
+ case REG_RX_DMA_DESC_LIST: /* Receive Descriptor List Address */
848
+ value = s->rx_desc_head;
849
+ break;
850
+ case REG_FRM_FLT: /* Receive Frame Filter */
851
+ value = s->frm_flt;
852
+ break;
853
+ case REG_RX_HASH_0: /* Receive Hash Table 0 */
854
+ case REG_RX_HASH_1: /* Receive Hash Table 1 */
855
+ break;
856
+ case REG_MII_CMD: /* Management Interface Command */
857
+ value = s->mii_cmd;
858
+ break;
859
+ case REG_MII_DATA: /* Management Interface Data */
860
+ value = s->mii_data;
861
+ break;
862
+ case REG_ADDR_HIGH: /* MAC Address High */
863
+ value = *(((uint32_t *) (s->conf.macaddr.a)) + 1);
864
+ break;
865
+ case REG_ADDR_LOW: /* MAC Address Low */
866
+ value = *(uint32_t *) (s->conf.macaddr.a);
867
+ break;
868
+ case REG_TX_DMA_STA: /* Transmit DMA Status */
869
+ break;
870
+ case REG_TX_CUR_DESC: /* Transmit Current Descriptor */
871
+ value = s->tx_desc_curr;
872
+ break;
873
+ case REG_TX_CUR_BUF: /* Transmit Current Buffer */
874
+ if (s->tx_desc_curr != 0) {
875
+ cpu_physical_memory_read(s->tx_desc_curr, &desc, sizeof(desc));
876
+ value = desc.addr;
877
+ } else {
878
+ value = 0;
879
+ }
616
+ }
880
+ break;
617
+ store_reg(s, a->rn, addr);
881
+ case REG_RX_DMA_STA: /* Receive DMA Status */
618
+ } else {
882
+ break;
619
+ tcg_temp_free_i32(addr);
883
+ case REG_RX_CUR_DESC: /* Receive Current Descriptor */
620
+ }
884
+ value = s->rx_desc_curr;
885
+ break;
886
+ case REG_RX_CUR_BUF: /* Receive Current Buffer */
887
+ if (s->rx_desc_curr != 0) {
888
+ cpu_physical_memory_read(s->rx_desc_curr, &desc, sizeof(desc));
889
+ value = desc.addr;
890
+ } else {
891
+ value = 0;
892
+ }
893
+ break;
894
+ case REG_RGMII_STA: /* RGMII Status */
895
+ break;
896
+ default:
897
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: read access to unknown "
898
+ "EMAC register 0x" TARGET_FMT_plx "\n",
899
+ offset);
900
+ }
901
+
902
+ trace_allwinner_sun8i_emac_read(offset, value);
903
+ return value;
621
+ return value;
904
+}
622
+}
905
+
623
+
906
+static void allwinner_sun8i_emac_write(void *opaque, hwaddr offset,
624
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
907
+ uint64_t value, unsigned size)
908
+{
625
+{
909
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(opaque);
626
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
910
+ NetClientState *nc = qemu_get_queue(s->nic);
627
+ return false;
911
+
628
+ }
912
+ trace_allwinner_sun8i_emac_write(offset, value);
629
+ if (a->rn == 15) {
913
+
630
+ return false;
914
+ switch (offset) {
631
+ }
915
+ case REG_BASIC_CTL_0: /* Basic Control 0 */
632
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
916
+ s->basic_ctl0 = value;
917
+ break;
918
+ case REG_BASIC_CTL_1: /* Basic Control 1 */
919
+ if (value & BASIC_CTL1_SOFTRST) {
920
+ allwinner_sun8i_emac_reset(DEVICE(s));
921
+ value &= ~BASIC_CTL1_SOFTRST;
922
+ }
923
+ s->basic_ctl1 = value;
924
+ if (allwinner_sun8i_emac_can_receive(nc)) {
925
+ qemu_flush_queued_packets(nc);
926
+ }
927
+ break;
928
+ case REG_INT_STA: /* Interrupt Status */
929
+ s->int_sta &= ~value;
930
+ allwinner_sun8i_emac_update_irq(s);
931
+ break;
932
+ case REG_INT_EN: /* Interrupt Enable */
933
+ s->int_en = value;
934
+ allwinner_sun8i_emac_update_irq(s);
935
+ break;
936
+ case REG_TX_CTL_0: /* Transmit Control 0 */
937
+ s->tx_ctl0 = value;
938
+ break;
939
+ case REG_TX_CTL_1: /* Transmit Control 1 */
940
+ s->tx_ctl1 = value;
941
+ if (value & TX_CTL1_TX_DMA_EN) {
942
+ allwinner_sun8i_emac_transmit(s);
943
+ }
944
+ break;
945
+ case REG_TX_FLOW_CTL: /* Transmit Flow Control */
946
+ s->tx_flowctl = value;
947
+ break;
948
+ case REG_TX_DMA_DESC_LIST: /* Transmit Descriptor List Address */
949
+ s->tx_desc_head = value;
950
+ s->tx_desc_curr = value;
951
+ break;
952
+ case REG_RX_CTL_0: /* Receive Control 0 */
953
+ s->rx_ctl0 = value;
954
+ break;
955
+ case REG_RX_CTL_1: /* Receive Control 1 */
956
+ s->rx_ctl1 = value | RX_CTL1_RX_MD;
957
+ if ((value & RX_CTL1_RX_DMA_EN) &&
958
+ allwinner_sun8i_emac_can_receive(nc)) {
959
+ qemu_flush_queued_packets(nc);
960
+ }
961
+ break;
962
+ case REG_RX_DMA_DESC_LIST: /* Receive Descriptor List Address */
963
+ s->rx_desc_head = value;
964
+ s->rx_desc_curr = value;
965
+ break;
966
+ case REG_FRM_FLT: /* Receive Frame Filter */
967
+ s->frm_flt = value;
968
+ break;
969
+ case REG_RX_HASH_0: /* Receive Hash Table 0 */
970
+ case REG_RX_HASH_1: /* Receive Hash Table 1 */
971
+ break;
972
+ case REG_MII_CMD: /* Management Interface Command */
973
+ s->mii_cmd = value & ~MII_CMD_PHY_BUSY;
974
+ allwinner_sun8i_emac_mii_cmd(s);
975
+ break;
976
+ case REG_MII_DATA: /* Management Interface Data */
977
+ s->mii_data = value;
978
+ break;
979
+ case REG_ADDR_HIGH: /* MAC Address High */
980
+ s->conf.macaddr.a[4] = (value & 0xff);
981
+ s->conf.macaddr.a[5] = (value & 0xff00) >> 8;
982
+ break;
983
+ case REG_ADDR_LOW: /* MAC Address Low */
984
+ s->conf.macaddr.a[0] = (value & 0xff);
985
+ s->conf.macaddr.a[1] = (value & 0xff00) >> 8;
986
+ s->conf.macaddr.a[2] = (value & 0xff0000) >> 16;
987
+ s->conf.macaddr.a[3] = (value & 0xff000000) >> 24;
988
+ break;
989
+ case REG_TX_DMA_STA: /* Transmit DMA Status */
990
+ case REG_TX_CUR_DESC: /* Transmit Current Descriptor */
991
+ case REG_TX_CUR_BUF: /* Transmit Current Buffer */
992
+ case REG_RX_DMA_STA: /* Receive DMA Status */
993
+ case REG_RX_CUR_DESC: /* Receive Current Descriptor */
994
+ case REG_RX_CUR_BUF: /* Receive Current Buffer */
995
+ case REG_RGMII_STA: /* RGMII Status */
996
+ break;
997
+ default:
998
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: write access to unknown "
999
+ "EMAC register 0x" TARGET_FMT_plx "\n",
1000
+ offset);
1001
+ }
1002
+}
633
+}
1003
+
634
+
1004
+static void allwinner_sun8i_emac_set_link(NetClientState *nc)
635
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1005
+{
636
+{
1006
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
637
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
1007
+
638
+ return false;
1008
+ trace_allwinner_sun8i_emac_set_link(!nc->link_down);
639
+ }
1009
+ allwinner_sun8i_emac_mii_set_link(s, !nc->link_down);
640
+ if (a->rn == 15) {
641
+ return false;
642
+ }
643
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
1010
+}
644
+}
1011
+
645
+
1012
+static const MemoryRegionOps allwinner_sun8i_emac_mem_ops = {
646
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
1013
+ .read = allwinner_sun8i_emac_read,
647
{
1014
+ .write = allwinner_sun8i_emac_write,
648
/*
1015
+ .endianness = DEVICE_NATIVE_ENDIAN,
649
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
1016
+ .valid = {
1017
+ .min_access_size = 4,
1018
+ .max_access_size = 4,
1019
+ },
1020
+ .impl.min_access_size = 4,
1021
+};
1022
+
1023
+static NetClientInfo net_allwinner_sun8i_emac_info = {
1024
+ .type = NET_CLIENT_DRIVER_NIC,
1025
+ .size = sizeof(NICState),
1026
+ .can_receive = allwinner_sun8i_emac_can_receive,
1027
+ .receive = allwinner_sun8i_emac_receive,
1028
+ .link_status_changed = allwinner_sun8i_emac_set_link,
1029
+};
1030
+
1031
+static void allwinner_sun8i_emac_init(Object *obj)
1032
+{
1033
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1034
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(obj);
1035
+
1036
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_sun8i_emac_mem_ops,
1037
+ s, TYPE_AW_SUN8I_EMAC, 64 * KiB);
1038
+ sysbus_init_mmio(sbd, &s->iomem);
1039
+ sysbus_init_irq(sbd, &s->irq);
1040
+}
1041
+
1042
+static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp)
1043
+{
1044
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(dev);
1045
+
1046
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
1047
+ s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf,
1048
+ object_get_typename(OBJECT(dev)), dev->id, s);
1049
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
1050
+}
1051
+
1052
+static Property allwinner_sun8i_emac_properties[] = {
1053
+ DEFINE_NIC_PROPERTIES(AwSun8iEmacState, conf),
1054
+ DEFINE_PROP_UINT8("phy-addr", AwSun8iEmacState, mii_phy_addr, 0),
1055
+ DEFINE_PROP_END_OF_LIST(),
1056
+};
1057
+
1058
+static int allwinner_sun8i_emac_post_load(void *opaque, int version_id)
1059
+{
1060
+ AwSun8iEmacState *s = opaque;
1061
+
1062
+ allwinner_sun8i_emac_set_link(qemu_get_queue(s->nic));
1063
+
1064
+ return 0;
1065
+}
1066
+
1067
+static const VMStateDescription vmstate_aw_emac = {
1068
+ .name = "allwinner-sun8i-emac",
1069
+ .version_id = 1,
1070
+ .minimum_version_id = 1,
1071
+ .post_load = allwinner_sun8i_emac_post_load,
1072
+ .fields = (VMStateField[]) {
1073
+ VMSTATE_UINT8(mii_phy_addr, AwSun8iEmacState),
1074
+ VMSTATE_UINT32(mii_cmd, AwSun8iEmacState),
1075
+ VMSTATE_UINT32(mii_data, AwSun8iEmacState),
1076
+ VMSTATE_UINT32(mii_cr, AwSun8iEmacState),
1077
+ VMSTATE_UINT32(mii_st, AwSun8iEmacState),
1078
+ VMSTATE_UINT32(mii_adv, AwSun8iEmacState),
1079
+ VMSTATE_UINT32(basic_ctl0, AwSun8iEmacState),
1080
+ VMSTATE_UINT32(basic_ctl1, AwSun8iEmacState),
1081
+ VMSTATE_UINT32(int_en, AwSun8iEmacState),
1082
+ VMSTATE_UINT32(int_sta, AwSun8iEmacState),
1083
+ VMSTATE_UINT32(frm_flt, AwSun8iEmacState),
1084
+ VMSTATE_UINT32(rx_ctl0, AwSun8iEmacState),
1085
+ VMSTATE_UINT32(rx_ctl1, AwSun8iEmacState),
1086
+ VMSTATE_UINT32(rx_desc_head, AwSun8iEmacState),
1087
+ VMSTATE_UINT32(rx_desc_curr, AwSun8iEmacState),
1088
+ VMSTATE_UINT32(tx_ctl0, AwSun8iEmacState),
1089
+ VMSTATE_UINT32(tx_ctl1, AwSun8iEmacState),
1090
+ VMSTATE_UINT32(tx_desc_head, AwSun8iEmacState),
1091
+ VMSTATE_UINT32(tx_desc_curr, AwSun8iEmacState),
1092
+ VMSTATE_UINT32(tx_flowctl, AwSun8iEmacState),
1093
+ VMSTATE_END_OF_LIST()
1094
+ }
1095
+};
1096
+
1097
+static void allwinner_sun8i_emac_class_init(ObjectClass *klass, void *data)
1098
+{
1099
+ DeviceClass *dc = DEVICE_CLASS(klass);
1100
+
1101
+ dc->realize = allwinner_sun8i_emac_realize;
1102
+ dc->reset = allwinner_sun8i_emac_reset;
1103
+ dc->vmsd = &vmstate_aw_emac;
1104
+ device_class_set_props(dc, allwinner_sun8i_emac_properties);
1105
+}
1106
+
1107
+static const TypeInfo allwinner_sun8i_emac_info = {
1108
+ .name = TYPE_AW_SUN8I_EMAC,
1109
+ .parent = TYPE_SYS_BUS_DEVICE,
1110
+ .instance_size = sizeof(AwSun8iEmacState),
1111
+ .instance_init = allwinner_sun8i_emac_init,
1112
+ .class_init = allwinner_sun8i_emac_class_init,
1113
+};
1114
+
1115
+static void allwinner_sun8i_emac_register_types(void)
1116
+{
1117
+ type_register_static(&allwinner_sun8i_emac_info);
1118
+}
1119
+
1120
+type_init(allwinner_sun8i_emac_register_types)
1121
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
1122
index XXXXXXX..XXXXXXX 100644
650
index XXXXXXX..XXXXXXX 100644
1123
--- a/hw/arm/Kconfig
651
--- a/target/arm/translate-vfp.c
1124
+++ b/hw/arm/Kconfig
652
+++ b/target/arm/translate-vfp.c
1125
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
653
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
1126
config ALLWINNER_H3
654
* Generate code for M-profile lazy FP state preservation if needed;
1127
bool
655
* this corresponds to the pseudocode PreserveFPState() function.
1128
select ALLWINNER_A10_PIT
656
*/
1129
+ select ALLWINNER_SUN8I_EMAC
657
-static void gen_preserve_fp_state(DisasContext *s)
1130
select SERIAL
658
+void gen_preserve_fp_state(DisasContext *s)
1131
select ARM_TIMER
659
{
1132
select ARM_GIC
660
if (s->v7m_lspact) {
1133
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
661
/*
1134
index XXXXXXX..XXXXXXX 100644
662
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
1135
--- a/hw/net/Kconfig
663
return true;
1136
+++ b/hw/net/Kconfig
664
}
1137
@@ -XXX,XX +XXX,XX @@ config MIPSNET
665
1138
config ALLWINNER_EMAC
666
-/*
1139
bool
667
- * M-profile provides two different sets of instructions that can
1140
668
- * access floating point system registers: VMSR/VMRS (which move
1141
+config ALLWINNER_SUN8I_EMAC
669
- * to/from a general purpose register) and VLDR/VSTR sysreg (which
1142
+ bool
670
- * move directly to/from memory). In some cases there are also side
1143
+
671
- * effects which must happen after any write to memory (which could
1144
config IMX_FEC
672
- * cause an exception). So we implement the common logic for the
1145
bool
673
- * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
1146
674
- * which take pointers to callback functions which will perform the
1147
diff --git a/hw/net/trace-events b/hw/net/trace-events
675
- * actual "read/write general purpose register" and "read/write
1148
index XXXXXXX..XXXXXXX 100644
676
- * memory" operations.
1149
--- a/hw/net/trace-events
677
- */
1150
+++ b/hw/net/trace-events
678
-
1151
@@ -XXX,XX +XXX,XX @@
679
-/*
1152
# See docs/devel/tracing.txt for syntax documentation.
680
- * Emit code to store the sysreg to its final destination; frees the
1153
681
- * TCG temp 'value' it is passed.
1154
+# allwinner-sun8i-emac.c
682
- */
1155
+allwinner_sun8i_emac_mii_write_reg(uint32_t reg, uint32_t value) "MII write: reg=0x%" PRIx32 " value=0x%" PRIx32
683
-typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
1156
+allwinner_sun8i_emac_mii_read_reg(uint32_t reg, uint32_t value) "MII read: reg=0x%" PRIx32 " value=0x%" PRIx32
684
-/*
1157
+allwinner_sun8i_emac_receive(uint32_t desc, uint32_t paddr, uint32_t bytes) "RX packet: desc=0x%" PRIx32 " paddr=0x%" PRIx32 " bytes=%" PRIu32
685
- * Emit code to load the value to be copied to the sysreg; returns
1158
+allwinner_sun8i_emac_transmit(uint32_t desc, uint32_t paddr, uint32_t bytes) "TX packet: desc=0x%" PRIx32 " paddr=0x%" PRIx32 " bytes=%" PRIu32
686
- * a new TCG temporary
1159
+allwinner_sun8i_emac_reset(void) "HW reset"
687
- */
1160
+allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
688
-typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
1161
+allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
689
-
1162
+allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
690
-/* Common decode/access checks for fp sysreg read/write */
1163
+
691
-typedef enum FPSysRegCheckResult {
1164
# etraxfs_eth.c
692
- FPSysRegCheckFailed, /* caller should return false */
1165
mdio_phy_read(int regnum, uint16_t value) "read phy_reg:%d value:0x%04x"
693
- FPSysRegCheckDone, /* caller should return true */
1166
mdio_phy_write(int regnum, uint16_t value) "write phy_reg:%d value:0x%04x"
694
- FPSysRegCheckContinue, /* caller should continue generating code */
695
-} FPSysRegCheckResult;
696
-
697
-static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
698
-{
699
- if (!dc_isar_feature(aa32_fpsp_v2, s) && !dc_isar_feature(aa32_mve, s)) {
700
- return FPSysRegCheckFailed;
701
- }
702
-
703
- switch (regno) {
704
- case ARM_VFP_FPSCR:
705
- case QEMU_VFP_FPSCR_NZCV:
706
- break;
707
- case ARM_VFP_FPSCR_NZCVQC:
708
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
709
- return FPSysRegCheckFailed;
710
- }
711
- break;
712
- case ARM_VFP_FPCXT_S:
713
- case ARM_VFP_FPCXT_NS:
714
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
715
- return FPSysRegCheckFailed;
716
- }
717
- if (!s->v8m_secure) {
718
- return FPSysRegCheckFailed;
719
- }
720
- break;
721
- case ARM_VFP_VPR:
722
- case ARM_VFP_P0:
723
- if (!dc_isar_feature(aa32_mve, s)) {
724
- return FPSysRegCheckFailed;
725
- }
726
- break;
727
- default:
728
- return FPSysRegCheckFailed;
729
- }
730
-
731
- /*
732
- * FPCXT_NS is a special case: it has specific handling for
733
- * "current FP state is inactive", and must do the PreserveFPState()
734
- * but not the usual full set of actions done by ExecuteFPCheck().
735
- * So we don't call vfp_access_check() and the callers must handle this.
736
- */
737
- if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s)) {
738
- return FPSysRegCheckDone;
739
- }
740
- return FPSysRegCheckContinue;
741
-}
742
-
743
-static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
744
- TCGLabel *label)
745
-{
746
- /*
747
- * FPCXT_NS is a special case: it has specific handling for
748
- * "current FP state is inactive", and must do the PreserveFPState()
749
- * but not the usual full set of actions done by ExecuteFPCheck().
750
- * We don't have a TB flag that matches the fpInactive check, so we
751
- * do it at runtime as we don't expect FPCXT_NS accesses to be frequent.
752
- *
753
- * Emit code that checks fpInactive and does a conditional
754
- * branch to label based on it:
755
- * if cond is TCG_COND_NE then branch if fpInactive != 0 (ie if inactive)
756
- * if cond is TCG_COND_EQ then branch if fpInactive == 0 (ie if active)
757
- */
758
- assert(cond == TCG_COND_EQ || cond == TCG_COND_NE);
759
-
760
- /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
761
- TCGv_i32 aspen, fpca;
762
- aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
763
- fpca = load_cpu_field(v7m.control[M_REG_S]);
764
- tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
765
- tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
766
- tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
767
- tcg_gen_or_i32(fpca, fpca, aspen);
768
- tcg_gen_brcondi_i32(tcg_invert_cond(cond), fpca, 0, label);
769
- tcg_temp_free_i32(aspen);
770
- tcg_temp_free_i32(fpca);
771
-}
772
-
773
-static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
774
- fp_sysreg_loadfn *loadfn,
775
- void *opaque)
776
-{
777
- /* Do a write to an M-profile floating point system register */
778
- TCGv_i32 tmp;
779
- TCGLabel *lab_end = NULL;
780
-
781
- switch (fp_sysreg_checks(s, regno)) {
782
- case FPSysRegCheckFailed:
783
- return false;
784
- case FPSysRegCheckDone:
785
- return true;
786
- case FPSysRegCheckContinue:
787
- break;
788
- }
789
-
790
- switch (regno) {
791
- case ARM_VFP_FPSCR:
792
- tmp = loadfn(s, opaque);
793
- gen_helper_vfp_set_fpscr(cpu_env, tmp);
794
- tcg_temp_free_i32(tmp);
795
- gen_lookup_tb(s);
796
- break;
797
- case ARM_VFP_FPSCR_NZCVQC:
798
- {
799
- TCGv_i32 fpscr;
800
- tmp = loadfn(s, opaque);
801
- if (dc_isar_feature(aa32_mve, s)) {
802
- /* QC is only present for MVE; otherwise RES0 */
803
- TCGv_i32 qc = tcg_temp_new_i32();
804
- tcg_gen_andi_i32(qc, tmp, FPCR_QC);
805
- /*
806
- * The 4 vfp.qc[] fields need only be "zero" vs "non-zero";
807
- * here writing the same value into all elements is simplest.
808
- */
809
- tcg_gen_gvec_dup_i32(MO_32, offsetof(CPUARMState, vfp.qc),
810
- 16, 16, qc);
811
- }
812
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
813
- fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
814
- tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
815
- tcg_gen_or_i32(fpscr, fpscr, tmp);
816
- store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
817
- tcg_temp_free_i32(tmp);
818
- break;
819
- }
820
- case ARM_VFP_FPCXT_NS:
821
- lab_end = gen_new_label();
822
- /* fpInactive case: write is a NOP, so branch to end */
823
- gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
824
- /*
825
- * !fpInactive: if FPU disabled, take NOCP exception;
826
- * otherwise PreserveFPState(), and then FPCXT_NS writes
827
- * behave the same as FPCXT_S writes.
828
- */
829
- if (s->fp_excp_el) {
830
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
831
- syn_uncategorized(), s->fp_excp_el);
832
- /*
833
- * This was only a conditional exception, so override
834
- * gen_exception_insn()'s default to DISAS_NORETURN
835
- */
836
- s->base.is_jmp = DISAS_NEXT;
837
- break;
838
- }
839
- gen_preserve_fp_state(s);
840
- /* fall through */
841
- case ARM_VFP_FPCXT_S:
842
- {
843
- TCGv_i32 sfpa, control;
844
- /*
845
- * Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
846
- * bits [27:0] from value and zeroes bits [31:28].
847
- */
848
- tmp = loadfn(s, opaque);
849
- sfpa = tcg_temp_new_i32();
850
- tcg_gen_shri_i32(sfpa, tmp, 31);
851
- control = load_cpu_field(v7m.control[M_REG_S]);
852
- tcg_gen_deposit_i32(control, control, sfpa,
853
- R_V7M_CONTROL_SFPA_SHIFT, 1);
854
- store_cpu_field(control, v7m.control[M_REG_S]);
855
- tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
856
- gen_helper_vfp_set_fpscr(cpu_env, tmp);
857
- tcg_temp_free_i32(tmp);
858
- tcg_temp_free_i32(sfpa);
859
- break;
860
- }
861
- case ARM_VFP_VPR:
862
- /* Behaves as NOP if not privileged */
863
- if (IS_USER(s)) {
864
- break;
865
- }
866
- tmp = loadfn(s, opaque);
867
- store_cpu_field(tmp, v7m.vpr);
868
- break;
869
- case ARM_VFP_P0:
870
- {
871
- TCGv_i32 vpr;
872
- tmp = loadfn(s, opaque);
873
- vpr = load_cpu_field(v7m.vpr);
874
- tcg_gen_deposit_i32(vpr, vpr, tmp,
875
- R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
876
- store_cpu_field(vpr, v7m.vpr);
877
- tcg_temp_free_i32(tmp);
878
- break;
879
- }
880
- default:
881
- g_assert_not_reached();
882
- }
883
- if (lab_end) {
884
- gen_set_label(lab_end);
885
- }
886
- return true;
887
-}
888
-
889
-static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
890
- fp_sysreg_storefn *storefn,
891
- void *opaque)
892
-{
893
- /* Do a read from an M-profile floating point system register */
894
- TCGv_i32 tmp;
895
- TCGLabel *lab_end = NULL;
896
- bool lookup_tb = false;
897
-
898
- switch (fp_sysreg_checks(s, regno)) {
899
- case FPSysRegCheckFailed:
900
- return false;
901
- case FPSysRegCheckDone:
902
- return true;
903
- case FPSysRegCheckContinue:
904
- break;
905
- }
906
-
907
- if (regno == ARM_VFP_FPSCR_NZCVQC && !dc_isar_feature(aa32_mve, s)) {
908
- /* QC is RES0 without MVE, so NZCVQC simplifies to NZCV */
909
- regno = QEMU_VFP_FPSCR_NZCV;
910
- }
911
-
912
- switch (regno) {
913
- case ARM_VFP_FPSCR:
914
- tmp = tcg_temp_new_i32();
915
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
916
- storefn(s, opaque, tmp);
917
- break;
918
- case ARM_VFP_FPSCR_NZCVQC:
919
- tmp = tcg_temp_new_i32();
920
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
921
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
922
- storefn(s, opaque, tmp);
923
- break;
924
- case QEMU_VFP_FPSCR_NZCV:
925
- /*
926
- * Read just NZCV; this is a special case to avoid the
927
- * helper call for the "VMRS to CPSR.NZCV" insn.
928
- */
929
- tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
930
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
931
- storefn(s, opaque, tmp);
932
- break;
933
- case ARM_VFP_FPCXT_S:
934
- {
935
- TCGv_i32 control, sfpa, fpscr;
936
- /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
937
- tmp = tcg_temp_new_i32();
938
- sfpa = tcg_temp_new_i32();
939
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
940
- tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
941
- control = load_cpu_field(v7m.control[M_REG_S]);
942
- tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
943
- tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
944
- tcg_gen_or_i32(tmp, tmp, sfpa);
945
- tcg_temp_free_i32(sfpa);
946
- /*
947
- * Store result before updating FPSCR etc, in case
948
- * it is a memory write which causes an exception.
949
- */
950
- storefn(s, opaque, tmp);
951
- /*
952
- * Now we must reset FPSCR from FPDSCR_NS, and clear
953
- * CONTROL.SFPA; so we'll end the TB here.
954
- */
955
- tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
956
- store_cpu_field(control, v7m.control[M_REG_S]);
957
- fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
958
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
959
- tcg_temp_free_i32(fpscr);
960
- lookup_tb = true;
961
- break;
962
- }
963
- case ARM_VFP_FPCXT_NS:
964
- {
965
- TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
966
- TCGLabel *lab_active = gen_new_label();
967
-
968
- lookup_tb = true;
969
-
970
- gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
971
- /* fpInactive case: reads as FPDSCR_NS */
972
- TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
973
- storefn(s, opaque, tmp);
974
- lab_end = gen_new_label();
975
- tcg_gen_br(lab_end);
976
-
977
- gen_set_label(lab_active);
978
- /*
979
- * !fpInactive: if FPU disabled, take NOCP exception;
980
- * otherwise PreserveFPState(), and then FPCXT_NS
981
- * reads the same as FPCXT_S.
982
- */
983
- if (s->fp_excp_el) {
984
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
985
- syn_uncategorized(), s->fp_excp_el);
986
- /*
987
- * This was only a conditional exception, so override
988
- * gen_exception_insn()'s default to DISAS_NORETURN
989
- */
990
- s->base.is_jmp = DISAS_NEXT;
991
- break;
992
- }
993
- gen_preserve_fp_state(s);
994
- tmp = tcg_temp_new_i32();
995
- sfpa = tcg_temp_new_i32();
996
- fpscr = tcg_temp_new_i32();
997
- gen_helper_vfp_get_fpscr(fpscr, cpu_env);
998
- tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK);
999
- control = load_cpu_field(v7m.control[M_REG_S]);
1000
- tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
1001
- tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
1002
- tcg_gen_or_i32(tmp, tmp, sfpa);
1003
- tcg_temp_free_i32(control);
1004
- /* Store result before updating FPSCR, in case it faults */
1005
- storefn(s, opaque, tmp);
1006
- /* If SFPA is zero then set FPSCR from FPDSCR_NS */
1007
- fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
1008
- zero = tcg_const_i32(0);
1009
- tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
1010
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
1011
- tcg_temp_free_i32(zero);
1012
- tcg_temp_free_i32(sfpa);
1013
- tcg_temp_free_i32(fpdscr);
1014
- tcg_temp_free_i32(fpscr);
1015
- break;
1016
- }
1017
- case ARM_VFP_VPR:
1018
- /* Behaves as NOP if not privileged */
1019
- if (IS_USER(s)) {
1020
- break;
1021
- }
1022
- tmp = load_cpu_field(v7m.vpr);
1023
- storefn(s, opaque, tmp);
1024
- break;
1025
- case ARM_VFP_P0:
1026
- tmp = load_cpu_field(v7m.vpr);
1027
- tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
1028
- storefn(s, opaque, tmp);
1029
- break;
1030
- default:
1031
- g_assert_not_reached();
1032
- }
1033
-
1034
- if (lab_end) {
1035
- gen_set_label(lab_end);
1036
- }
1037
- if (lookup_tb) {
1038
- gen_lookup_tb(s);
1039
- }
1040
- return true;
1041
-}
1042
-
1043
-static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
1044
-{
1045
- arg_VMSR_VMRS *a = opaque;
1046
-
1047
- if (a->rt == 15) {
1048
- /* Set the 4 flag bits in the CPSR */
1049
- gen_set_nzcv(value);
1050
- tcg_temp_free_i32(value);
1051
- } else {
1052
- store_reg(s, a->rt, value);
1053
- }
1054
-}
1055
-
1056
-static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
1057
-{
1058
- arg_VMSR_VMRS *a = opaque;
1059
-
1060
- return load_reg(s, a->rt);
1061
-}
1062
-
1063
-static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1064
-{
1065
- /*
1066
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
1067
- * FPSCR -> r15 is a special case which writes to the PSR flags;
1068
- * set a->reg to a special value to tell gen_M_fp_sysreg_read()
1069
- * we only care about the top 4 bits of FPSCR there.
1070
- */
1071
- if (a->rt == 15) {
1072
- if (a->l && a->reg == ARM_VFP_FPSCR) {
1073
- a->reg = QEMU_VFP_FPSCR_NZCV;
1074
- } else {
1075
- return false;
1076
- }
1077
- }
1078
-
1079
- if (a->l) {
1080
- /* VMRS, move FP system register to gp register */
1081
- return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
1082
- } else {
1083
- /* VMSR, move gp register to FP system register */
1084
- return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
1085
- }
1086
-}
1087
-
1088
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1089
{
1090
TCGv_i32 tmp;
1091
bool ignore_vfp_enabled = false;
1092
1093
if (arm_dc_feature(s, ARM_FEATURE_M)) {
1094
- return gen_M_VMSR_VMRS(s, a);
1095
+ /* M profile version was already handled in m-nocp.decode */
1096
+ return false;
1097
}
1098
1099
if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1100
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1101
return true;
1102
}
1103
1104
-static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
1105
-{
1106
- arg_vldr_sysreg *a = opaque;
1107
- uint32_t offset = a->imm;
1108
- TCGv_i32 addr;
1109
-
1110
- if (!a->a) {
1111
- offset = -offset;
1112
- }
1113
-
1114
- addr = load_reg(s, a->rn);
1115
- if (a->p) {
1116
- tcg_gen_addi_i32(addr, addr, offset);
1117
- }
1118
-
1119
- if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1120
- gen_helper_v8m_stackcheck(cpu_env, addr);
1121
- }
1122
-
1123
- gen_aa32_st_i32(s, value, addr, get_mem_index(s),
1124
- MO_UL | MO_ALIGN | s->be_data);
1125
- tcg_temp_free_i32(value);
1126
-
1127
- if (a->w) {
1128
- /* writeback */
1129
- if (!a->p) {
1130
- tcg_gen_addi_i32(addr, addr, offset);
1131
- }
1132
- store_reg(s, a->rn, addr);
1133
- } else {
1134
- tcg_temp_free_i32(addr);
1135
- }
1136
-}
1137
-
1138
-static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
1139
-{
1140
- arg_vldr_sysreg *a = opaque;
1141
- uint32_t offset = a->imm;
1142
- TCGv_i32 addr;
1143
- TCGv_i32 value = tcg_temp_new_i32();
1144
-
1145
- if (!a->a) {
1146
- offset = -offset;
1147
- }
1148
-
1149
- addr = load_reg(s, a->rn);
1150
- if (a->p) {
1151
- tcg_gen_addi_i32(addr, addr, offset);
1152
- }
1153
-
1154
- if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1155
- gen_helper_v8m_stackcheck(cpu_env, addr);
1156
- }
1157
-
1158
- gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
1159
- MO_UL | MO_ALIGN | s->be_data);
1160
-
1161
- if (a->w) {
1162
- /* writeback */
1163
- if (!a->p) {
1164
- tcg_gen_addi_i32(addr, addr, offset);
1165
- }
1166
- store_reg(s, a->rn, addr);
1167
- } else {
1168
- tcg_temp_free_i32(addr);
1169
- }
1170
- return value;
1171
-}
1172
-
1173
-static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1174
-{
1175
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
1176
- return false;
1177
- }
1178
- if (a->rn == 15) {
1179
- return false;
1180
- }
1181
- return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
1182
-}
1183
-
1184
-static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1185
-{
1186
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
1187
- return false;
1188
- }
1189
- if (a->rn == 15) {
1190
- return false;
1191
- }
1192
- return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
1193
-}
1194
1195
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
1196
{
1167
--
1197
--
1168
2.20.1
1198
2.20.1
1169
1199
1170
1200
diff view generated by jsdifflib
New patch
1
1
A few subcases of VLDR/VSTR sysreg succeed but do not perform a
2
memory access:
3
* VSTR of VPR when unprivileged
4
* VLDR to VPR when unprivileged
5
* VLDR to FPCXT_NS when fpInactive
6
7
In these cases, even though we don't do the memory access we should
8
still update the base register and perform the stack limit check if
9
the insn's addressing mode specifies writeback. Our implementation
10
failed to do this, because we handle these side-effects inside the
11
memory_to_fp_sysreg() and fp_sysreg_to_memory() callback functions,
12
which are only called if there's something to load or store.
13
14
Fix this by adding an extra argument to the callbacks which is set to
15
true to actually perform the access and false to only do side effects
16
like writeback, and calling the callback with do_access = false
17
for the three cases listed above.
18
19
This produces slightly suboptimal code for the case of a write
20
to FPCXT_NS when the FPU is inactive and the insn didn't have
21
side effects (ie no writeback, or via VMSR), in which case we'll
22
generate a conditional branch over an unconditional branch.
23
But this doesn't seem to be important enough to merit requiring
24
the callback to report back whether it generated any code or not.
25
26
Cc: qemu-stable@nongnu.org
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20210618141019.10671-5-peter.maydell@linaro.org
30
---
31
target/arm/translate-m-nocp.c | 102 ++++++++++++++++++++++++----------
32
1 file changed, 72 insertions(+), 30 deletions(-)
33
34
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-m-nocp.c
37
+++ b/target/arm/translate-m-nocp.c
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
39
40
/*
41
* Emit code to store the sysreg to its final destination; frees the
42
- * TCG temp 'value' it is passed.
43
+ * TCG temp 'value' it is passed. do_access is true to do the store,
44
+ * and false to skip it and only perform side-effects like base
45
+ * register writeback.
46
*/
47
-typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
48
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value,
49
+ bool do_access);
50
/*
51
* Emit code to load the value to be copied to the sysreg; returns
52
- * a new TCG temporary
53
+ * a new TCG temporary. do_access is true to do the store,
54
+ * and false to skip it and only perform side-effects like base
55
+ * register writeback.
56
*/
57
-typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
58
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque,
59
+ bool do_access);
60
61
/* Common decode/access checks for fp sysreg read/write */
62
typedef enum FPSysRegCheckResult {
63
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
64
65
switch (regno) {
66
case ARM_VFP_FPSCR:
67
- tmp = loadfn(s, opaque);
68
+ tmp = loadfn(s, opaque, true);
69
gen_helper_vfp_set_fpscr(cpu_env, tmp);
70
tcg_temp_free_i32(tmp);
71
gen_lookup_tb(s);
72
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
73
case ARM_VFP_FPSCR_NZCVQC:
74
{
75
TCGv_i32 fpscr;
76
- tmp = loadfn(s, opaque);
77
+ tmp = loadfn(s, opaque, true);
78
if (dc_isar_feature(aa32_mve, s)) {
79
/* QC is only present for MVE; otherwise RES0 */
80
TCGv_i32 qc = tcg_temp_new_i32();
81
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
82
break;
83
}
84
case ARM_VFP_FPCXT_NS:
85
+ {
86
+ TCGLabel *lab_active = gen_new_label();
87
+
88
lab_end = gen_new_label();
89
- /* fpInactive case: write is a NOP, so branch to end */
90
- gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
91
+ gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
92
+ /*
93
+ * fpInactive case: write is a NOP, so only do side effects
94
+ * like register writeback before we branch to end
95
+ */
96
+ loadfn(s, opaque, false);
97
+ tcg_gen_br(lab_end);
98
+
99
+ gen_set_label(lab_active);
100
/*
101
* !fpInactive: if FPU disabled, take NOCP exception;
102
* otherwise PreserveFPState(), and then FPCXT_NS writes
103
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
104
break;
105
}
106
gen_preserve_fp_state(s);
107
- /* fall through */
108
+ }
109
+ /* fall through */
110
case ARM_VFP_FPCXT_S:
111
{
112
TCGv_i32 sfpa, control;
113
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
114
* Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
115
* bits [27:0] from value and zeroes bits [31:28].
116
*/
117
- tmp = loadfn(s, opaque);
118
+ tmp = loadfn(s, opaque, true);
119
sfpa = tcg_temp_new_i32();
120
tcg_gen_shri_i32(sfpa, tmp, 31);
121
control = load_cpu_field(v7m.control[M_REG_S]);
122
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
123
case ARM_VFP_VPR:
124
/* Behaves as NOP if not privileged */
125
if (IS_USER(s)) {
126
+ loadfn(s, opaque, false);
127
break;
128
}
129
- tmp = loadfn(s, opaque);
130
+ tmp = loadfn(s, opaque, true);
131
store_cpu_field(tmp, v7m.vpr);
132
break;
133
case ARM_VFP_P0:
134
{
135
TCGv_i32 vpr;
136
- tmp = loadfn(s, opaque);
137
+ tmp = loadfn(s, opaque, true);
138
vpr = load_cpu_field(v7m.vpr);
139
tcg_gen_deposit_i32(vpr, vpr, tmp,
140
R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
141
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
142
case ARM_VFP_FPSCR:
143
tmp = tcg_temp_new_i32();
144
gen_helper_vfp_get_fpscr(tmp, cpu_env);
145
- storefn(s, opaque, tmp);
146
+ storefn(s, opaque, tmp, true);
147
break;
148
case ARM_VFP_FPSCR_NZCVQC:
149
tmp = tcg_temp_new_i32();
150
gen_helper_vfp_get_fpscr(tmp, cpu_env);
151
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
152
- storefn(s, opaque, tmp);
153
+ storefn(s, opaque, tmp, true);
154
break;
155
case QEMU_VFP_FPSCR_NZCV:
156
/*
157
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
158
*/
159
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
160
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
161
- storefn(s, opaque, tmp);
162
+ storefn(s, opaque, tmp, true);
163
break;
164
case ARM_VFP_FPCXT_S:
165
{
166
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
167
* Store result before updating FPSCR etc, in case
168
* it is a memory write which causes an exception.
169
*/
170
- storefn(s, opaque, tmp);
171
+ storefn(s, opaque, tmp, true);
172
/*
173
* Now we must reset FPSCR from FPDSCR_NS, and clear
174
* CONTROL.SFPA; so we'll end the TB here.
175
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
176
gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
177
/* fpInactive case: reads as FPDSCR_NS */
178
TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
179
- storefn(s, opaque, tmp);
180
+ storefn(s, opaque, tmp, true);
181
lab_end = gen_new_label();
182
tcg_gen_br(lab_end);
183
184
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
185
tcg_gen_or_i32(tmp, tmp, sfpa);
186
tcg_temp_free_i32(control);
187
/* Store result before updating FPSCR, in case it faults */
188
- storefn(s, opaque, tmp);
189
+ storefn(s, opaque, tmp, true);
190
/* If SFPA is zero then set FPSCR from FPDSCR_NS */
191
fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
192
zero = tcg_const_i32(0);
193
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
194
case ARM_VFP_VPR:
195
/* Behaves as NOP if not privileged */
196
if (IS_USER(s)) {
197
+ storefn(s, opaque, NULL, false);
198
break;
199
}
200
tmp = load_cpu_field(v7m.vpr);
201
- storefn(s, opaque, tmp);
202
+ storefn(s, opaque, tmp, true);
203
break;
204
case ARM_VFP_P0:
205
tmp = load_cpu_field(v7m.vpr);
206
tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
207
- storefn(s, opaque, tmp);
208
+ storefn(s, opaque, tmp, true);
209
break;
210
default:
211
g_assert_not_reached();
212
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
213
return true;
214
}
215
216
-static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
217
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value,
218
+ bool do_access)
219
{
220
arg_VMSR_VMRS *a = opaque;
221
222
+ if (!do_access) {
223
+ return;
224
+ }
225
+
226
if (a->rt == 15) {
227
/* Set the 4 flag bits in the CPSR */
228
gen_set_nzcv(value);
229
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
230
}
231
}
232
233
-static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
234
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque, bool do_access)
235
{
236
arg_VMSR_VMRS *a = opaque;
237
238
+ if (!do_access) {
239
+ return NULL;
240
+ }
241
return load_reg(s, a->rt);
242
}
243
244
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
245
}
246
}
247
248
-static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
249
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value,
250
+ bool do_access)
251
{
252
arg_vldr_sysreg *a = opaque;
253
uint32_t offset = a->imm;
254
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
255
offset = -offset;
256
}
257
258
+ if (!do_access && !a->w) {
259
+ return;
260
+ }
261
+
262
addr = load_reg(s, a->rn);
263
if (a->p) {
264
tcg_gen_addi_i32(addr, addr, offset);
265
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
266
gen_helper_v8m_stackcheck(cpu_env, addr);
267
}
268
269
- gen_aa32_st_i32(s, value, addr, get_mem_index(s),
270
- MO_UL | MO_ALIGN | s->be_data);
271
- tcg_temp_free_i32(value);
272
+ if (do_access) {
273
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
274
+ MO_UL | MO_ALIGN | s->be_data);
275
+ tcg_temp_free_i32(value);
276
+ }
277
278
if (a->w) {
279
/* writeback */
280
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
281
}
282
}
283
284
-static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
285
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque,
286
+ bool do_access)
287
{
288
arg_vldr_sysreg *a = opaque;
289
uint32_t offset = a->imm;
290
TCGv_i32 addr;
291
- TCGv_i32 value = tcg_temp_new_i32();
292
+ TCGv_i32 value = NULL;
293
294
if (!a->a) {
295
offset = -offset;
296
}
297
298
+ if (!do_access && !a->w) {
299
+ return NULL;
300
+ }
301
+
302
addr = load_reg(s, a->rn);
303
if (a->p) {
304
tcg_gen_addi_i32(addr, addr, offset);
305
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
306
gen_helper_v8m_stackcheck(cpu_env, addr);
307
}
308
309
- gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
310
- MO_UL | MO_ALIGN | s->be_data);
311
+ if (do_access) {
312
+ value = tcg_temp_new_i32();
313
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
314
+ MO_UL | MO_ALIGN | s->be_data);
315
+ }
316
317
if (a->w) {
318
/* writeback */
319
--
320
2.20.1
321
322
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Factor the code in full_vfp_access_check() which updates the
2
ownership of the FP context and creates a new FP context
3
out into its own function.
2
4
3
Let's move the code which freezes which gic-version to
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
be applied in a dedicated function. We also now set by
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
default the VIRT_GIC_VERSION_NO_SET. This eventually
7
Message-id: 20210618141019.10671-6-peter.maydell@linaro.org
6
turns into the legacy v2 choice in the finalize() function.
8
---
9
target/arm/translate-vfp.c | 104 +++++++++++++++++++++----------------
10
1 file changed, 58 insertions(+), 46 deletions(-)
7
11
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
12
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Andrew Jones <drjones@redhat.com>
11
Message-id: 20200311131618.7187-4-eric.auger@redhat.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
include/hw/arm/virt.h | 1 +
15
hw/arm/virt.c | 54 ++++++++++++++++++++++++++-----------------
16
2 files changed, 34 insertions(+), 21 deletions(-)
17
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/virt.h
14
--- a/target/arm/translate-vfp.c
21
+++ b/include/hw/arm/virt.h
15
+++ b/target/arm/translate-vfp.c
22
@@ -XXX,XX +XXX,XX @@ typedef enum VirtGICType {
16
@@ -XXX,XX +XXX,XX @@ void gen_preserve_fp_state(DisasContext *s)
23
VIRT_GIC_VERSION_HOST,
24
VIRT_GIC_VERSION_2,
25
VIRT_GIC_VERSION_3,
26
+ VIRT_GIC_VERSION_NOSEL,
27
} VirtGICType;
28
29
typedef struct MemMapEntry {
30
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/virt.c
33
+++ b/hw/arm/virt.c
34
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
35
}
17
}
36
}
18
}
37
19
38
+/*
20
+/*
39
+ * finalize_gic_version - Determines the final gic_version
21
+ * Generate code for M-profile FP context handling: update the
40
+ * according to the gic-version property
22
+ * ownership of the FP context, and create a new context if
41
+ *
23
+ * necessary. This corresponds to the parts of the pseudocode
42
+ * Default GIC type is v2
24
+ * ExecuteFPCheck() after the inital PreserveFPState() call.
43
+ */
25
+ */
44
+static void finalize_gic_version(VirtMachineState *vms)
26
+static void gen_update_fp_context(DisasContext *s)
45
+{
27
+{
46
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
28
+ /* Update ownership of FP context: set FPCCR.S to match current state */
47
+ vms->gic_version == VIRT_GIC_VERSION_MAX) {
29
+ if (s->v8m_fpccr_s_wrong) {
48
+ if (!kvm_enabled()) {
30
+ TCGv_i32 tmp;
49
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
31
+
50
+ error_report("gic-version=host requires KVM");
32
+ tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
51
+ exit(1);
33
+ if (s->v8m_secure) {
52
+ } else {
34
+ tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
53
+ /* "max": currently means 3 for TCG */
54
+ vms->gic_version = VIRT_GIC_VERSION_3;
55
+ }
56
+ } else {
35
+ } else {
57
+ vms->gic_version = kvm_arm_vgic_probe();
36
+ tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
58
+ if (!vms->gic_version) {
59
+ error_report(
60
+ "Unable to determine GIC version supported by host");
61
+ exit(1);
62
+ }
63
+ }
37
+ }
64
+ } else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
38
+ store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
65
+ vms->gic_version = VIRT_GIC_VERSION_2;
39
+ /* Don't need to do this for any further FP insns in this TB */
40
+ s->v8m_fpccr_s_wrong = false;
41
+ }
42
+
43
+ if (s->v7m_new_fp_ctxt_needed) {
44
+ /*
45
+ * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA,
46
+ * the FPSCR, and VPR.
47
+ */
48
+ TCGv_i32 control, fpscr;
49
+ uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
50
+
51
+ fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
52
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
53
+ tcg_temp_free_i32(fpscr);
54
+ if (dc_isar_feature(aa32_mve, s)) {
55
+ TCGv_i32 z32 = tcg_const_i32(0);
56
+ store_cpu_field(z32, v7m.vpr);
57
+ }
58
+
59
+ /*
60
+ * We don't need to arrange to end the TB, because the only
61
+ * parts of FPSCR which we cache in the TB flags are the VECLEN
62
+ * and VECSTRIDE, and those don't exist for M-profile.
63
+ */
64
+
65
+ if (s->v8m_secure) {
66
+ bits |= R_V7M_CONTROL_SFPA_MASK;
67
+ }
68
+ control = load_cpu_field(v7m.control[M_REG_S]);
69
+ tcg_gen_ori_i32(control, control, bits);
70
+ store_cpu_field(control, v7m.control[M_REG_S]);
71
+ /* Don't need to do this for any further FP insns in this TB */
72
+ s->v7m_new_fp_ctxt_needed = false;
66
+ }
73
+ }
67
+}
74
+}
68
+
75
+
69
static void machvirt_init(MachineState *machine)
76
/*
70
{
77
* Check that VFP access is enabled. If it is, do the necessary
71
VirtMachineState *vms = VIRT_MACHINE(machine);
78
* M-profile lazy-FP handling and then return true.
72
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
79
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
73
/* We can probe only here because during property set
80
/* Trigger lazy-state preservation if necessary */
74
* KVM is not available yet
81
gen_preserve_fp_state(s);
75
*/
82
76
- if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
83
- /* Update ownership of FP context: set FPCCR.S to match current state */
77
- vms->gic_version == VIRT_GIC_VERSION_MAX) {
84
- if (s->v8m_fpccr_s_wrong) {
78
- if (!kvm_enabled()) {
85
- TCGv_i32 tmp;
79
- if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
86
-
80
- error_report("gic-version=host requires KVM");
87
- tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
81
- exit(1);
88
- if (s->v8m_secure) {
89
- tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
82
- } else {
90
- } else {
83
- /* "max": currently means 3 for TCG */
91
- tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
84
- vms->gic_version = VIRT_GIC_VERSION_3;
85
- }
92
- }
86
- } else {
93
- store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
87
- vms->gic_version = kvm_arm_vgic_probe();
94
- /* Don't need to do this for any further FP insns in this TB */
88
- if (!vms->gic_version) {
95
- s->v8m_fpccr_s_wrong = false;
89
- error_report(
96
- }
90
- "Unable to determine GIC version supported by host");
97
-
91
- exit(1);
98
- if (s->v7m_new_fp_ctxt_needed) {
99
- /*
100
- * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA,
101
- * the FPSCR, and VPR.
102
- */
103
- TCGv_i32 control, fpscr;
104
- uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
105
-
106
- fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
107
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
108
- tcg_temp_free_i32(fpscr);
109
- if (dc_isar_feature(aa32_mve, s)) {
110
- TCGv_i32 z32 = tcg_const_i32(0);
111
- store_cpu_field(z32, v7m.vpr);
92
- }
112
- }
113
-
114
- /*
115
- * We don't need to arrange to end the TB, because the only
116
- * parts of FPSCR which we cache in the TB flags are the VECLEN
117
- * and VECSTRIDE, and those don't exist for M-profile.
118
- */
119
-
120
- if (s->v8m_secure) {
121
- bits |= R_V7M_CONTROL_SFPA_MASK;
122
- }
123
- control = load_cpu_field(v7m.control[M_REG_S]);
124
- tcg_gen_ori_i32(control, control, bits);
125
- store_cpu_field(control, v7m.control[M_REG_S]);
126
- /* Don't need to do this for any further FP insns in this TB */
127
- s->v7m_new_fp_ctxt_needed = false;
93
- }
128
- }
94
- }
129
+ /* Update ownership of FP context and create new FP context if needed */
95
+ finalize_gic_version(vms);
130
+ gen_update_fp_context(s);
96
131
}
97
if (!cpu_type_valid(machine->cpu_type)) {
132
98
error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
133
return true;
99
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
100
"Set on/off to enable/disable using "
101
"physical address space above 32 bits",
102
NULL);
103
- /* Default GIC type is v2 */
104
- vms->gic_version = VIRT_GIC_VERSION_2;
105
+ vms->gic_version = VIRT_GIC_VERSION_NOSEL;
106
object_property_add_str(obj, "gic-version", virt_get_gic_version,
107
virt_set_gic_version, NULL);
108
object_property_set_description(obj, "gic-version",
109
--
134
--
110
2.20.1
135
2.20.1
111
136
112
137
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
vfp_access_check and its helper routine full_vfp_access_check() has
2
gradually grown and is now an awkward mix of A-profile only and
3
M-profile only pieces. Refactor it into an A-profile only and an
4
M-profile only version, taking advantage of the fact that now the
5
only direct call to full_vfp_access_check() is in A-profile-only
6
code.
2
7
3
Wire up eSDHC controllers in fsl-imx25. For imx25-pdk, connect drives
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
provided on the command line to available eSDHC controllers.
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210618141019.10671-7-peter.maydell@linaro.org
11
---
12
target/arm/translate-vfp.c | 79 +++++++++++++++++++++++---------------
13
1 file changed, 48 insertions(+), 31 deletions(-)
5
14
6
This patch enables booting the imx25-pdk emulation from SD card.
15
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
7
8
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
9
Message-id: 20200310215146.19688-2-linux@roeck-us.net
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: made commit subject consistent with other patch]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
include/hw/arm/fsl-imx25.h | 9 +++++++++
15
hw/arm/fsl-imx25.c | 32 ++++++++++++++++++++++++++++++++
16
hw/arm/imx25_pdk.c | 16 ++++++++++++++++
17
3 files changed, 57 insertions(+)
18
19
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/arm/fsl-imx25.h
17
--- a/target/arm/translate-vfp.c
22
+++ b/include/hw/arm/fsl-imx25.h
18
+++ b/target/arm/translate-vfp.c
23
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void gen_update_fp_context(DisasContext *s)
24
#include "hw/misc/imx_rngc.h"
20
}
25
#include "hw/i2c/imx_i2c.h"
21
26
#include "hw/gpio/imx_gpio.h"
22
/*
27
+#include "hw/sd/sdhci.h"
23
- * Check that VFP access is enabled. If it is, do the necessary
28
#include "exec/memory.h"
24
- * M-profile lazy-FP handling and then return true.
29
#include "target/arm/cpu.h"
25
- * If not, emit code to generate an appropriate exception and
30
26
- * return false.
31
@@ -XXX,XX +XXX,XX @@
27
+ * Check that VFP access is enabled, A-profile specific version.
32
#define FSL_IMX25_NUM_EPITS 2
28
+ *
33
#define FSL_IMX25_NUM_I2CS 3
29
+ * If VFP is enabled, return true. If not, emit code to generate an
34
#define FSL_IMX25_NUM_GPIOS 4
30
+ * appropriate exception and return false.
35
+#define FSL_IMX25_NUM_ESDHCS 2
31
* The ignore_vfp_enabled argument specifies that we should ignore
36
32
- * whether VFP is enabled via FPEXC[EN]: this should be true for FMXR/FMRX
37
typedef struct FslIMX25State {
33
+ * whether VFP is enabled via FPEXC.EN: this should be true for FMXR/FMRX
38
/*< private >*/
34
* accesses to FPSID, FPEXC, MVFR0, MVFR1, MVFR2, and false for all other insns.
39
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
35
*/
40
IMXRNGCState rngc;
36
-static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
41
IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
37
+static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
42
IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
38
{
43
+ SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
39
if (s->fp_excp_el) {
44
MemoryRegion rom[2];
40
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
45
MemoryRegion iram;
41
- /*
46
MemoryRegion iram_alias;
42
- * M-profile mostly catches the "FPU disabled" case early, in
47
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
43
- * disas_m_nocp(), but a few insns (eg LCTP, WLSTP, DLSTP)
48
#define FSL_IMX25_GPIO3_SIZE 0x4000
44
- * which do coprocessor-checks are outside the large ranges of
49
#define FSL_IMX25_RNGC_ADDR 0x53FB0000
45
- * the encoding space handled by the patterns in m-nocp.decode,
50
#define FSL_IMX25_RNGC_SIZE 0x4000
46
- * and for them we may need to raise NOCP here.
51
+#define FSL_IMX25_ESDHC1_ADDR 0x53FB4000
47
- */
52
+#define FSL_IMX25_ESDHC1_SIZE 0x4000
48
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
53
+#define FSL_IMX25_ESDHC2_ADDR 0x53FB8000
49
- syn_uncategorized(), s->fp_excp_el);
54
+#define FSL_IMX25_ESDHC2_SIZE 0x4000
50
- } else {
55
#define FSL_IMX25_GPIO1_ADDR 0x53FCC000
51
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
56
#define FSL_IMX25_GPIO1_SIZE 0x4000
52
- syn_fp_access_trap(1, 0xe, false),
57
#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
53
- s->fp_excp_el);
58
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
54
- }
59
#define FSL_IMX25_GPIO2_IRQ 51
55
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
60
#define FSL_IMX25_GPIO3_IRQ 16
56
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
61
#define FSL_IMX25_GPIO4_IRQ 23
57
return false;
62
+#define FSL_IMX25_ESDHC1_IRQ 9
58
}
63
+#define FSL_IMX25_ESDHC2_IRQ 8
59
64
60
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
65
#endif /* FSL_IMX25_H */
61
unallocated_encoding(s);
66
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
62
return false;
67
index XXXXXXX..XXXXXXX 100644
63
}
68
--- a/hw/arm/fsl-imx25.c
64
+ return true;
69
+++ b/hw/arm/fsl-imx25.c
65
+}
70
@@ -XXX,XX +XXX,XX @@
66
71
#include "hw/qdev-properties.h"
67
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
72
#include "chardev/char.h"
68
- /* Handle M-profile lazy FP state mechanics */
73
69
-
74
+#define IMX25_ESDHC_CAPABILITIES 0x07e20000
70
- /* Trigger lazy-state preservation if necessary */
71
- gen_preserve_fp_state(s);
72
-
73
- /* Update ownership of FP context and create new FP context if needed */
74
- gen_update_fp_context(s);
75
+/*
76
+ * Check that VFP access is enabled, M-profile specific version.
77
+ *
78
+ * If VFP is enabled, do the necessary M-profile lazy-FP handling and then
79
+ * return true. If not, emit code to generate an appropriate exception and
80
+ * return false.
81
+ */
82
+static bool vfp_access_check_m(DisasContext *s)
83
+{
84
+ if (s->fp_excp_el) {
85
+ /*
86
+ * M-profile mostly catches the "FPU disabled" case early, in
87
+ * disas_m_nocp(), but a few insns (eg LCTP, WLSTP, DLSTP)
88
+ * which do coprocessor-checks are outside the large ranges of
89
+ * the encoding space handled by the patterns in m-nocp.decode,
90
+ * and for them we may need to raise NOCP here.
91
+ */
92
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
93
+ syn_uncategorized(), s->fp_excp_el);
94
+ return false;
95
}
96
97
+ /* Handle M-profile lazy FP state mechanics */
75
+
98
+
76
static void fsl_imx25_init(Object *obj)
99
+ /* Trigger lazy-state preservation if necessary */
100
+ gen_preserve_fp_state(s);
101
+
102
+ /* Update ownership of FP context and create new FP context if needed */
103
+ gen_update_fp_context(s);
104
+
105
return true;
106
}
107
108
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
109
*/
110
bool vfp_access_check(DisasContext *s)
77
{
111
{
78
FslIMX25State *s = FSL_IMX25(obj);
112
- return full_vfp_access_check(s, false);
79
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_init(Object *obj)
113
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
80
sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]),
114
+ return vfp_access_check_m(s);
81
TYPE_IMX_GPIO);
115
+ } else {
82
}
116
+ return vfp_access_check_a(s, false);
83
+
84
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
85
+ sysbus_init_child_obj(obj, "sdhc[*]", &s->esdhc[i], sizeof(s->esdhc[i]),
86
+ TYPE_IMX_USDHC);
87
+ }
117
+ }
88
}
118
}
89
119
90
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
120
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
91
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
121
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
92
gpio_table[i].irq));
122
return false;
93
}
123
}
94
124
95
+ /* Initialize all SDHC */
125
- if (!full_vfp_access_check(s, ignore_vfp_enabled)) {
96
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
126
+ /*
97
+ static const struct {
127
+ * Call vfp_access_check_a() directly, because we need to tell
98
+ hwaddr addr;
128
+ * it to ignore FPEXC.EN for some register accesses.
99
+ unsigned int irq;
129
+ */
100
+ } esdhc_table[FSL_IMX25_NUM_ESDHCS] = {
130
+ if (!vfp_access_check_a(s, ignore_vfp_enabled)) {
101
+ { FSL_IMX25_ESDHC1_ADDR, FSL_IMX25_ESDHC1_IRQ },
131
return true;
102
+ { FSL_IMX25_ESDHC2_ADDR, FSL_IMX25_ESDHC2_IRQ },
132
}
103
+ };
133
104
+
105
+ object_property_set_uint(OBJECT(&s->esdhc[i]), 2, "sd-spec-version",
106
+ &err);
107
+ object_property_set_uint(OBJECT(&s->esdhc[i]), IMX25_ESDHC_CAPABILITIES,
108
+ "capareg", &err);
109
+ object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
110
+ if (err) {
111
+ error_propagate(errp, err);
112
+ return;
113
+ }
114
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr);
115
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->esdhc[i]), 0,
116
+ qdev_get_gpio_in(DEVICE(&s->avic),
117
+ esdhc_table[i].irq));
118
+ }
119
+
120
/* initialize 2 x 16 KB ROM */
121
memory_region_init_rom(&s->rom[0], NULL,
122
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
123
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
124
index XXXXXXX..XXXXXXX 100644
125
--- a/hw/arm/imx25_pdk.c
126
+++ b/hw/arm/imx25_pdk.c
127
@@ -XXX,XX +XXX,XX @@
128
#include "qemu/osdep.h"
129
#include "qapi/error.h"
130
#include "cpu.h"
131
+#include "hw/qdev-properties.h"
132
#include "hw/arm/fsl-imx25.h"
133
#include "hw/boards.h"
134
#include "qemu/error-report.h"
135
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_init(MachineState *machine)
136
imx25_pdk_binfo.board_id = 1771,
137
imx25_pdk_binfo.nb_cpus = 1;
138
139
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
140
+ BusState *bus;
141
+ DeviceState *carddev;
142
+ DriveInfo *di;
143
+ BlockBackend *blk;
144
+
145
+ di = drive_get_next(IF_SD);
146
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
147
+ bus = qdev_get_child_bus(DEVICE(&s->soc.esdhc[i]), "sd-bus");
148
+ carddev = qdev_create(bus, TYPE_SD_CARD);
149
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
150
+ object_property_set_bool(OBJECT(carddev), true,
151
+ "realized", &error_fatal);
152
+ }
153
+
154
/*
155
* We test explicitly for qtest here as it is not done (yet?) in
156
* arm_load_kernel(). Without this the "make check" command would
157
--
134
--
158
2.20.1
135
2.20.1
159
136
160
137
diff view generated by jsdifflib
New patch
1
Instead of open-coding the "take NOCP exception if FPU disabled,
2
otherwise call gen_preserve_fp_state()" code in the accessors for
3
FPCXT_NS, add an argument to vfp_access_check_m() which tells it to
4
skip the gen_update_fp_context() call, so we can use it for the
5
FPCXT_NS case.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210618141019.10671-8-peter.maydell@linaro.org
10
---
11
target/arm/translate-a32.h | 2 +-
12
target/arm/translate-m-nocp.c | 10 ++--------
13
target/arm/translate-vfp.c | 13 ++++++++-----
14
3 files changed, 11 insertions(+), 14 deletions(-)
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 @@ bool disas_neon_shared(DisasContext *s, uint32_t insn);
21
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
22
void arm_gen_condlabel(DisasContext *s);
23
bool vfp_access_check(DisasContext *s);
24
-void gen_preserve_fp_state(DisasContext *s);
25
+bool vfp_access_check_m(DisasContext *s, bool skip_context_update);
26
void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
27
void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
28
void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
29
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-m-nocp.c
32
+++ b/target/arm/translate-m-nocp.c
33
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
34
* otherwise PreserveFPState(), and then FPCXT_NS writes
35
* behave the same as FPCXT_S writes.
36
*/
37
- if (s->fp_excp_el) {
38
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
39
- syn_uncategorized(), s->fp_excp_el);
40
+ if (!vfp_access_check_m(s, true)) {
41
/*
42
* This was only a conditional exception, so override
43
* gen_exception_insn()'s default to DISAS_NORETURN
44
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
45
s->base.is_jmp = DISAS_NEXT;
46
break;
47
}
48
- gen_preserve_fp_state(s);
49
}
50
/* fall through */
51
case ARM_VFP_FPCXT_S:
52
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
53
* otherwise PreserveFPState(), and then FPCXT_NS
54
* reads the same as FPCXT_S.
55
*/
56
- if (s->fp_excp_el) {
57
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
58
- syn_uncategorized(), s->fp_excp_el);
59
+ if (!vfp_access_check_m(s, true)) {
60
/*
61
* This was only a conditional exception, so override
62
* gen_exception_insn()'s default to DISAS_NORETURN
63
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
64
s->base.is_jmp = DISAS_NEXT;
65
break;
66
}
67
- gen_preserve_fp_state(s);
68
tmp = tcg_temp_new_i32();
69
sfpa = tcg_temp_new_i32();
70
fpscr = tcg_temp_new_i32();
71
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/translate-vfp.c
74
+++ b/target/arm/translate-vfp.c
75
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
76
* Generate code for M-profile lazy FP state preservation if needed;
77
* this corresponds to the pseudocode PreserveFPState() function.
78
*/
79
-void gen_preserve_fp_state(DisasContext *s)
80
+static void gen_preserve_fp_state(DisasContext *s)
81
{
82
if (s->v7m_lspact) {
83
/*
84
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
85
* If VFP is enabled, do the necessary M-profile lazy-FP handling and then
86
* return true. If not, emit code to generate an appropriate exception and
87
* return false.
88
+ * skip_context_update is true to skip the "update FP context" part of this.
89
*/
90
-static bool vfp_access_check_m(DisasContext *s)
91
+bool vfp_access_check_m(DisasContext *s, bool skip_context_update)
92
{
93
if (s->fp_excp_el) {
94
/*
95
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_m(DisasContext *s)
96
/* Trigger lazy-state preservation if necessary */
97
gen_preserve_fp_state(s);
98
99
- /* Update ownership of FP context and create new FP context if needed */
100
- gen_update_fp_context(s);
101
+ if (!skip_context_update) {
102
+ /* Update ownership of FP context and create new FP context if needed */
103
+ gen_update_fp_context(s);
104
+ }
105
106
return true;
107
}
108
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_m(DisasContext *s)
109
bool vfp_access_check(DisasContext *s)
110
{
111
if (arm_dc_feature(s, ARM_FEATURE_M)) {
112
- return vfp_access_check_m(s);
113
+ return vfp_access_check_m(s, false);
114
} else {
115
return vfp_access_check_a(s, false);
116
}
117
--
118
2.20.1
119
120
diff view generated by jsdifflib
1
A write to the CONTROL register can change our current EL (by
1
Implement the forms of the MVE VLDR and VSTR insns which perform
2
writing to the nPRIV bit). That means that we can't assume
2
non-widening loads of bytes, halfwords or words from memory into
3
that s->current_el is still valid in trans_MSR_v7m() when
3
vector elements of the same width (encodings T5, T6, T7).
4
we try to rebuild the hflags.
5
4
6
Add a new helper rebuild_hflags_m32_newel() which, like the
5
(At the moment we know for MVE and M-profile in general that
7
existing rebuild_hflags_a32_newel(), recalculates the current
6
vfp_access_check() can never return false, but we include the
8
EL from scratch, and use it in trans_MSR_v7m().
7
conventional return-true-on-failure check for consistency
9
8
with non-M-profile translation code.)
10
This fixes an assertion about an hflags mismatch when the
11
guest changes privilege by writing to CONTROL.
12
9
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200303174950.3298-4-peter.maydell@linaro.org
12
Message-id: 20210617121628.20116-2-peter.maydell@linaro.org
16
---
13
---
17
target/arm/helper.h | 1 +
14
target/arm/{translate-mve.c => helper-mve.h} | 19 +-
18
target/arm/helper.c | 12 ++++++++++++
15
target/arm/helper.h | 2 +
19
target/arm/translate.c | 7 +++----
16
target/arm/internals.h | 11 ++
20
3 files changed, 16 insertions(+), 4 deletions(-)
17
target/arm/mve.decode | 22 +++
18
target/arm/mve_helper.c | 172 +++++++++++++++++++
19
target/arm/translate-mve.c | 119 +++++++++++++
20
target/arm/meson.build | 1 +
21
7 files changed, 334 insertions(+), 12 deletions(-)
22
copy target/arm/{translate-mve.c => helper-mve.h} (61%)
23
create mode 100644 target/arm/mve_helper.c
21
24
25
diff --git a/target/arm/translate-mve.c b/target/arm/helper-mve.h
26
similarity index 61%
27
copy from target/arm/translate-mve.c
28
copy to target/arm/helper-mve.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-mve.c
31
+++ b/target/arm/helper-mve.h
32
@@ -XXX,XX +XXX,XX @@
33
/*
34
- * ARM translation: M-profile MVE instructions
35
+ * M-profile MVE specific helper definitions
36
*
37
* Copyright (c) 2021 Linaro, Ltd.
38
*
39
@@ -XXX,XX +XXX,XX @@
40
* You should have received a copy of the GNU Lesser General Public
41
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
42
*/
43
-
44
-#include "qemu/osdep.h"
45
-#include "tcg/tcg-op.h"
46
-#include "tcg/tcg-op-gvec.h"
47
-#include "exec/exec-all.h"
48
-#include "exec/gen-icount.h"
49
-#include "translate.h"
50
-#include "translate-a32.h"
51
-
52
-/* Include the generated decoder */
53
-#include "decode-mve.c.inc"
54
+DEF_HELPER_FLAGS_3(mve_vldrb, TCG_CALL_NO_WG, void, env, ptr, i32)
55
+DEF_HELPER_FLAGS_3(mve_vldrh, TCG_CALL_NO_WG, void, env, ptr, i32)
56
+DEF_HELPER_FLAGS_3(mve_vldrw, TCG_CALL_NO_WG, void, env, ptr, i32)
57
+DEF_HELPER_FLAGS_3(mve_vstrb, TCG_CALL_NO_WG, void, env, ptr, i32)
58
+DEF_HELPER_FLAGS_3(mve_vstrh, TCG_CALL_NO_WG, void, env, ptr, i32)
59
+DEF_HELPER_FLAGS_3(mve_vstrw, TCG_CALL_NO_WG, void, env, ptr, i32)
22
diff --git a/target/arm/helper.h b/target/arm/helper.h
60
diff --git a/target/arm/helper.h b/target/arm/helper.h
23
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper.h
62
--- a/target/arm/helper.h
25
+++ b/target/arm/helper.h
63
+++ b/target/arm/helper.h
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(msr_banked, void, env, i32, i32, i32)
64
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
27
DEF_HELPER_2(get_user_reg, i32, env, i32)
65
#include "helper-a64.h"
28
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
66
#include "helper-sve.h"
29
67
#endif
30
+DEF_HELPER_FLAGS_1(rebuild_hflags_m32_newel, TCG_CALL_NO_RWG, void, env)
68
+
31
DEF_HELPER_FLAGS_2(rebuild_hflags_m32, TCG_CALL_NO_RWG, void, env, int)
69
+#include "helper-mve.h"
32
DEF_HELPER_FLAGS_1(rebuild_hflags_a32_newel, TCG_CALL_NO_RWG, void, env)
70
diff --git a/target/arm/internals.h b/target/arm/internals.h
33
DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int)
71
index XXXXXXX..XXXXXXX 100644
34
diff --git a/target/arm/helper.c b/target/arm/helper.c
72
--- a/target/arm/internals.h
35
index XXXXXXX..XXXXXXX 100644
73
+++ b/target/arm/internals.h
36
--- a/target/arm/helper.c
74
@@ -XXX,XX +XXX,XX @@ static inline uint64_t useronly_maybe_clean_ptr(uint32_t desc, uint64_t ptr)
37
+++ b/target/arm/helper.c
75
return ptr;
38
@@ -XXX,XX +XXX,XX @@ void arm_rebuild_hflags(CPUARMState *env)
39
env->hflags = rebuild_hflags_internal(env);
40
}
76
}
41
77
78
+/* Values for M-profile PSR.ECI for MVE insns */
79
+enum MVEECIState {
80
+ ECI_NONE = 0, /* No completed beats */
81
+ ECI_A0 = 1, /* Completed: A0 */
82
+ ECI_A0A1 = 2, /* Completed: A0, A1 */
83
+ /* 3 is reserved */
84
+ ECI_A0A1A2 = 4, /* Completed: A0, A1, A2 */
85
+ ECI_A0A1A2B0 = 5, /* Completed: A0, A1, A2, B0 */
86
+ /* All other values reserved */
87
+};
88
+
89
#endif
90
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/mve.decode
93
+++ b/target/arm/mve.decode
94
@@ -XXX,XX +XXX,XX @@
95
#
96
# This file is processed by scripts/decodetree.py
97
#
98
+
99
+%qd 22:1 13:3
100
+
101
+&vldr_vstr rn qd imm p a w size l
102
+
103
+@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd
104
+
105
+# Vector loads and stores
106
+
107
+# Non-widening loads/stores (P=0 W=0 is 'related encoding')
108
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111100 ....... @vldr_vstr \
109
+ size=0 p=0 w=1
110
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111101 ....... @vldr_vstr \
111
+ size=1 p=0 w=1
112
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111110 ....... @vldr_vstr \
113
+ size=2 p=0 w=1
114
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111100 ....... @vldr_vstr \
115
+ size=0 p=1
116
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
117
+ size=1 p=1
118
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
119
+ size=2 p=1
120
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
121
new file mode 100644
122
index XXXXXXX..XXXXXXX
123
--- /dev/null
124
+++ b/target/arm/mve_helper.c
125
@@ -XXX,XX +XXX,XX @@
42
+/*
126
+/*
43
+ * If we have triggered a EL state change we can't rely on the
127
+ * M-profile MVE Operations
44
+ * translator having passed it to us, we need to recompute.
128
+ *
129
+ * Copyright (c) 2021 Linaro, Ltd.
130
+ *
131
+ * This library is free software; you can redistribute it and/or
132
+ * modify it under the terms of the GNU Lesser General Public
133
+ * License as published by the Free Software Foundation; either
134
+ * version 2.1 of the License, or (at your option) any later version.
135
+ *
136
+ * This library is distributed in the hope that it will be useful,
137
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
138
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139
+ * Lesser General Public License for more details.
140
+ *
141
+ * You should have received a copy of the GNU Lesser General Public
142
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
45
+ */
143
+ */
46
+void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env)
144
+
47
+{
145
+#include "qemu/osdep.h"
48
+ int el = arm_current_el(env);
146
+#include "cpu.h"
49
+ int fp_el = fp_exception_el(env, el);
147
+#include "internals.h"
50
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
148
+#include "vec_internal.h"
51
+ env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
149
+#include "exec/helper-proto.h"
52
+}
150
+#include "exec/cpu_ldst.h"
53
+
151
+#include "exec/exec-all.h"
54
void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
152
+
55
{
153
+static uint16_t mve_element_mask(CPUARMState *env)
56
int fp_el = fp_exception_el(env, el);
154
+{
57
diff --git a/target/arm/translate.c b/target/arm/translate.c
155
+ /*
58
index XXXXXXX..XXXXXXX 100644
156
+ * Return the mask of which elements in the MVE vector should be
59
--- a/target/arm/translate.c
157
+ * updated. This is a combination of multiple things:
60
+++ b/target/arm/translate.c
158
+ * (1) by default, we update every lane in the vector
61
@@ -XXX,XX +XXX,XX @@ static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
159
+ * (2) VPT predication stores its state in the VPR register;
62
160
+ * (3) low-overhead-branch tail predication will mask out part
63
static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
161
+ * the vector on the final iteration of the loop
64
{
162
+ * (4) if EPSR.ECI is set then we must execute only some beats
65
- TCGv_i32 addr, reg, el;
163
+ * of the insn
66
+ TCGv_i32 addr, reg;
164
+ * We combine all these into a 16-bit result with the same semantics
67
165
+ * as VPR.P0: 0 to mask the lane, 1 if it is active.
68
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
166
+ * 8-bit vector ops will look at all bits of the result;
69
return false;
167
+ * 16-bit ops will look at bits 0, 2, 4, ...;
70
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
168
+ * 32-bit ops will look at bits 0, 4, 8 and 12.
71
gen_helper_v7m_msr(cpu_env, addr, reg);
169
+ * Compare pseudocode GetCurInstrBeat(), though that only returns
72
tcg_temp_free_i32(addr);
170
+ * the 4-bit slice of the mask corresponding to a single beat.
73
tcg_temp_free_i32(reg);
171
+ */
74
- el = tcg_const_i32(s->current_el);
172
+ uint16_t mask = FIELD_EX32(env->v7m.vpr, V7M_VPR, P0);
75
- gen_helper_rebuild_hflags_m32(cpu_env, el);
173
+
76
- tcg_temp_free_i32(el);
174
+ if (!(env->v7m.vpr & R_V7M_VPR_MASK01_MASK)) {
77
+ /* If we wrote to CONTROL, the EL might have changed */
175
+ mask |= 0xff;
78
+ gen_helper_rebuild_hflags_m32_newel(cpu_env);
176
+ }
79
gen_lookup_tb(s);
177
+ if (!(env->v7m.vpr & R_V7M_VPR_MASK23_MASK)) {
80
return true;
178
+ mask |= 0xff00;
81
}
179
+ }
180
+
181
+ if (env->v7m.ltpsize < 4 &&
182
+ env->regs[14] <= (1 << (4 - env->v7m.ltpsize))) {
183
+ /*
184
+ * Tail predication active, and this is the last loop iteration.
185
+ * The element size is (1 << ltpsize), and we only want to process
186
+ * loopcount elements, so we want to retain the least significant
187
+ * (loopcount * esize) predicate bits and zero out bits above that.
188
+ */
189
+ int masklen = env->regs[14] << env->v7m.ltpsize;
190
+ assert(masklen <= 16);
191
+ mask &= MAKE_64BIT_MASK(0, masklen);
192
+ }
193
+
194
+ if ((env->condexec_bits & 0xf) == 0) {
195
+ /*
196
+ * ECI bits indicate which beats are already executed;
197
+ * we handle this by effectively predicating them out.
198
+ */
199
+ int eci = env->condexec_bits >> 4;
200
+ switch (eci) {
201
+ case ECI_NONE:
202
+ break;
203
+ case ECI_A0:
204
+ mask &= 0xfff0;
205
+ break;
206
+ case ECI_A0A1:
207
+ mask &= 0xff00;
208
+ break;
209
+ case ECI_A0A1A2:
210
+ case ECI_A0A1A2B0:
211
+ mask &= 0xf000;
212
+ break;
213
+ default:
214
+ g_assert_not_reached();
215
+ }
216
+ }
217
+
218
+ return mask;
219
+}
220
+
221
+static void mve_advance_vpt(CPUARMState *env)
222
+{
223
+ /* Advance the VPT and ECI state if necessary */
224
+ uint32_t vpr = env->v7m.vpr;
225
+ unsigned mask01, mask23;
226
+
227
+ if ((env->condexec_bits & 0xf) == 0) {
228
+ env->condexec_bits = (env->condexec_bits == (ECI_A0A1A2B0 << 4)) ?
229
+ (ECI_A0 << 4) : (ECI_NONE << 4);
230
+ }
231
+
232
+ if (!(vpr & (R_V7M_VPR_MASK01_MASK | R_V7M_VPR_MASK23_MASK))) {
233
+ /* VPT not enabled, nothing to do */
234
+ return;
235
+ }
236
+
237
+ mask01 = FIELD_EX32(vpr, V7M_VPR, MASK01);
238
+ mask23 = FIELD_EX32(vpr, V7M_VPR, MASK23);
239
+ if (mask01 > 8) {
240
+ /* high bit set, but not 0b1000: invert the relevant half of P0 */
241
+ vpr ^= 0xff;
242
+ }
243
+ if (mask23 > 8) {
244
+ /* high bit set, but not 0b1000: invert the relevant half of P0 */
245
+ vpr ^= 0xff00;
246
+ }
247
+ vpr = FIELD_DP32(vpr, V7M_VPR, MASK01, mask01 << 1);
248
+ vpr = FIELD_DP32(vpr, V7M_VPR, MASK23, mask23 << 1);
249
+ env->v7m.vpr = vpr;
250
+}
251
+
252
+
253
+#define DO_VLDR(OP, MSIZE, LDTYPE, ESIZE, TYPE) \
254
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, uint32_t addr) \
255
+ { \
256
+ TYPE *d = vd; \
257
+ uint16_t mask = mve_element_mask(env); \
258
+ unsigned b, e; \
259
+ /* \
260
+ * R_SXTM allows the dest reg to become UNKNOWN for abandoned \
261
+ * beats so we don't care if we update part of the dest and \
262
+ * then take an exception. \
263
+ */ \
264
+ for (b = 0, e = 0; b < 16; b += ESIZE, e++) { \
265
+ if (mask & (1 << b)) { \
266
+ d[H##ESIZE(e)] = cpu_##LDTYPE##_data_ra(env, addr, GETPC()); \
267
+ } \
268
+ addr += MSIZE; \
269
+ } \
270
+ mve_advance_vpt(env); \
271
+ }
272
+
273
+#define DO_VSTR(OP, MSIZE, STTYPE, ESIZE, TYPE) \
274
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, uint32_t addr) \
275
+ { \
276
+ TYPE *d = vd; \
277
+ uint16_t mask = mve_element_mask(env); \
278
+ unsigned b, e; \
279
+ for (b = 0, e = 0; b < 16; b += ESIZE, e++) { \
280
+ if (mask & (1 << b)) { \
281
+ cpu_##STTYPE##_data_ra(env, addr, d[H##ESIZE(e)], GETPC()); \
282
+ } \
283
+ addr += MSIZE; \
284
+ } \
285
+ mve_advance_vpt(env); \
286
+ }
287
+
288
+DO_VLDR(vldrb, 1, ldub, 1, uint8_t)
289
+DO_VLDR(vldrh, 2, lduw, 2, uint16_t)
290
+DO_VLDR(vldrw, 4, ldl, 4, uint32_t)
291
+
292
+DO_VSTR(vstrb, 1, stb, 1, uint8_t)
293
+DO_VSTR(vstrh, 2, stw, 2, uint16_t)
294
+DO_VSTR(vstrw, 4, stl, 4, uint32_t)
295
+
296
+#undef DO_VLDR
297
+#undef DO_VSTR
298
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/target/arm/translate-mve.c
301
+++ b/target/arm/translate-mve.c
302
@@ -XXX,XX +XXX,XX @@
303
304
/* Include the generated decoder */
305
#include "decode-mve.c.inc"
306
+
307
+typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
308
+
309
+/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
310
+static inline long mve_qreg_offset(unsigned reg)
311
+{
312
+ return offsetof(CPUARMState, vfp.zregs[reg].d[0]);
313
+}
314
+
315
+static TCGv_ptr mve_qreg_ptr(unsigned reg)
316
+{
317
+ TCGv_ptr ret = tcg_temp_new_ptr();
318
+ tcg_gen_addi_ptr(ret, cpu_env, mve_qreg_offset(reg));
319
+ return ret;
320
+}
321
+
322
+static bool mve_check_qreg_bank(DisasContext *s, int qmask)
323
+{
324
+ /*
325
+ * Check whether Qregs are in range. For v8.1M only Q0..Q7
326
+ * are supported, see VFPSmallRegisterBank().
327
+ */
328
+ return qmask < 8;
329
+}
330
+
331
+static bool mve_eci_check(DisasContext *s)
332
+{
333
+ /*
334
+ * This is a beatwise insn: check that ECI is valid (not a
335
+ * reserved value) and note that we are handling it.
336
+ * Return true if OK, false if we generated an exception.
337
+ */
338
+ s->eci_handled = true;
339
+ switch (s->eci) {
340
+ case ECI_NONE:
341
+ case ECI_A0:
342
+ case ECI_A0A1:
343
+ case ECI_A0A1A2:
344
+ case ECI_A0A1A2B0:
345
+ return true;
346
+ default:
347
+ /* Reserved value: INVSTATE UsageFault */
348
+ gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
349
+ default_exception_el(s));
350
+ return false;
351
+ }
352
+}
353
+
354
+static void mve_update_eci(DisasContext *s)
355
+{
356
+ /*
357
+ * The helper function will always update the CPUState field,
358
+ * so we only need to update the DisasContext field.
359
+ */
360
+ if (s->eci) {
361
+ s->eci = (s->eci == ECI_A0A1A2B0) ? ECI_A0 : ECI_NONE;
362
+ }
363
+}
364
+
365
+static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn)
366
+{
367
+ TCGv_i32 addr;
368
+ uint32_t offset;
369
+ TCGv_ptr qreg;
370
+
371
+ if (!dc_isar_feature(aa32_mve, s) ||
372
+ !mve_check_qreg_bank(s, a->qd) ||
373
+ !fn) {
374
+ return false;
375
+ }
376
+
377
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
378
+ if (a->rn == 15 || (a->rn == 13 && a->w)) {
379
+ return false;
380
+ }
381
+
382
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
383
+ return true;
384
+ }
385
+
386
+ offset = a->imm << a->size;
387
+ if (!a->a) {
388
+ offset = -offset;
389
+ }
390
+ addr = load_reg(s, a->rn);
391
+ if (a->p) {
392
+ tcg_gen_addi_i32(addr, addr, offset);
393
+ }
394
+
395
+ qreg = mve_qreg_ptr(a->qd);
396
+ fn(cpu_env, qreg, addr);
397
+ tcg_temp_free_ptr(qreg);
398
+
399
+ /*
400
+ * Writeback always happens after the last beat of the insn,
401
+ * regardless of predication
402
+ */
403
+ if (a->w) {
404
+ if (!a->p) {
405
+ tcg_gen_addi_i32(addr, addr, offset);
406
+ }
407
+ store_reg(s, a->rn, addr);
408
+ } else {
409
+ tcg_temp_free_i32(addr);
410
+ }
411
+ mve_update_eci(s);
412
+ return true;
413
+}
414
+
415
+static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
416
+{
417
+ static MVEGenLdStFn * const ldstfns[4][2] = {
418
+ { gen_helper_mve_vstrb, gen_helper_mve_vldrb },
419
+ { gen_helper_mve_vstrh, gen_helper_mve_vldrh },
420
+ { gen_helper_mve_vstrw, gen_helper_mve_vldrw },
421
+ { NULL, NULL }
422
+ };
423
+ return do_ldst(s, a, ldstfns[a->size][a->l]);
424
+}
425
diff --git a/target/arm/meson.build b/target/arm/meson.build
426
index XXXXXXX..XXXXXXX 100644
427
--- a/target/arm/meson.build
428
+++ b/target/arm/meson.build
429
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
430
'helper.c',
431
'iwmmxt_helper.c',
432
'm_helper.c',
433
+ 'mve_helper.c',
434
'neon_helper.c',
435
'op_helper.c',
436
'tlb_helper.c',
82
--
437
--
83
2.20.1
438
2.20.1
84
439
85
440
diff view generated by jsdifflib
New patch
1
Implement the variants of MVE VLDR (encodings T1, T2) which perform
2
"widening" loads where bytes or halfwords are loaded from memory and
3
zero or sign-extended into halfword or word length vector elements,
4
and the narrowing MVE VSTR (encodings T1, T2) where bytes or
5
halfwords are stored from halfword or word elements.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210617121628.20116-3-peter.maydell@linaro.org
10
---
11
target/arm/helper-mve.h | 10 ++++++++++
12
target/arm/mve.decode | 25 +++++++++++++++++++++++--
13
target/arm/mve_helper.c | 11 +++++++++++
14
target/arm/translate-mve.c | 14 ++++++++++++++
15
4 files changed, 58 insertions(+), 2 deletions(-)
16
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vldrw, TCG_CALL_NO_WG, void, env, ptr, i32)
22
DEF_HELPER_FLAGS_3(mve_vstrb, TCG_CALL_NO_WG, void, env, ptr, i32)
23
DEF_HELPER_FLAGS_3(mve_vstrh, TCG_CALL_NO_WG, void, env, ptr, i32)
24
DEF_HELPER_FLAGS_3(mve_vstrw, TCG_CALL_NO_WG, void, env, ptr, i32)
25
+
26
+DEF_HELPER_FLAGS_3(mve_vldrb_sh, TCG_CALL_NO_WG, void, env, ptr, i32)
27
+DEF_HELPER_FLAGS_3(mve_vldrb_sw, TCG_CALL_NO_WG, void, env, ptr, i32)
28
+DEF_HELPER_FLAGS_3(mve_vldrb_uh, TCG_CALL_NO_WG, void, env, ptr, i32)
29
+DEF_HELPER_FLAGS_3(mve_vldrb_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
30
+DEF_HELPER_FLAGS_3(mve_vldrh_sw, TCG_CALL_NO_WG, void, env, ptr, i32)
31
+DEF_HELPER_FLAGS_3(mve_vldrh_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
32
+DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
33
+DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
34
+DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
35
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/mve.decode
38
+++ b/target/arm/mve.decode
39
@@ -XXX,XX +XXX,XX @@
40
41
%qd 22:1 13:3
42
43
-&vldr_vstr rn qd imm p a w size l
44
+&vldr_vstr rn qd imm p a w size l u
45
46
-@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd
47
+@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
48
+# Note that both Rn and Qd are 3 bits only (no D bit)
49
+@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
50
51
# Vector loads and stores
52
53
+# Widening loads and narrowing stores:
54
+# for these P=0 W=0 is 'related encoding'; sz=11 is 'related encoding'
55
+# This means we need to expand out to multiple patterns for P, W, SZ.
56
+# For stores the U bit must be 0 but we catch that in the trans_ function.
57
+# The naming scheme here is "VLDSTB_H == in-memory byte load/store to/from
58
+# signed halfword element in register", etc.
59
+VLDSTB_H 111 . 110 0 a:1 0 1 . 0 ... ... 0 111 01 ....... @vldst_wn \
60
+ p=0 w=1 size=1
61
+VLDSTB_H 111 . 110 1 a:1 0 w:1 . 0 ... ... 0 111 01 ....... @vldst_wn \
62
+ p=1 size=1
63
+VLDSTB_W 111 . 110 0 a:1 0 1 . 0 ... ... 0 111 10 ....... @vldst_wn \
64
+ p=0 w=1 size=2
65
+VLDSTB_W 111 . 110 1 a:1 0 w:1 . 0 ... ... 0 111 10 ....... @vldst_wn \
66
+ p=1 size=2
67
+VLDSTH_W 111 . 110 0 a:1 0 1 . 1 ... ... 0 111 10 ....... @vldst_wn \
68
+ p=0 w=1 size=2
69
+VLDSTH_W 111 . 110 1 a:1 0 w:1 . 1 ... ... 0 111 10 ....... @vldst_wn \
70
+ p=1 size=2
71
+
72
# Non-widening loads/stores (P=0 W=0 is 'related encoding')
73
VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111100 ....... @vldr_vstr \
74
size=0 p=0 w=1
75
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/mve_helper.c
78
+++ b/target/arm/mve_helper.c
79
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrb, 1, stb, 1, uint8_t)
80
DO_VSTR(vstrh, 2, stw, 2, uint16_t)
81
DO_VSTR(vstrw, 4, stl, 4, uint32_t)
82
83
+DO_VLDR(vldrb_sh, 1, ldsb, 2, int16_t)
84
+DO_VLDR(vldrb_sw, 1, ldsb, 4, int32_t)
85
+DO_VLDR(vldrb_uh, 1, ldub, 2, uint16_t)
86
+DO_VLDR(vldrb_uw, 1, ldub, 4, uint32_t)
87
+DO_VLDR(vldrh_sw, 2, ldsw, 4, int32_t)
88
+DO_VLDR(vldrh_uw, 2, lduw, 4, uint32_t)
89
+
90
+DO_VSTR(vstrb_h, 1, stb, 2, int16_t)
91
+DO_VSTR(vstrb_w, 1, stb, 4, int32_t)
92
+DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
93
+
94
#undef DO_VLDR
95
#undef DO_VSTR
96
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate-mve.c
99
+++ b/target/arm/translate-mve.c
100
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
101
};
102
return do_ldst(s, a, ldstfns[a->size][a->l]);
103
}
104
+
105
+#define DO_VLDST_WIDE_NARROW(OP, SLD, ULD, ST) \
106
+ static bool trans_##OP(DisasContext *s, arg_VLDR_VSTR *a) \
107
+ { \
108
+ static MVEGenLdStFn * const ldstfns[2][2] = { \
109
+ { gen_helper_mve_##ST, gen_helper_mve_##SLD }, \
110
+ { NULL, gen_helper_mve_##ULD }, \
111
+ }; \
112
+ return do_ldst(s, a, ldstfns[a->u][a->l]); \
113
+ }
114
+
115
+DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
116
+DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
117
+DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
118
--
119
2.20.1
120
121
diff view generated by jsdifflib
New patch
1
1
Implement the MVE VCLZ insn (and the necessary machinery
2
for MVE 1-input vector ops).
3
4
Note that for non-load instructions predication is always performed
5
at a byte level granularity regardless of element size (R_ZLSJ),
6
and so the masking logic here differs from that used in the VLDR
7
and VSTR helpers.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210617121628.20116-4-peter.maydell@linaro.org
12
---
13
target/arm/helper-mve.h | 4 ++
14
target/arm/mve.decode | 8 ++++
15
target/arm/mve_helper.c | 82 ++++++++++++++++++++++++++++++++++++++
16
target/arm/translate-mve.c | 38 ++++++++++++++++++
17
4 files changed, 132 insertions(+)
18
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper-mve.h
22
+++ b/target/arm/helper-mve.h
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vldrh_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
24
DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
25
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
26
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
27
+
28
+DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
+DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
+DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/mve.decode
34
+++ b/target/arm/mve.decode
35
@@ -XXX,XX +XXX,XX @@
36
#
37
38
%qd 22:1 13:3
39
+%qm 5:1 1:3
40
41
&vldr_vstr rn qd imm p a w size l u
42
+&1op qd qm size
43
44
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
45
# Note that both Rn and Qd are 3 bits only (no D bit)
46
@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
47
48
+@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
49
+
50
# Vector loads and stores
51
52
# Widening loads and narrowing stores:
53
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
54
size=1 p=1
55
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
56
size=2 p=1
57
+
58
+# Vector miscellaneous
59
+
60
+VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
61
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/mve_helper.c
64
+++ b/target/arm/mve_helper.c
65
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
66
67
#undef DO_VLDR
68
#undef DO_VSTR
69
+
70
+/*
71
+ * The mergemask(D, R, M) macro performs the operation "*D = R" but
72
+ * storing only the bytes which correspond to 1 bits in M,
73
+ * leaving other bytes in *D unchanged. We use _Generic
74
+ * to select the correct implementation based on the type of D.
75
+ */
76
+
77
+static void mergemask_ub(uint8_t *d, uint8_t r, uint16_t mask)
78
+{
79
+ if (mask & 1) {
80
+ *d = r;
81
+ }
82
+}
83
+
84
+static void mergemask_sb(int8_t *d, int8_t r, uint16_t mask)
85
+{
86
+ mergemask_ub((uint8_t *)d, r, mask);
87
+}
88
+
89
+static void mergemask_uh(uint16_t *d, uint16_t r, uint16_t mask)
90
+{
91
+ uint16_t bmask = expand_pred_b_data[mask & 3];
92
+ *d = (*d & ~bmask) | (r & bmask);
93
+}
94
+
95
+static void mergemask_sh(int16_t *d, int16_t r, uint16_t mask)
96
+{
97
+ mergemask_uh((uint16_t *)d, r, mask);
98
+}
99
+
100
+static void mergemask_uw(uint32_t *d, uint32_t r, uint16_t mask)
101
+{
102
+ uint32_t bmask = expand_pred_b_data[mask & 0xf];
103
+ *d = (*d & ~bmask) | (r & bmask);
104
+}
105
+
106
+static void mergemask_sw(int32_t *d, int32_t r, uint16_t mask)
107
+{
108
+ mergemask_uw((uint32_t *)d, r, mask);
109
+}
110
+
111
+static void mergemask_uq(uint64_t *d, uint64_t r, uint16_t mask)
112
+{
113
+ uint64_t bmask = expand_pred_b_data[mask & 0xff];
114
+ *d = (*d & ~bmask) | (r & bmask);
115
+}
116
+
117
+static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
118
+{
119
+ mergemask_uq((uint64_t *)d, r, mask);
120
+}
121
+
122
+#define mergemask(D, R, M) \
123
+ _Generic(D, \
124
+ uint8_t *: mergemask_ub, \
125
+ int8_t *: mergemask_sb, \
126
+ uint16_t *: mergemask_uh, \
127
+ int16_t *: mergemask_sh, \
128
+ uint32_t *: mergemask_uw, \
129
+ int32_t *: mergemask_sw, \
130
+ uint64_t *: mergemask_uq, \
131
+ int64_t *: mergemask_sq)(D, R, M)
132
+
133
+#define DO_1OP(OP, ESIZE, TYPE, FN) \
134
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
135
+ { \
136
+ TYPE *d = vd, *m = vm; \
137
+ uint16_t mask = mve_element_mask(env); \
138
+ unsigned e; \
139
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
140
+ mergemask(&d[H##ESIZE(e)], FN(m[H##ESIZE(e)]), mask); \
141
+ } \
142
+ mve_advance_vpt(env); \
143
+ }
144
+
145
+#define DO_CLZ_B(N) (clz32(N) - 24)
146
+#define DO_CLZ_H(N) (clz32(N) - 16)
147
+
148
+DO_1OP(vclzb, 1, uint8_t, DO_CLZ_B)
149
+DO_1OP(vclzh, 2, uint16_t, DO_CLZ_H)
150
+DO_1OP(vclzw, 4, uint32_t, clz32)
151
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/target/arm/translate-mve.c
154
+++ b/target/arm/translate-mve.c
155
@@ -XXX,XX +XXX,XX @@
156
#include "decode-mve.c.inc"
157
158
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
159
+typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
160
161
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
162
static inline long mve_qreg_offset(unsigned reg)
163
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
164
DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
165
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
166
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
167
+
168
+static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
169
+{
170
+ TCGv_ptr qd, qm;
171
+
172
+ if (!dc_isar_feature(aa32_mve, s) ||
173
+ !mve_check_qreg_bank(s, a->qd | a->qm) ||
174
+ !fn) {
175
+ return false;
176
+ }
177
+
178
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
179
+ return true;
180
+ }
181
+
182
+ qd = mve_qreg_ptr(a->qd);
183
+ qm = mve_qreg_ptr(a->qm);
184
+ fn(cpu_env, qd, qm);
185
+ tcg_temp_free_ptr(qd);
186
+ tcg_temp_free_ptr(qm);
187
+ mve_update_eci(s);
188
+ return true;
189
+}
190
+
191
+#define DO_1OP(INSN, FN) \
192
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
193
+ { \
194
+ static MVEGenOneOpFn * const fns[] = { \
195
+ gen_helper_mve_##FN##b, \
196
+ gen_helper_mve_##FN##h, \
197
+ gen_helper_mve_##FN##w, \
198
+ NULL, \
199
+ }; \
200
+ return do_1op(s, a, fns[a->size]); \
201
+ }
202
+
203
+DO_1OP(VCLZ, vclz)
204
--
205
2.20.1
206
207
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Implement the MVE VCLS insn.
2
2
3
We plan to introduce yet another value for the gic version (nosel).
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
As we already use exotic values such as 0 and -1, let's introduce
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
a dedicated enum type and let vms->gic_version take this
5
Message-id: 20210617121628.20116-5-peter.maydell@linaro.org
6
type.
6
---
7
target/arm/helper-mve.h | 4 ++++
8
target/arm/mve.decode | 1 +
9
target/arm/mve_helper.c | 7 +++++++
10
target/arm/translate-mve.c | 1 +
11
4 files changed, 13 insertions(+)
7
12
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
12
Message-id: 20200311131618.7187-3-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
include/hw/arm/virt.h | 11 +++++++++--
16
hw/arm/virt.c | 30 +++++++++++++++---------------
17
2 files changed, 24 insertions(+), 17 deletions(-)
18
19
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/arm/virt.h
15
--- a/target/arm/helper-mve.h
22
+++ b/include/hw/arm/virt.h
16
+++ b/target/arm/helper-mve.h
23
@@ -XXX,XX +XXX,XX @@ typedef enum VirtIOMMUType {
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
24
VIRT_IOMMU_VIRTIO,
18
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
25
} VirtIOMMUType;
19
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
26
20
27
+typedef enum VirtGICType {
21
+DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
+ VIRT_GIC_VERSION_MAX,
22
+DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
+ VIRT_GIC_VERSION_HOST,
23
+DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
+ VIRT_GIC_VERSION_2,
31
+ VIRT_GIC_VERSION_3,
32
+} VirtGICType;
33
+
24
+
34
typedef struct MemMapEntry {
25
DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
35
hwaddr base;
26
DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
36
hwaddr size;
27
DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
37
@@ -XXX,XX +XXX,XX @@ typedef struct {
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
38
bool highmem_ecam;
39
bool its;
40
bool virt;
41
- int32_t gic_version;
42
+ VirtGICType gic_version;
43
VirtIOMMUType iommu;
44
uint16_t virtio_iommu_bdf;
45
struct arm_boot_info bootinfo;
46
@@ -XXX,XX +XXX,XX @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
47
uint32_t redist0_capacity =
48
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
49
50
- assert(vms->gic_version == 3);
51
+ assert(vms->gic_version == VIRT_GIC_VERSION_3);
52
53
return vms->smp_cpus > redist0_capacity ? 2 : 1;
54
}
55
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
56
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/virt.c
30
--- a/target/arm/mve.decode
58
+++ b/hw/arm/virt.c
31
+++ b/target/arm/mve.decode
59
@@ -XXX,XX +XXX,XX @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
32
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
60
irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
33
34
# Vector miscellaneous
35
36
+VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
37
VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@ static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
43
mve_advance_vpt(env); \
61
}
44
}
62
45
63
- if (vms->gic_version == 2) {
46
+#define DO_CLS_B(N) (clrsb32(N) - 24)
64
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
47
+#define DO_CLS_H(N) (clrsb32(N) - 16)
65
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
48
+
66
GIC_FDT_IRQ_PPI_CPU_WIDTH,
49
+DO_1OP(vclsb, 1, int8_t, DO_CLS_B)
67
(1 << vms->smp_cpus) - 1);
50
+DO_1OP(vclsh, 2, int16_t, DO_CLS_H)
68
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
51
+DO_1OP(vclsw, 4, int32_t, clrsb32)
69
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 0x2);
52
+
70
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 0x2);
53
#define DO_CLZ_B(N) (clz32(N) - 24)
71
qemu_fdt_setprop(vms->fdt, nodename, "ranges", NULL, 0);
54
#define DO_CLZ_H(N) (clz32(N) - 16)
72
- if (vms->gic_version == 3) {
55
73
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
56
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
74
int nb_redist_regions = virt_gicv3_redist_region_count(vms);
57
index XXXXXXX..XXXXXXX 100644
75
58
--- a/target/arm/translate-mve.c
76
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
59
+++ b/target/arm/translate-mve.c
77
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
60
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
78
}
79
}
61
}
80
62
81
- if (vms->gic_version == 2) {
63
DO_1OP(VCLZ, vclz)
82
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
64
+DO_1OP(VCLS, vcls)
83
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
84
GIC_FDT_IRQ_PPI_CPU_WIDTH,
85
(1 << vms->smp_cpus) - 1);
86
@@ -XXX,XX +XXX,XX @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
87
* purposes are to make TCG consistent (with 64-bit KVM hosts)
88
* and to improve SGI efficiency.
89
*/
90
- if (vms->gic_version == 3) {
91
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
92
clustersz = GICV3_TARGETLIST_BITS;
93
} else {
94
clustersz = GIC_TARGETLIST_BITS;
95
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
96
/* We can probe only here because during property set
97
* KVM is not available yet
98
*/
99
- if (vms->gic_version <= 0) {
100
- /* "host" or "max" */
101
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
102
+ vms->gic_version == VIRT_GIC_VERSION_MAX) {
103
if (!kvm_enabled()) {
104
- if (vms->gic_version == 0) {
105
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
106
error_report("gic-version=host requires KVM");
107
exit(1);
108
} else {
109
/* "max": currently means 3 for TCG */
110
- vms->gic_version = 3;
111
+ vms->gic_version = VIRT_GIC_VERSION_3;
112
}
113
} else {
114
vms->gic_version = kvm_arm_vgic_probe();
115
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
116
/* The maximum number of CPUs depends on the GIC version, or on how
117
* many redistributors we can fit into the memory map.
118
*/
119
- if (vms->gic_version == 3) {
120
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
121
virt_max_cpus =
122
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
123
virt_max_cpus +=
124
@@ -XXX,XX +XXX,XX @@ static void virt_set_its(Object *obj, bool value, Error **errp)
125
static char *virt_get_gic_version(Object *obj, Error **errp)
126
{
127
VirtMachineState *vms = VIRT_MACHINE(obj);
128
- const char *val = vms->gic_version == 3 ? "3" : "2";
129
+ const char *val = vms->gic_version == VIRT_GIC_VERSION_3 ? "3" : "2";
130
131
return g_strdup(val);
132
}
133
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
134
VirtMachineState *vms = VIRT_MACHINE(obj);
135
136
if (!strcmp(value, "3")) {
137
- vms->gic_version = 3;
138
+ vms->gic_version = VIRT_GIC_VERSION_3;
139
} else if (!strcmp(value, "2")) {
140
- vms->gic_version = 2;
141
+ vms->gic_version = VIRT_GIC_VERSION_2;
142
} else if (!strcmp(value, "host")) {
143
- vms->gic_version = 0; /* Will probe later */
144
+ vms->gic_version = VIRT_GIC_VERSION_HOST; /* Will probe later */
145
} else if (!strcmp(value, "max")) {
146
- vms->gic_version = -1; /* Will probe later */
147
+ vms->gic_version = VIRT_GIC_VERSION_MAX; /* Will probe later */
148
} else {
149
error_setg(errp, "Invalid gic-version value");
150
error_append_hint(errp, "Valid values are 3, 2, host, max.\n");
151
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
152
"physical address space above 32 bits",
153
NULL);
154
/* Default GIC type is v2 */
155
- vms->gic_version = 2;
156
+ vms->gic_version = VIRT_GIC_VERSION_2;
157
object_property_add_str(obj, "gic-version", virt_get_gic_version,
158
virt_set_gic_version, NULL);
159
object_property_set_description(obj, "gic-version",
160
--
65
--
161
2.20.1
66
2.20.1
162
67
163
68
diff view generated by jsdifflib
New patch
1
Implement the MVE instructions VREV16, VREV32 and VREV64.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-6-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 7 +++++++
8
target/arm/mve.decode | 4 ++++
9
target/arm/mve_helper.c | 7 +++++++
10
target/arm/translate-mve.c | 33 +++++++++++++++++++++++++++++++++
11
4 files changed, 51 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_3(mve_vrev16b, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vrev32b, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vrev32h, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vrev64b, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
33
34
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
35
VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
36
+
37
+VREV16 1111 1111 1 . 11 .. 00 ... 0 0001 01 . 0 ... 0 @1op
38
+VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
39
+VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
40
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/mve_helper.c
43
+++ b/target/arm/mve_helper.c
44
@@ -XXX,XX +XXX,XX @@ DO_1OP(vclsw, 4, int32_t, clrsb32)
45
DO_1OP(vclzb, 1, uint8_t, DO_CLZ_B)
46
DO_1OP(vclzh, 2, uint16_t, DO_CLZ_H)
47
DO_1OP(vclzw, 4, uint32_t, clz32)
48
+
49
+DO_1OP(vrev16b, 2, uint16_t, bswap16)
50
+DO_1OP(vrev32b, 4, uint32_t, bswap32)
51
+DO_1OP(vrev32h, 4, uint32_t, hswap32)
52
+DO_1OP(vrev64b, 8, uint64_t, bswap64)
53
+DO_1OP(vrev64h, 8, uint64_t, hswap64)
54
+DO_1OP(vrev64w, 8, uint64_t, wswap64)
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-mve.c
58
+++ b/target/arm/translate-mve.c
59
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
60
61
DO_1OP(VCLZ, vclz)
62
DO_1OP(VCLS, vcls)
63
+
64
+static bool trans_VREV16(DisasContext *s, arg_1op *a)
65
+{
66
+ static MVEGenOneOpFn * const fns[] = {
67
+ gen_helper_mve_vrev16b,
68
+ NULL,
69
+ NULL,
70
+ NULL,
71
+ };
72
+ return do_1op(s, a, fns[a->size]);
73
+}
74
+
75
+static bool trans_VREV32(DisasContext *s, arg_1op *a)
76
+{
77
+ static MVEGenOneOpFn * const fns[] = {
78
+ gen_helper_mve_vrev32b,
79
+ gen_helper_mve_vrev32h,
80
+ NULL,
81
+ NULL,
82
+ };
83
+ return do_1op(s, a, fns[a->size]);
84
+}
85
+
86
+static bool trans_VREV64(DisasContext *s, arg_1op *a)
87
+{
88
+ static MVEGenOneOpFn * const fns[] = {
89
+ gen_helper_mve_vrev64b,
90
+ gen_helper_mve_vrev64h,
91
+ gen_helper_mve_vrev64w,
92
+ NULL,
93
+ };
94
+ return do_1op(s, a, fns[a->size]);
95
+}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
New patch
1
Implement the MVE VMVN(register) operation. Note that for
2
predication this operation is byte-by-byte.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-7-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 2 ++
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 4 ++++
11
target/arm/translate-mve.c | 5 +++++
12
4 files changed, 14 insertions(+)
13
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vrev32h, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vrev64b, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_3(mve_vmvn, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/mve.decode
27
+++ b/target/arm/mve.decode
28
@@ -XXX,XX +XXX,XX @@
29
@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
30
31
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
32
+@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
33
34
# Vector loads and stores
35
36
@@ -XXX,XX +XXX,XX @@ VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
37
VREV16 1111 1111 1 . 11 .. 00 ... 0 0001 01 . 0 ... 0 @1op
38
VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
39
VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
40
+
41
+VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_1OP(vrev32h, 4, uint32_t, hswap32)
47
DO_1OP(vrev64b, 8, uint64_t, bswap64)
48
DO_1OP(vrev64h, 8, uint64_t, hswap64)
49
DO_1OP(vrev64w, 8, uint64_t, wswap64)
50
+
51
+#define DO_NOT(N) (~(N))
52
+
53
+DO_1OP(vmvn, 8, uint64_t, DO_NOT)
54
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/translate-mve.c
57
+++ b/target/arm/translate-mve.c
58
@@ -XXX,XX +XXX,XX @@ static bool trans_VREV64(DisasContext *s, arg_1op *a)
59
};
60
return do_1op(s, a, fns[a->size]);
61
}
62
+
63
+static bool trans_VMVN(DisasContext *s, arg_1op *a)
64
+{
65
+ return do_1op(s, a, gen_helper_mve_vmvn);
66
+}
67
--
68
2.20.1
69
70
diff view generated by jsdifflib
New patch
1
Implement the MVE VABS functions (both integer and floating point).
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-8-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 6 ++++++
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 13 +++++++++++++
10
target/arm/translate-mve.c | 15 +++++++++++++++
11
4 files changed, 37 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
20
DEF_HELPER_FLAGS_3(mve_vmvn, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_3(mve_vabsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vabsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vfabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vfabss, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/mve.decode
30
+++ b/target/arm/mve.decode
31
@@ -XXX,XX +XXX,XX @@ VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
32
VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
33
34
VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
35
+
36
+VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
37
+VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@
43
#include "exec/helper-proto.h"
44
#include "exec/cpu_ldst.h"
45
#include "exec/exec-all.h"
46
+#include "tcg/tcg.h"
47
48
static uint16_t mve_element_mask(CPUARMState *env)
49
{
50
@@ -XXX,XX +XXX,XX @@ DO_1OP(vrev64w, 8, uint64_t, wswap64)
51
#define DO_NOT(N) (~(N))
52
53
DO_1OP(vmvn, 8, uint64_t, DO_NOT)
54
+
55
+#define DO_ABS(N) ((N) < 0 ? -(N) : (N))
56
+#define DO_FABSH(N) ((N) & dup_const(MO_16, 0x7fff))
57
+#define DO_FABSS(N) ((N) & dup_const(MO_32, 0x7fffffff))
58
+
59
+DO_1OP(vabsb, 1, int8_t, DO_ABS)
60
+DO_1OP(vabsh, 2, int16_t, DO_ABS)
61
+DO_1OP(vabsw, 4, int32_t, DO_ABS)
62
+
63
+/* We can do these 64 bits at a time */
64
+DO_1OP(vfabsh, 8, uint64_t, DO_FABSH)
65
+DO_1OP(vfabss, 8, uint64_t, DO_FABSS)
66
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate-mve.c
69
+++ b/target/arm/translate-mve.c
70
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
71
72
DO_1OP(VCLZ, vclz)
73
DO_1OP(VCLS, vcls)
74
+DO_1OP(VABS, vabs)
75
76
static bool trans_VREV16(DisasContext *s, arg_1op *a)
77
{
78
@@ -XXX,XX +XXX,XX @@ static bool trans_VMVN(DisasContext *s, arg_1op *a)
79
{
80
return do_1op(s, a, gen_helper_mve_vmvn);
81
}
82
+
83
+static bool trans_VABS_fp(DisasContext *s, arg_1op *a)
84
+{
85
+ static MVEGenOneOpFn * const fns[] = {
86
+ NULL,
87
+ gen_helper_mve_vfabsh,
88
+ gen_helper_mve_vfabss,
89
+ NULL,
90
+ };
91
+ if (!dc_isar_feature(aa32_mve_fp, s)) {
92
+ return false;
93
+ }
94
+ return do_1op(s, a, fns[a->size]);
95
+}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
New patch
1
Implement the MVE VNEG insn (both integer and floating point forms).
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-9-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 6 ++++++
8
target/arm/mve.decode | 2 ++
9
target/arm/mve_helper.c | 12 ++++++++++++
10
target/arm/translate-mve.c | 15 +++++++++++++++
11
4 files changed, 35 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
DEF_HELPER_FLAGS_3(mve_vabsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vfabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vfabss, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_3(mve_vnegb, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/mve.decode
30
+++ b/target/arm/mve.decode
31
@@ -XXX,XX +XXX,XX @@ VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
32
33
VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
34
VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
35
+VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
36
+VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
37
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/mve_helper.c
40
+++ b/target/arm/mve_helper.c
41
@@ -XXX,XX +XXX,XX @@ DO_1OP(vabsw, 4, int32_t, DO_ABS)
42
/* We can do these 64 bits at a time */
43
DO_1OP(vfabsh, 8, uint64_t, DO_FABSH)
44
DO_1OP(vfabss, 8, uint64_t, DO_FABSS)
45
+
46
+#define DO_NEG(N) (-(N))
47
+#define DO_FNEGH(N) ((N) ^ dup_const(MO_16, 0x8000))
48
+#define DO_FNEGS(N) ((N) ^ dup_const(MO_32, 0x80000000))
49
+
50
+DO_1OP(vnegb, 1, int8_t, DO_NEG)
51
+DO_1OP(vnegh, 2, int16_t, DO_NEG)
52
+DO_1OP(vnegw, 4, int32_t, DO_NEG)
53
+
54
+/* We can do these 64 bits at a time */
55
+DO_1OP(vfnegh, 8, uint64_t, DO_FNEGH)
56
+DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
57
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate-mve.c
60
+++ b/target/arm/translate-mve.c
61
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
62
DO_1OP(VCLZ, vclz)
63
DO_1OP(VCLS, vcls)
64
DO_1OP(VABS, vabs)
65
+DO_1OP(VNEG, vneg)
66
67
static bool trans_VREV16(DisasContext *s, arg_1op *a)
68
{
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VABS_fp(DisasContext *s, arg_1op *a)
70
}
71
return do_1op(s, a, fns[a->size]);
72
}
73
+
74
+static bool trans_VNEG_fp(DisasContext *s, arg_1op *a)
75
+{
76
+ static MVEGenOneOpFn * const fns[] = {
77
+ NULL,
78
+ gen_helper_mve_vfnegh,
79
+ gen_helper_mve_vfnegs,
80
+ NULL,
81
+ };
82
+ if (!dc_isar_feature(aa32_mve_fp, s)) {
83
+ return false;
84
+ }
85
+ return do_1op(s, a, fns[a->size]);
86
+}
87
--
88
2.20.1
89
90
diff view generated by jsdifflib
New patch
1
The Arm MVE VDUP implementation would like to be able to emit code to
2
duplicate a byte or halfword value into an i32. We have code to do
3
this already in tcg-op-gvec.c, so all we need to do is make the
4
functions global.
1
5
6
For consistency with other functions made available to the frontends:
7
* we rename to tcg_gen_dup_*
8
* we expose both the _i32 and _i64 forms
9
* we provide the #define for a _tl form
10
11
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210617121628.20116-10-peter.maydell@linaro.org
15
---
16
include/tcg/tcg-op.h | 8 ++++++++
17
include/tcg/tcg.h | 1 -
18
tcg/tcg-op-gvec.c | 20 ++++++++++----------
19
3 files changed, 18 insertions(+), 11 deletions(-)
20
21
diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/tcg/tcg-op.h
24
+++ b/include/tcg/tcg-op.h
25
@@ -XXX,XX +XXX,XX @@ void tcg_gen_umin_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
26
void tcg_gen_umax_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
27
void tcg_gen_abs_i32(TCGv_i32, TCGv_i32);
28
29
+/* Replicate a value of size @vece from @in to all the lanes in @out */
30
+void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in);
31
+
32
static inline void tcg_gen_discard_i32(TCGv_i32 arg)
33
{
34
tcg_gen_op1_i32(INDEX_op_discard, arg);
35
@@ -XXX,XX +XXX,XX @@ void tcg_gen_umin_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
36
void tcg_gen_umax_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
37
void tcg_gen_abs_i64(TCGv_i64, TCGv_i64);
38
39
+/* Replicate a value of size @vece from @in to all the lanes in @out */
40
+void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in);
41
+
42
#if TCG_TARGET_REG_BITS == 64
43
static inline void tcg_gen_discard_i64(TCGv_i64 arg)
44
{
45
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
46
#define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i64
47
#define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i64
48
#define tcg_gen_dup_tl_vec tcg_gen_dup_i64_vec
49
+#define tcg_gen_dup_tl tcg_gen_dup_i64
50
#else
51
#define tcg_gen_movi_tl tcg_gen_movi_i32
52
#define tcg_gen_mov_tl tcg_gen_mov_i32
53
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
54
#define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i32
55
#define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i32
56
#define tcg_gen_dup_tl_vec tcg_gen_dup_i32_vec
57
+#define tcg_gen_dup_tl tcg_gen_dup_i32
58
#endif
59
60
#if UINTPTR_MAX == UINT32_MAX
61
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/include/tcg/tcg.h
64
+++ b/include/tcg/tcg.h
65
@@ -XXX,XX +XXX,XX @@ uint64_t dup_const(unsigned vece, uint64_t c);
66
: (qemu_build_not_reached_always(), 0)) \
67
: dup_const(VECE, C))
68
69
-
70
/*
71
* Memory helpers that will be used by TCG generated code.
72
*/
73
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/tcg/tcg-op-gvec.c
76
+++ b/tcg/tcg-op-gvec.c
77
@@ -XXX,XX +XXX,XX @@ uint64_t (dup_const)(unsigned vece, uint64_t c)
78
}
79
80
/* Duplicate IN into OUT as per VECE. */
81
-static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
82
+void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
83
{
84
switch (vece) {
85
case MO_8:
86
@@ -XXX,XX +XXX,XX @@ static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
87
}
88
}
89
90
-static void gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in)
91
+void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in)
92
{
93
switch (vece) {
94
case MO_8:
95
@@ -XXX,XX +XXX,XX @@ static void do_dup(unsigned vece, uint32_t dofs, uint32_t oprsz,
96
&& (vece != MO_32 || !check_size_impl(oprsz, 4))) {
97
t_64 = tcg_temp_new_i64();
98
tcg_gen_extu_i32_i64(t_64, in_32);
99
- gen_dup_i64(vece, t_64, t_64);
100
+ tcg_gen_dup_i64(vece, t_64, t_64);
101
} else {
102
t_32 = tcg_temp_new_i32();
103
- gen_dup_i32(vece, t_32, in_32);
104
+ tcg_gen_dup_i32(vece, t_32, in_32);
105
}
106
} else if (in_64) {
107
/* We are given a 64-bit variable input. */
108
t_64 = tcg_temp_new_i64();
109
- gen_dup_i64(vece, t_64, in_64);
110
+ tcg_gen_dup_i64(vece, t_64, in_64);
111
} else {
112
/* We are given a constant input. */
113
/* For 64-bit hosts, use 64-bit constants for "simple" constants
114
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
115
} else if (g->fni8 && check_size_impl(oprsz, 8)) {
116
TCGv_i64 t64 = tcg_temp_new_i64();
117
118
- gen_dup_i64(g->vece, t64, c);
119
+ tcg_gen_dup_i64(g->vece, t64, c);
120
expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8);
121
tcg_temp_free_i64(t64);
122
} else if (g->fni4 && check_size_impl(oprsz, 4)) {
123
TCGv_i32 t32 = tcg_temp_new_i32();
124
125
tcg_gen_extrl_i64_i32(t32, c);
126
- gen_dup_i32(g->vece, t32, t32);
127
+ tcg_gen_dup_i32(g->vece, t32, t32);
128
expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4);
129
tcg_temp_free_i32(t32);
130
} else {
131
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
132
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
133
{
134
TCGv_i64 tmp = tcg_temp_new_i64();
135
- gen_dup_i64(vece, tmp, c);
136
+ tcg_gen_dup_i64(vece, tmp, c);
137
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands);
138
tcg_temp_free_i64(tmp);
139
}
140
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
141
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
142
{
143
TCGv_i64 tmp = tcg_temp_new_i64();
144
- gen_dup_i64(vece, tmp, c);
145
+ tcg_gen_dup_i64(vece, tmp, c);
146
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors);
147
tcg_temp_free_i64(tmp);
148
}
149
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
150
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
151
{
152
TCGv_i64 tmp = tcg_temp_new_i64();
153
- gen_dup_i64(vece, tmp, c);
154
+ tcg_gen_dup_i64(vece, tmp, c);
155
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors);
156
tcg_temp_free_i64(tmp);
157
}
158
--
159
2.20.1
160
161
diff view generated by jsdifflib
New patch
1
Implement the MVE VDUP insn, which duplicates a value from
2
a general-purpose register into every lane of a vector
3
register (subject to predication).
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210617121628.20116-11-peter.maydell@linaro.org
8
---
9
target/arm/helper-mve.h | 2 ++
10
target/arm/mve.decode | 10 ++++++++++
11
target/arm/mve_helper.c | 16 ++++++++++++++++
12
target/arm/translate-mve.c | 27 +++++++++++++++++++++++++++
13
4 files changed, 55 insertions(+)
14
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-mve.h
18
+++ b/target/arm/helper-mve.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
20
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
21
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
22
23
+DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
24
+
25
DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@
33
34
%qd 22:1 13:3
35
%qm 5:1 1:3
36
+%qn 7:1 17:3
37
38
&vldr_vstr rn qd imm p a w size l u
39
&1op qd qm size
40
@@ -XXX,XX +XXX,XX @@ VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
41
VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
42
VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
43
VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
44
+
45
+&vdup qd rt size
46
+# Qd is in the fields usually named Qn
47
+@vdup .... .... . . .. ... . rt:4 .... . . . . .... qd=%qn &vdup
48
+
49
+# B and E bits encode size, which we decode here to the usual size values
50
+VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
51
+VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
52
+VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
53
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/mve_helper.c
56
+++ b/target/arm/mve_helper.c
57
@@ -XXX,XX +XXX,XX @@ static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
58
uint64_t *: mergemask_uq, \
59
int64_t *: mergemask_sq)(D, R, M)
60
61
+void HELPER(mve_vdup)(CPUARMState *env, void *vd, uint32_t val)
62
+{
63
+ /*
64
+ * The generated code already replicated an 8 or 16 bit constant
65
+ * into the 32-bit value, so we only need to write the 32-bit
66
+ * value to all elements of the Qreg, allowing for predication.
67
+ */
68
+ uint32_t *d = vd;
69
+ uint16_t mask = mve_element_mask(env);
70
+ unsigned e;
71
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) {
72
+ mergemask(&d[H4(e)], val, mask);
73
+ }
74
+ mve_advance_vpt(env);
75
+}
76
+
77
#define DO_1OP(OP, ESIZE, TYPE, FN) \
78
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
79
{ \
80
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate-mve.c
83
+++ b/target/arm/translate-mve.c
84
@@ -XXX,XX +XXX,XX @@ DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
85
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
86
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
87
88
+static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
89
+{
90
+ TCGv_ptr qd;
91
+ TCGv_i32 rt;
92
+
93
+ if (!dc_isar_feature(aa32_mve, s) ||
94
+ !mve_check_qreg_bank(s, a->qd)) {
95
+ return false;
96
+ }
97
+ if (a->rt == 13 || a->rt == 15) {
98
+ /* UNPREDICTABLE; we choose to UNDEF */
99
+ return false;
100
+ }
101
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
102
+ return true;
103
+ }
104
+
105
+ qd = mve_qreg_ptr(a->qd);
106
+ rt = load_reg(s, a->rt);
107
+ tcg_gen_dup_i32(a->size, rt, rt);
108
+ gen_helper_mve_vdup(cpu_env, qd, rt);
109
+ tcg_temp_free_ptr(qd);
110
+ tcg_temp_free_i32(rt);
111
+ mve_update_eci(s);
112
+ return true;
113
+}
114
+
115
static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
116
{
117
TCGv_ptr qd, qm;
118
--
119
2.20.1
120
121
diff view generated by jsdifflib
New patch
1
Implement the MVE vector logical operations operating
2
on two registers.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-12-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 6 ++++++
9
target/arm/mve.decode | 9 +++++++++
10
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 37 +++++++++++++++++++++++++++++++++++++
12
4 files changed, 78 insertions(+)
13
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vand, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vbic, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@
33
34
&vldr_vstr rn qd imm p a w size l u
35
&1op qd qm size
36
+&2op qd qm qn size
37
38
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
39
# Note that both Rn and Qd are 3 bits only (no D bit)
40
@@ -XXX,XX +XXX,XX @@
41
42
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
43
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
44
+@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
45
46
# Vector loads and stores
47
48
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
49
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
50
size=2 p=1
51
52
+# Vector 2-op
53
+VAND 1110 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
54
+VBIC 1110 1111 0 . 01 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
55
+VORR 1110 1111 0 . 10 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
56
+VORN 1110 1111 0 . 11 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
57
+VEOR 1111 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
58
+
59
# Vector miscellaneous
60
61
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
62
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/mve_helper.c
65
+++ b/target/arm/mve_helper.c
66
@@ -XXX,XX +XXX,XX @@ DO_1OP(vnegw, 4, int32_t, DO_NEG)
67
/* We can do these 64 bits at a time */
68
DO_1OP(vfnegh, 8, uint64_t, DO_FNEGH)
69
DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
70
+
71
+#define DO_2OP(OP, ESIZE, TYPE, FN) \
72
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
73
+ void *vd, void *vn, void *vm) \
74
+ { \
75
+ TYPE *d = vd, *n = vn, *m = vm; \
76
+ uint16_t mask = mve_element_mask(env); \
77
+ unsigned e; \
78
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
79
+ mergemask(&d[H##ESIZE(e)], \
80
+ FN(n[H##ESIZE(e)], m[H##ESIZE(e)]), mask); \
81
+ } \
82
+ mve_advance_vpt(env); \
83
+ }
84
+
85
+#define DO_AND(N, M) ((N) & (M))
86
+#define DO_BIC(N, M) ((N) & ~(M))
87
+#define DO_ORR(N, M) ((N) | (M))
88
+#define DO_ORN(N, M) ((N) | ~(M))
89
+#define DO_EOR(N, M) ((N) ^ (M))
90
+
91
+DO_2OP(vand, 8, uint64_t, DO_AND)
92
+DO_2OP(vbic, 8, uint64_t, DO_BIC)
93
+DO_2OP(vorr, 8, uint64_t, DO_ORR)
94
+DO_2OP(vorn, 8, uint64_t, DO_ORN)
95
+DO_2OP(veor, 8, uint64_t, DO_EOR)
96
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate-mve.c
99
+++ b/target/arm/translate-mve.c
100
@@ -XXX,XX +XXX,XX @@
101
102
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
103
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
104
+typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
105
106
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
107
static inline long mve_qreg_offset(unsigned reg)
108
@@ -XXX,XX +XXX,XX @@ static bool trans_VNEG_fp(DisasContext *s, arg_1op *a)
109
}
110
return do_1op(s, a, fns[a->size]);
111
}
112
+
113
+static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn)
114
+{
115
+ TCGv_ptr qd, qn, qm;
116
+
117
+ if (!dc_isar_feature(aa32_mve, s) ||
118
+ !mve_check_qreg_bank(s, a->qd | a->qn | a->qm) ||
119
+ !fn) {
120
+ return false;
121
+ }
122
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
123
+ return true;
124
+ }
125
+
126
+ qd = mve_qreg_ptr(a->qd);
127
+ qn = mve_qreg_ptr(a->qn);
128
+ qm = mve_qreg_ptr(a->qm);
129
+ fn(cpu_env, qd, qn, qm);
130
+ tcg_temp_free_ptr(qd);
131
+ tcg_temp_free_ptr(qn);
132
+ tcg_temp_free_ptr(qm);
133
+ mve_update_eci(s);
134
+ return true;
135
+}
136
+
137
+#define DO_LOGIC(INSN, HELPER) \
138
+ static bool trans_##INSN(DisasContext *s, arg_2op *a) \
139
+ { \
140
+ return do_2op(s, a, HELPER); \
141
+ }
142
+
143
+DO_LOGIC(VAND, gen_helper_mve_vand)
144
+DO_LOGIC(VBIC, gen_helper_mve_vbic)
145
+DO_LOGIC(VORR, gen_helper_mve_vorr)
146
+DO_LOGIC(VORN, gen_helper_mve_vorn)
147
+DO_LOGIC(VEOR, gen_helper_mve_veor)
148
--
149
2.20.1
150
151
diff view generated by jsdifflib
New patch
1
Implement the MVE VADD, VSUB and VMUL insns.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-13-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 12 ++++++++++++
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 16 ++++++++++++++++
11
4 files changed, 47 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vbic, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_4(mve_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vaddw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+
26
+DEF_HELPER_FLAGS_4(mve_vsubb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vsubh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vsubw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vmulb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vmulh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vmulw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@
38
39
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
40
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
41
+@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
42
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
43
44
# Vector loads and stores
45
@@ -XXX,XX +XXX,XX @@ VORR 1110 1111 0 . 10 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
46
VORN 1110 1111 0 . 11 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
47
VEOR 1111 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
48
49
+VADD 1110 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
50
+VSUB 1111 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
51
+VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
52
+
53
# Vector miscellaneous
54
55
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
56
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/mve_helper.c
59
+++ b/target/arm/mve_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
61
mve_advance_vpt(env); \
62
}
63
64
+/* provide unsigned 2-op helpers for all sizes */
65
+#define DO_2OP_U(OP, FN) \
66
+ DO_2OP(OP##b, 1, uint8_t, FN) \
67
+ DO_2OP(OP##h, 2, uint16_t, FN) \
68
+ DO_2OP(OP##w, 4, uint32_t, FN)
69
+
70
#define DO_AND(N, M) ((N) & (M))
71
#define DO_BIC(N, M) ((N) & ~(M))
72
#define DO_ORR(N, M) ((N) | (M))
73
@@ -XXX,XX +XXX,XX @@ DO_2OP(vbic, 8, uint64_t, DO_BIC)
74
DO_2OP(vorr, 8, uint64_t, DO_ORR)
75
DO_2OP(vorn, 8, uint64_t, DO_ORN)
76
DO_2OP(veor, 8, uint64_t, DO_EOR)
77
+
78
+#define DO_ADD(N, M) ((N) + (M))
79
+#define DO_SUB(N, M) ((N) - (M))
80
+#define DO_MUL(N, M) ((N) * (M))
81
+
82
+DO_2OP_U(vadd, DO_ADD)
83
+DO_2OP_U(vsub, DO_SUB)
84
+DO_2OP_U(vmul, DO_MUL)
85
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/translate-mve.c
88
+++ b/target/arm/translate-mve.c
89
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VBIC, gen_helper_mve_vbic)
90
DO_LOGIC(VORR, gen_helper_mve_vorr)
91
DO_LOGIC(VORN, gen_helper_mve_vorn)
92
DO_LOGIC(VEOR, gen_helper_mve_veor)
93
+
94
+#define DO_2OP(INSN, FN) \
95
+ static bool trans_##INSN(DisasContext *s, arg_2op *a) \
96
+ { \
97
+ static MVEGenTwoOpFn * const fns[] = { \
98
+ gen_helper_mve_##FN##b, \
99
+ gen_helper_mve_##FN##h, \
100
+ gen_helper_mve_##FN##w, \
101
+ NULL, \
102
+ }; \
103
+ return do_2op(s, a, fns[a->size]); \
104
+ }
105
+
106
+DO_2OP(VADD, vadd)
107
+DO_2OP(VSUB, vsub)
108
+DO_2OP(VMUL, vmul)
109
--
110
2.20.1
111
112
diff view generated by jsdifflib
New patch
1
Implement the MVE VMULH insn, which performs a vector
2
multiply and returns the high half of the result.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-14-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 7 +++++++
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 38 insertions(+)
13
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vsubw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vmulb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vmulh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
DEF_HELPER_FLAGS_4(mve_vmulw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vmulhsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vmulhsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@ VADD 1110 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
34
VSUB 1111 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
35
VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
36
37
+VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
38
+VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
39
+
40
# Vector miscellaneous
41
42
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
43
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/mve_helper.c
46
+++ b/target/arm/mve_helper.c
47
@@ -XXX,XX +XXX,XX @@ DO_2OP(veor, 8, uint64_t, DO_EOR)
48
DO_2OP_U(vadd, DO_ADD)
49
DO_2OP_U(vsub, DO_SUB)
50
DO_2OP_U(vmul, DO_MUL)
51
+
52
+/*
53
+ * Because the computation type is at least twice as large as required,
54
+ * these work for both signed and unsigned source types.
55
+ */
56
+static inline uint8_t do_mulh_b(int32_t n, int32_t m)
57
+{
58
+ return (n * m) >> 8;
59
+}
60
+
61
+static inline uint16_t do_mulh_h(int32_t n, int32_t m)
62
+{
63
+ return (n * m) >> 16;
64
+}
65
+
66
+static inline uint32_t do_mulh_w(int64_t n, int64_t m)
67
+{
68
+ return (n * m) >> 32;
69
+}
70
+
71
+DO_2OP(vmulhsb, 1, int8_t, do_mulh_b)
72
+DO_2OP(vmulhsh, 2, int16_t, do_mulh_h)
73
+DO_2OP(vmulhsw, 4, int32_t, do_mulh_w)
74
+DO_2OP(vmulhub, 1, uint8_t, do_mulh_b)
75
+DO_2OP(vmulhuh, 2, uint16_t, do_mulh_h)
76
+DO_2OP(vmulhuw, 4, uint32_t, do_mulh_w)
77
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/translate-mve.c
80
+++ b/target/arm/translate-mve.c
81
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VEOR, gen_helper_mve_veor)
82
DO_2OP(VADD, vadd)
83
DO_2OP(VSUB, vsub)
84
DO_2OP(VMUL, vmul)
85
+DO_2OP(VMULH_S, vmulhs)
86
+DO_2OP(VMULH_U, vmulhu)
87
--
88
2.20.1
89
90
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement the MVE VRMULH insn, which performs a rounding multiply
2
and then returns the high half.
2
3
3
Allwinner System-on-Chips usually contain a Real Time Clock (RTC)
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
for non-volatile system date and time keeping. This commit adds a generic
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Allwinner RTC device that supports the RTC devices found in Allwinner SoC
6
Message-id: 20210617121628.20116-15-peter.maydell@linaro.org
6
family sun4i (A10), sun7i (A20) and sun6i and newer (A31, H2+, H3, etc).
7
---
7
The following RTC functionality and features are implemented:
8
target/arm/helper-mve.h | 7 +++++++
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 22 ++++++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 34 insertions(+)
8
13
9
* Year-Month-Day read/write
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
10
* Hour-Minute-Second read/write
11
* General Purpose storage
12
13
The following boards are extended with the RTC device:
14
15
* Cubieboard (hw/arm/cubieboard.c)
16
* Orange Pi PC (hw/arm/orangepi.c)
17
18
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
20
Message-id: 20200311221854.30370-13-nieklinnenbank@gmail.com
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/rtc/Makefile.objs | 1 +
24
include/hw/arm/allwinner-a10.h | 2 +
25
include/hw/arm/allwinner-h3.h | 3 +
26
include/hw/rtc/allwinner-rtc.h | 134 +++++++++++
27
hw/arm/allwinner-a10.c | 8 +
28
hw/arm/allwinner-h3.c | 9 +-
29
hw/rtc/allwinner-rtc.c | 411 +++++++++++++++++++++++++++++++++
30
hw/rtc/trace-events | 4 +
31
8 files changed, 571 insertions(+), 1 deletion(-)
32
create mode 100644 include/hw/rtc/allwinner-rtc.h
33
create mode 100644 hw/rtc/allwinner-rtc.c
34
35
diff --git a/hw/rtc/Makefile.objs b/hw/rtc/Makefile.objs
36
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/rtc/Makefile.objs
16
--- a/target/arm/helper-mve.h
38
+++ b/hw/rtc/Makefile.objs
17
+++ b/target/arm/helper-mve.h
39
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
40
common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
19
DEF_HELPER_FLAGS_4(mve_vmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
41
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_rtc.o
20
DEF_HELPER_FLAGS_4(mve_vmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
42
common-obj-$(CONFIG_GOLDFISH_RTC) += goldfish_rtc.o
21
DEF_HELPER_FLAGS_4(mve_vmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
43
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-rtc.o
22
+
44
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
23
+DEF_HELPER_FLAGS_4(mve_vrmulhsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vrmulhsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vrmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vrmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vrmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vrmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
45
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/allwinner-a10.h
31
--- a/target/arm/mve.decode
47
+++ b/include/hw/arm/allwinner-a10.h
32
+++ b/target/arm/mve.decode
48
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
49
#include "hw/ide/ahci.h"
34
VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
50
#include "hw/usb/hcd-ohci.h"
35
VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
51
#include "hw/usb/hcd-ehci.h"
36
52
+#include "hw/rtc/allwinner-rtc.h"
37
+VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
53
38
+VRMULH_U 111 1 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
54
#include "target/arm/cpu.h"
39
+
55
40
# Vector miscellaneous
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
41
57
AwEmacState emac;
42
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
58
AllwinnerAHCIState sata;
43
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
59
AwSdHostState mmc0;
60
+ AwRtcState rtc;
61
MemoryRegion sram_a;
62
EHCISysBusState ehci[AW_A10_NUM_USB];
63
OHCISysBusState ohci[AW_A10_NUM_USB];
64
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
65
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
66
--- a/include/hw/arm/allwinner-h3.h
45
--- a/target/arm/mve_helper.c
67
+++ b/include/hw/arm/allwinner-h3.h
46
+++ b/target/arm/mve_helper.c
68
@@ -XXX,XX +XXX,XX @@
47
@@ -XXX,XX +XXX,XX @@ static inline uint32_t do_mulh_w(int64_t n, int64_t m)
69
#include "hw/misc/allwinner-sid.h"
48
return (n * m) >> 32;
70
#include "hw/sd/allwinner-sdhost.h"
71
#include "hw/net/allwinner-sun8i-emac.h"
72
+#include "hw/rtc/allwinner-rtc.h"
73
#include "target/arm/cpu.h"
74
#include "sysemu/block-backend.h"
75
76
@@ -XXX,XX +XXX,XX @@ enum {
77
AW_H3_GIC_CPU,
78
AW_H3_GIC_HYP,
79
AW_H3_GIC_VCPU,
80
+ AW_H3_RTC,
81
AW_H3_CPUCFG,
82
AW_H3_SDRAM
83
};
84
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
85
AwSidState sid;
86
AwSdHostState mmc0;
87
AwSun8iEmacState emac;
88
+ AwRtcState rtc;
89
GICState gic;
90
MemoryRegion sram_a1;
91
MemoryRegion sram_a2;
92
diff --git a/include/hw/rtc/allwinner-rtc.h b/include/hw/rtc/allwinner-rtc.h
93
new file mode 100644
94
index XXXXXXX..XXXXXXX
95
--- /dev/null
96
+++ b/include/hw/rtc/allwinner-rtc.h
97
@@ -XXX,XX +XXX,XX @@
98
+/*
99
+ * Allwinner Real Time Clock emulation
100
+ *
101
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
102
+ *
103
+ * This program is free software: you can redistribute it and/or modify
104
+ * it under the terms of the GNU General Public License as published by
105
+ * the Free Software Foundation, either version 2 of the License, or
106
+ * (at your option) any later version.
107
+ *
108
+ * This program is distributed in the hope that it will be useful,
109
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
110
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
111
+ * GNU General Public License for more details.
112
+ *
113
+ * You should have received a copy of the GNU General Public License
114
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
115
+ */
116
+
117
+#ifndef HW_MISC_ALLWINNER_RTC_H
118
+#define HW_MISC_ALLWINNER_RTC_H
119
+
120
+#include "qom/object.h"
121
+#include "hw/sysbus.h"
122
+
123
+/**
124
+ * Constants
125
+ * @{
126
+ */
127
+
128
+/** Highest register address used by RTC device */
129
+#define AW_RTC_REGS_MAXADDR (0x200)
130
+
131
+/** Total number of known registers */
132
+#define AW_RTC_REGS_NUM (AW_RTC_REGS_MAXADDR / sizeof(uint32_t))
133
+
134
+/** @} */
135
+
136
+/**
137
+ * Object model types
138
+ * @{
139
+ */
140
+
141
+/** Generic Allwinner RTC device (abstract) */
142
+#define TYPE_AW_RTC "allwinner-rtc"
143
+
144
+/** Allwinner RTC sun4i family (A10, A12) */
145
+#define TYPE_AW_RTC_SUN4I TYPE_AW_RTC "-sun4i"
146
+
147
+/** Allwinner RTC sun6i family and newer (A31, H2+, H3, etc) */
148
+#define TYPE_AW_RTC_SUN6I TYPE_AW_RTC "-sun6i"
149
+
150
+/** Allwinner RTC sun7i family (A20) */
151
+#define TYPE_AW_RTC_SUN7I TYPE_AW_RTC "-sun7i"
152
+
153
+/** @} */
154
+
155
+/**
156
+ * Object model macros
157
+ * @{
158
+ */
159
+
160
+#define AW_RTC(obj) \
161
+ OBJECT_CHECK(AwRtcState, (obj), TYPE_AW_RTC)
162
+#define AW_RTC_CLASS(klass) \
163
+ OBJECT_CLASS_CHECK(AwRtcClass, (klass), TYPE_AW_RTC)
164
+#define AW_RTC_GET_CLASS(obj) \
165
+ OBJECT_GET_CLASS(AwRtcClass, (obj), TYPE_AW_RTC)
166
+
167
+/** @} */
168
+
169
+/**
170
+ * Allwinner RTC per-object instance state.
171
+ */
172
+typedef struct AwRtcState {
173
+ /*< private >*/
174
+ SysBusDevice parent_obj;
175
+ /*< public >*/
176
+
177
+ /**
178
+ * Actual year represented by the device when year counter is zero
179
+ *
180
+ * Can be overridden by the user using the corresponding 'base-year'
181
+ * property. The base year used by the target OS driver can vary, for
182
+ * example the Linux driver for sun6i uses 1970 while NetBSD uses 2000.
183
+ */
184
+ int base_year;
185
+
186
+ /** Maps I/O registers in physical memory */
187
+ MemoryRegion iomem;
188
+
189
+ /** Array of hardware registers */
190
+ uint32_t regs[AW_RTC_REGS_NUM];
191
+
192
+} AwRtcState;
193
+
194
+/**
195
+ * Allwinner RTC class-level struct.
196
+ *
197
+ * This struct is filled by each sunxi device specific code
198
+ * such that the generic code can use this struct to support
199
+ * all devices.
200
+ */
201
+typedef struct AwRtcClass {
202
+ /*< private >*/
203
+ SysBusDeviceClass parent_class;
204
+ /*< public >*/
205
+
206
+ /** Defines device specific register map */
207
+ const uint8_t *regmap;
208
+
209
+ /** Size of the regmap in bytes */
210
+ size_t regmap_size;
211
+
212
+ /**
213
+ * Read device specific register
214
+ *
215
+ * @offset: register offset to read
216
+ * @return true if register read successful, false otherwise
217
+ */
218
+ bool (*read)(AwRtcState *s, uint32_t offset);
219
+
220
+ /**
221
+ * Write device specific register
222
+ *
223
+ * @offset: register offset to write
224
+ * @data: value to set in register
225
+ * @return true if register write successful, false otherwise
226
+ */
227
+ bool (*write)(AwRtcState *s, uint32_t offset, uint32_t data);
228
+
229
+} AwRtcClass;
230
+
231
+#endif /* HW_MISC_ALLWINNER_RTC_H */
232
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/hw/arm/allwinner-a10.c
235
+++ b/hw/arm/allwinner-a10.c
236
@@ -XXX,XX +XXX,XX @@
237
#define AW_A10_EHCI_BASE 0x01c14000
238
#define AW_A10_OHCI_BASE 0x01c14400
239
#define AW_A10_SATA_BASE 0x01c18000
240
+#define AW_A10_RTC_BASE 0x01c20d00
241
242
static void aw_a10_init(Object *obj)
243
{
244
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
245
246
sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
247
TYPE_AW_SDHOST_SUN4I);
248
+
249
+ sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc),
250
+ TYPE_AW_RTC_SUN4I);
251
}
49
}
252
50
253
static void aw_a10_realize(DeviceState *dev, Error **errp)
51
+static inline uint8_t do_rmulh_b(int32_t n, int32_t m)
254
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
255
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32));
256
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
257
"sd-bus", &error_abort);
258
+
259
+ /* RTC */
260
+ qdev_init_nofail(DEVICE(&s->rtc));
261
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->rtc), 0, AW_A10_RTC_BASE, 10);
262
}
263
264
static void aw_a10_class_init(ObjectClass *oc, void *data)
265
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/hw/arm/allwinner-h3.c
268
+++ b/hw/arm/allwinner-h3.c
269
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
270
[AW_H3_GIC_CPU] = 0x01c82000,
271
[AW_H3_GIC_HYP] = 0x01c84000,
272
[AW_H3_GIC_VCPU] = 0x01c86000,
273
+ [AW_H3_RTC] = 0x01f00000,
274
[AW_H3_CPUCFG] = 0x01f01c00,
275
[AW_H3_SDRAM] = 0x40000000
276
};
277
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
278
{ "csi", 0x01cb0000, 320 * KiB },
279
{ "tve", 0x01e00000, 64 * KiB },
280
{ "hdmi", 0x01ee0000, 128 * KiB },
281
- { "rtc", 0x01f00000, 1 * KiB },
282
{ "r_timer", 0x01f00800, 1 * KiB },
283
{ "r_intc", 0x01f00c00, 1 * KiB },
284
{ "r_wdog", 0x01f01000, 1 * KiB },
285
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
286
"ram-addr", &error_abort);
287
object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
288
"ram-size", &error_abort);
289
+
290
+ sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc),
291
+ TYPE_AW_RTC_SUN6I);
292
}
293
294
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
295
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
296
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1, s->memmap[AW_H3_DRAMCTL]);
297
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2, s->memmap[AW_H3_DRAMPHY]);
298
299
+ /* RTC */
300
+ qdev_init_nofail(DEVICE(&s->rtc));
301
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, s->memmap[AW_H3_RTC]);
302
+
303
/* Unimplemented devices */
304
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
305
create_unimplemented_device(unimplemented[i].device_name,
306
diff --git a/hw/rtc/allwinner-rtc.c b/hw/rtc/allwinner-rtc.c
307
new file mode 100644
308
index XXXXXXX..XXXXXXX
309
--- /dev/null
310
+++ b/hw/rtc/allwinner-rtc.c
311
@@ -XXX,XX +XXX,XX @@
312
+/*
313
+ * Allwinner Real Time Clock emulation
314
+ *
315
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
316
+ *
317
+ * This program is free software: you can redistribute it and/or modify
318
+ * it under the terms of the GNU General Public License as published by
319
+ * the Free Software Foundation, either version 2 of the License, or
320
+ * (at your option) any later version.
321
+ *
322
+ * This program is distributed in the hope that it will be useful,
323
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
324
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
325
+ * GNU General Public License for more details.
326
+ *
327
+ * You should have received a copy of the GNU General Public License
328
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
329
+ */
330
+
331
+#include "qemu/osdep.h"
332
+#include "qemu/units.h"
333
+#include "hw/sysbus.h"
334
+#include "migration/vmstate.h"
335
+#include "qemu/log.h"
336
+#include "qemu/module.h"
337
+#include "qemu-common.h"
338
+#include "hw/qdev-properties.h"
339
+#include "hw/rtc/allwinner-rtc.h"
340
+#include "trace.h"
341
+
342
+/* RTC registers */
343
+enum {
344
+ REG_LOSC = 1, /* Low Oscillator Control */
345
+ REG_YYMMDD, /* RTC Year-Month-Day */
346
+ REG_HHMMSS, /* RTC Hour-Minute-Second */
347
+ REG_ALARM1_WKHHMMSS, /* Alarm1 Week Hour-Minute-Second */
348
+ REG_ALARM1_EN, /* Alarm1 Enable */
349
+ REG_ALARM1_IRQ_EN, /* Alarm1 IRQ Enable */
350
+ REG_ALARM1_IRQ_STA, /* Alarm1 IRQ Status */
351
+ REG_GP0, /* General Purpose Register 0 */
352
+ REG_GP1, /* General Purpose Register 1 */
353
+ REG_GP2, /* General Purpose Register 2 */
354
+ REG_GP3, /* General Purpose Register 3 */
355
+
356
+ /* sun4i registers */
357
+ REG_ALARM1_DDHHMMSS, /* Alarm1 Day Hour-Minute-Second */
358
+ REG_CPUCFG, /* CPU Configuration Register */
359
+
360
+ /* sun6i registers */
361
+ REG_LOSC_AUTOSTA, /* LOSC Auto Switch Status */
362
+ REG_INT_OSC_PRE, /* Internal OSC Clock Prescaler */
363
+ REG_ALARM0_COUNTER, /* Alarm0 Counter */
364
+ REG_ALARM0_CUR_VLU, /* Alarm0 Counter Current Value */
365
+ REG_ALARM0_ENABLE, /* Alarm0 Enable */
366
+ REG_ALARM0_IRQ_EN, /* Alarm0 IRQ Enable */
367
+ REG_ALARM0_IRQ_STA, /* Alarm0 IRQ Status */
368
+ REG_ALARM_CONFIG, /* Alarm Config */
369
+ REG_LOSC_OUT_GATING, /* LOSC Output Gating Register */
370
+ REG_GP4, /* General Purpose Register 4 */
371
+ REG_GP5, /* General Purpose Register 5 */
372
+ REG_GP6, /* General Purpose Register 6 */
373
+ REG_GP7, /* General Purpose Register 7 */
374
+ REG_RTC_DBG, /* RTC Debug Register */
375
+ REG_GPL_HOLD_OUT, /* GPL Hold Output Register */
376
+ REG_VDD_RTC, /* VDD RTC Regulate Register */
377
+ REG_IC_CHARA, /* IC Characteristics Register */
378
+};
379
+
380
+/* RTC register flags */
381
+enum {
382
+ REG_LOSC_YMD = (1 << 7),
383
+ REG_LOSC_HMS = (1 << 8),
384
+};
385
+
386
+/* RTC sun4i register map (offset to name) */
387
+const uint8_t allwinner_rtc_sun4i_regmap[] = {
388
+ [0x0000] = REG_LOSC,
389
+ [0x0004] = REG_YYMMDD,
390
+ [0x0008] = REG_HHMMSS,
391
+ [0x000C] = REG_ALARM1_DDHHMMSS,
392
+ [0x0010] = REG_ALARM1_WKHHMMSS,
393
+ [0x0014] = REG_ALARM1_EN,
394
+ [0x0018] = REG_ALARM1_IRQ_EN,
395
+ [0x001C] = REG_ALARM1_IRQ_STA,
396
+ [0x0020] = REG_GP0,
397
+ [0x0024] = REG_GP1,
398
+ [0x0028] = REG_GP2,
399
+ [0x002C] = REG_GP3,
400
+ [0x003C] = REG_CPUCFG,
401
+};
402
+
403
+/* RTC sun6i register map (offset to name) */
404
+const uint8_t allwinner_rtc_sun6i_regmap[] = {
405
+ [0x0000] = REG_LOSC,
406
+ [0x0004] = REG_LOSC_AUTOSTA,
407
+ [0x0008] = REG_INT_OSC_PRE,
408
+ [0x0010] = REG_YYMMDD,
409
+ [0x0014] = REG_HHMMSS,
410
+ [0x0020] = REG_ALARM0_COUNTER,
411
+ [0x0024] = REG_ALARM0_CUR_VLU,
412
+ [0x0028] = REG_ALARM0_ENABLE,
413
+ [0x002C] = REG_ALARM0_IRQ_EN,
414
+ [0x0030] = REG_ALARM0_IRQ_STA,
415
+ [0x0040] = REG_ALARM1_WKHHMMSS,
416
+ [0x0044] = REG_ALARM1_EN,
417
+ [0x0048] = REG_ALARM1_IRQ_EN,
418
+ [0x004C] = REG_ALARM1_IRQ_STA,
419
+ [0x0050] = REG_ALARM_CONFIG,
420
+ [0x0060] = REG_LOSC_OUT_GATING,
421
+ [0x0100] = REG_GP0,
422
+ [0x0104] = REG_GP1,
423
+ [0x0108] = REG_GP2,
424
+ [0x010C] = REG_GP3,
425
+ [0x0110] = REG_GP4,
426
+ [0x0114] = REG_GP5,
427
+ [0x0118] = REG_GP6,
428
+ [0x011C] = REG_GP7,
429
+ [0x0170] = REG_RTC_DBG,
430
+ [0x0180] = REG_GPL_HOLD_OUT,
431
+ [0x0190] = REG_VDD_RTC,
432
+ [0x01F0] = REG_IC_CHARA,
433
+};
434
+
435
+static bool allwinner_rtc_sun4i_read(AwRtcState *s, uint32_t offset)
436
+{
52
+{
437
+ /* no sun4i specific registers currently implemented */
53
+ return (n * m + (1U << 7)) >> 8;
438
+ return false;
439
+}
54
+}
440
+
55
+
441
+static bool allwinner_rtc_sun4i_write(AwRtcState *s, uint32_t offset,
56
+static inline uint16_t do_rmulh_h(int32_t n, int32_t m)
442
+ uint32_t data)
443
+{
57
+{
444
+ /* no sun4i specific registers currently implemented */
58
+ return (n * m + (1U << 15)) >> 16;
445
+ return false;
446
+}
59
+}
447
+
60
+
448
+static bool allwinner_rtc_sun6i_read(AwRtcState *s, uint32_t offset)
61
+static inline uint32_t do_rmulh_w(int64_t n, int64_t m)
449
+{
62
+{
450
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
63
+ return (n * m + (1U << 31)) >> 32;
451
+
452
+ switch (c->regmap[offset]) {
453
+ case REG_GP4: /* General Purpose Register 4 */
454
+ case REG_GP5: /* General Purpose Register 5 */
455
+ case REG_GP6: /* General Purpose Register 6 */
456
+ case REG_GP7: /* General Purpose Register 7 */
457
+ return true;
458
+ default:
459
+ break;
460
+ }
461
+ return false;
462
+}
64
+}
463
+
65
+
464
+static bool allwinner_rtc_sun6i_write(AwRtcState *s, uint32_t offset,
66
DO_2OP(vmulhsb, 1, int8_t, do_mulh_b)
465
+ uint32_t data)
67
DO_2OP(vmulhsh, 2, int16_t, do_mulh_h)
466
+{
68
DO_2OP(vmulhsw, 4, int32_t, do_mulh_w)
467
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
69
DO_2OP(vmulhub, 1, uint8_t, do_mulh_b)
70
DO_2OP(vmulhuh, 2, uint16_t, do_mulh_h)
71
DO_2OP(vmulhuw, 4, uint32_t, do_mulh_w)
468
+
72
+
469
+ switch (c->regmap[offset]) {
73
+DO_2OP(vrmulhsb, 1, int8_t, do_rmulh_b)
470
+ case REG_GP4: /* General Purpose Register 4 */
74
+DO_2OP(vrmulhsh, 2, int16_t, do_rmulh_h)
471
+ case REG_GP5: /* General Purpose Register 5 */
75
+DO_2OP(vrmulhsw, 4, int32_t, do_rmulh_w)
472
+ case REG_GP6: /* General Purpose Register 6 */
76
+DO_2OP(vrmulhub, 1, uint8_t, do_rmulh_b)
473
+ case REG_GP7: /* General Purpose Register 7 */
77
+DO_2OP(vrmulhuh, 2, uint16_t, do_rmulh_h)
474
+ return true;
78
+DO_2OP(vrmulhuw, 4, uint32_t, do_rmulh_w)
475
+ default:
79
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
476
+ break;
477
+ }
478
+ return false;
479
+}
480
+
481
+static uint64_t allwinner_rtc_read(void *opaque, hwaddr offset,
482
+ unsigned size)
483
+{
484
+ AwRtcState *s = AW_RTC(opaque);
485
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
486
+ uint64_t val = 0;
487
+
488
+ if (offset >= c->regmap_size) {
489
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
490
+ __func__, (uint32_t)offset);
491
+ return 0;
492
+ }
493
+
494
+ if (!c->regmap[offset]) {
495
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid register 0x%04x\n",
496
+ __func__, (uint32_t)offset);
497
+ return 0;
498
+ }
499
+
500
+ switch (c->regmap[offset]) {
501
+ case REG_LOSC: /* Low Oscillator Control */
502
+ val = s->regs[REG_LOSC];
503
+ s->regs[REG_LOSC] &= ~(REG_LOSC_YMD | REG_LOSC_HMS);
504
+ break;
505
+ case REG_YYMMDD: /* RTC Year-Month-Day */
506
+ case REG_HHMMSS: /* RTC Hour-Minute-Second */
507
+ case REG_GP0: /* General Purpose Register 0 */
508
+ case REG_GP1: /* General Purpose Register 1 */
509
+ case REG_GP2: /* General Purpose Register 2 */
510
+ case REG_GP3: /* General Purpose Register 3 */
511
+ val = s->regs[c->regmap[offset]];
512
+ break;
513
+ default:
514
+ if (!c->read(s, offset)) {
515
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
516
+ __func__, (uint32_t)offset);
517
+ }
518
+ val = s->regs[c->regmap[offset]];
519
+ break;
520
+ }
521
+
522
+ trace_allwinner_rtc_read(offset, val);
523
+ return val;
524
+}
525
+
526
+static void allwinner_rtc_write(void *opaque, hwaddr offset,
527
+ uint64_t val, unsigned size)
528
+{
529
+ AwRtcState *s = AW_RTC(opaque);
530
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
531
+
532
+ if (offset >= c->regmap_size) {
533
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
534
+ __func__, (uint32_t)offset);
535
+ return;
536
+ }
537
+
538
+ if (!c->regmap[offset]) {
539
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid register 0x%04x\n",
540
+ __func__, (uint32_t)offset);
541
+ return;
542
+ }
543
+
544
+ trace_allwinner_rtc_write(offset, val);
545
+
546
+ switch (c->regmap[offset]) {
547
+ case REG_YYMMDD: /* RTC Year-Month-Day */
548
+ s->regs[REG_YYMMDD] = val;
549
+ s->regs[REG_LOSC] |= REG_LOSC_YMD;
550
+ break;
551
+ case REG_HHMMSS: /* RTC Hour-Minute-Second */
552
+ s->regs[REG_HHMMSS] = val;
553
+ s->regs[REG_LOSC] |= REG_LOSC_HMS;
554
+ break;
555
+ case REG_GP0: /* General Purpose Register 0 */
556
+ case REG_GP1: /* General Purpose Register 1 */
557
+ case REG_GP2: /* General Purpose Register 2 */
558
+ case REG_GP3: /* General Purpose Register 3 */
559
+ s->regs[c->regmap[offset]] = val;
560
+ break;
561
+ default:
562
+ if (!c->write(s, offset, val)) {
563
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
564
+ __func__, (uint32_t)offset);
565
+ }
566
+ break;
567
+ }
568
+}
569
+
570
+static const MemoryRegionOps allwinner_rtc_ops = {
571
+ .read = allwinner_rtc_read,
572
+ .write = allwinner_rtc_write,
573
+ .endianness = DEVICE_NATIVE_ENDIAN,
574
+ .valid = {
575
+ .min_access_size = 4,
576
+ .max_access_size = 4,
577
+ },
578
+ .impl.min_access_size = 4,
579
+};
580
+
581
+static void allwinner_rtc_reset(DeviceState *dev)
582
+{
583
+ AwRtcState *s = AW_RTC(dev);
584
+ struct tm now;
585
+
586
+ /* Clear registers */
587
+ memset(s->regs, 0, sizeof(s->regs));
588
+
589
+ /* Get current datetime */
590
+ qemu_get_timedate(&now, 0);
591
+
592
+ /* Set RTC with current datetime */
593
+ if (s->base_year > 1900) {
594
+ s->regs[REG_YYMMDD] = ((now.tm_year + 1900 - s->base_year) << 16) |
595
+ ((now.tm_mon + 1) << 8) |
596
+ now.tm_mday;
597
+ s->regs[REG_HHMMSS] = (((now.tm_wday + 6) % 7) << 29) |
598
+ (now.tm_hour << 16) |
599
+ (now.tm_min << 8) |
600
+ now.tm_sec;
601
+ }
602
+}
603
+
604
+static void allwinner_rtc_init(Object *obj)
605
+{
606
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
607
+ AwRtcState *s = AW_RTC(obj);
608
+
609
+ /* Memory mapping */
610
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_rtc_ops, s,
611
+ TYPE_AW_RTC, 1 * KiB);
612
+ sysbus_init_mmio(sbd, &s->iomem);
613
+}
614
+
615
+static const VMStateDescription allwinner_rtc_vmstate = {
616
+ .name = "allwinner-rtc",
617
+ .version_id = 1,
618
+ .minimum_version_id = 1,
619
+ .fields = (VMStateField[]) {
620
+ VMSTATE_UINT32_ARRAY(regs, AwRtcState, AW_RTC_REGS_NUM),
621
+ VMSTATE_END_OF_LIST()
622
+ }
623
+};
624
+
625
+static Property allwinner_rtc_properties[] = {
626
+ DEFINE_PROP_INT32("base-year", AwRtcState, base_year, 0),
627
+ DEFINE_PROP_END_OF_LIST(),
628
+};
629
+
630
+static void allwinner_rtc_class_init(ObjectClass *klass, void *data)
631
+{
632
+ DeviceClass *dc = DEVICE_CLASS(klass);
633
+
634
+ dc->reset = allwinner_rtc_reset;
635
+ dc->vmsd = &allwinner_rtc_vmstate;
636
+ device_class_set_props(dc, allwinner_rtc_properties);
637
+}
638
+
639
+static void allwinner_rtc_sun4i_init(Object *obj)
640
+{
641
+ AwRtcState *s = AW_RTC(obj);
642
+ s->base_year = 2010;
643
+}
644
+
645
+static void allwinner_rtc_sun4i_class_init(ObjectClass *klass, void *data)
646
+{
647
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
648
+
649
+ arc->regmap = allwinner_rtc_sun4i_regmap;
650
+ arc->regmap_size = sizeof(allwinner_rtc_sun4i_regmap);
651
+ arc->read = allwinner_rtc_sun4i_read;
652
+ arc->write = allwinner_rtc_sun4i_write;
653
+}
654
+
655
+static void allwinner_rtc_sun6i_init(Object *obj)
656
+{
657
+ AwRtcState *s = AW_RTC(obj);
658
+ s->base_year = 1970;
659
+}
660
+
661
+static void allwinner_rtc_sun6i_class_init(ObjectClass *klass, void *data)
662
+{
663
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
664
+
665
+ arc->regmap = allwinner_rtc_sun6i_regmap;
666
+ arc->regmap_size = sizeof(allwinner_rtc_sun6i_regmap);
667
+ arc->read = allwinner_rtc_sun6i_read;
668
+ arc->write = allwinner_rtc_sun6i_write;
669
+}
670
+
671
+static void allwinner_rtc_sun7i_init(Object *obj)
672
+{
673
+ AwRtcState *s = AW_RTC(obj);
674
+ s->base_year = 1970;
675
+}
676
+
677
+static void allwinner_rtc_sun7i_class_init(ObjectClass *klass, void *data)
678
+{
679
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
680
+ allwinner_rtc_sun4i_class_init(klass, arc);
681
+}
682
+
683
+static const TypeInfo allwinner_rtc_info = {
684
+ .name = TYPE_AW_RTC,
685
+ .parent = TYPE_SYS_BUS_DEVICE,
686
+ .instance_init = allwinner_rtc_init,
687
+ .instance_size = sizeof(AwRtcState),
688
+ .class_init = allwinner_rtc_class_init,
689
+ .class_size = sizeof(AwRtcClass),
690
+ .abstract = true,
691
+};
692
+
693
+static const TypeInfo allwinner_rtc_sun4i_info = {
694
+ .name = TYPE_AW_RTC_SUN4I,
695
+ .parent = TYPE_AW_RTC,
696
+ .class_init = allwinner_rtc_sun4i_class_init,
697
+ .instance_init = allwinner_rtc_sun4i_init,
698
+};
699
+
700
+static const TypeInfo allwinner_rtc_sun6i_info = {
701
+ .name = TYPE_AW_RTC_SUN6I,
702
+ .parent = TYPE_AW_RTC,
703
+ .class_init = allwinner_rtc_sun6i_class_init,
704
+ .instance_init = allwinner_rtc_sun6i_init,
705
+};
706
+
707
+static const TypeInfo allwinner_rtc_sun7i_info = {
708
+ .name = TYPE_AW_RTC_SUN7I,
709
+ .parent = TYPE_AW_RTC,
710
+ .class_init = allwinner_rtc_sun7i_class_init,
711
+ .instance_init = allwinner_rtc_sun7i_init,
712
+};
713
+
714
+static void allwinner_rtc_register(void)
715
+{
716
+ type_register_static(&allwinner_rtc_info);
717
+ type_register_static(&allwinner_rtc_sun4i_info);
718
+ type_register_static(&allwinner_rtc_sun6i_info);
719
+ type_register_static(&allwinner_rtc_sun7i_info);
720
+}
721
+
722
+type_init(allwinner_rtc_register)
723
diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events
724
index XXXXXXX..XXXXXXX 100644
80
index XXXXXXX..XXXXXXX 100644
725
--- a/hw/rtc/trace-events
81
--- a/target/arm/translate-mve.c
726
+++ b/hw/rtc/trace-events
82
+++ b/target/arm/translate-mve.c
727
@@ -XXX,XX +XXX,XX @@
83
@@ -XXX,XX +XXX,XX @@ DO_2OP(VSUB, vsub)
728
# See docs/devel/tracing.txt for syntax documentation.
84
DO_2OP(VMUL, vmul)
729
85
DO_2OP(VMULH_S, vmulhs)
730
+# allwinner-rtc.c
86
DO_2OP(VMULH_U, vmulhu)
731
+allwinner_rtc_read(uint64_t addr, uint64_t value) "addr 0x%" PRIx64 " value 0x%" PRIx64
87
+DO_2OP(VRMULH_S, vrmulhs)
732
+allwinner_rtc_write(uint64_t addr, uint64_t value) "addr 0x%" PRIx64 " value 0x%" PRIx64
88
+DO_2OP(VRMULH_U, vrmulhu)
733
+
734
# sun4v-rtc.c
735
sun4v_rtc_read(uint64_t addr, uint64_t value) "read: addr 0x%" PRIx64 " value 0x%" PRIx64
736
sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value 0x%" PRIx64
737
--
89
--
738
2.20.1
90
2.20.1
739
91
740
92
diff view generated by jsdifflib
New patch
1
Implement the MVE VMAX and VMIN insns.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-16-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 14 ++++++++++++++
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 37 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DEF_HELPER_FLAGS_4(mve_vrmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vrmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vrmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_4(mve_vmaxsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vmaxsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vmaxsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vmaxub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vmaxuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vmaxuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+
29
+DEF_HELPER_FLAGS_4(mve_vminsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+DEF_HELPER_FLAGS_4(mve_vminsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vminsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vminub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vminuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vminuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/mve.decode
38
+++ b/target/arm/mve.decode
39
@@ -XXX,XX +XXX,XX @@ VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
40
VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
41
VRMULH_U 111 1 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
42
43
+VMAX_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
44
+VMAX_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
45
+VMIN_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
46
+VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
47
+
48
# Vector miscellaneous
49
50
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
51
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/mve_helper.c
54
+++ b/target/arm/mve_helper.c
55
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
56
DO_2OP(OP##h, 2, uint16_t, FN) \
57
DO_2OP(OP##w, 4, uint32_t, FN)
58
59
+/* provide signed 2-op helpers for all sizes */
60
+#define DO_2OP_S(OP, FN) \
61
+ DO_2OP(OP##b, 1, int8_t, FN) \
62
+ DO_2OP(OP##h, 2, int16_t, FN) \
63
+ DO_2OP(OP##w, 4, int32_t, FN)
64
+
65
#define DO_AND(N, M) ((N) & (M))
66
#define DO_BIC(N, M) ((N) & ~(M))
67
#define DO_ORR(N, M) ((N) | (M))
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(vrmulhsw, 4, int32_t, do_rmulh_w)
69
DO_2OP(vrmulhub, 1, uint8_t, do_rmulh_b)
70
DO_2OP(vrmulhuh, 2, uint16_t, do_rmulh_h)
71
DO_2OP(vrmulhuw, 4, uint32_t, do_rmulh_w)
72
+
73
+#define DO_MAX(N, M) ((N) >= (M) ? (N) : (M))
74
+#define DO_MIN(N, M) ((N) >= (M) ? (M) : (N))
75
+
76
+DO_2OP_S(vmaxs, DO_MAX)
77
+DO_2OP_U(vmaxu, DO_MAX)
78
+DO_2OP_S(vmins, DO_MIN)
79
+DO_2OP_U(vminu, DO_MIN)
80
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate-mve.c
83
+++ b/target/arm/translate-mve.c
84
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULH_S, vmulhs)
85
DO_2OP(VMULH_U, vmulhu)
86
DO_2OP(VRMULH_S, vrmulhs)
87
DO_2OP(VRMULH_U, vrmulhu)
88
+DO_2OP(VMAX_S, vmaxs)
89
+DO_2OP(VMAX_U, vmaxu)
90
+DO_2OP(VMIN_S, vmins)
91
+DO_2OP(VMIN_U, vminu)
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
New patch
1
Implement the MVE VABD insn.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-17-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 7 +++++++
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 5 +++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 17 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vminsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DEF_HELPER_FLAGS_4(mve_vminub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vminuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vminuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_4(mve_vabdsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vabdsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vabdsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vabdub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vabduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vabduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VMAX_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
33
VMIN_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
34
VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
35
36
+VABD_S 111 0 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
37
+VABD_U 111 1 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
38
+
39
# Vector miscellaneous
40
41
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vmaxs, DO_MAX)
47
DO_2OP_U(vmaxu, DO_MAX)
48
DO_2OP_S(vmins, DO_MIN)
49
DO_2OP_U(vminu, DO_MIN)
50
+
51
+#define DO_ABD(N, M) ((N) >= (M) ? (N) - (M) : (M) - (N))
52
+
53
+DO_2OP_S(vabds, DO_ABD)
54
+DO_2OP_U(vabdu, DO_ABD)
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-mve.c
58
+++ b/target/arm/translate-mve.c
59
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMAX_S, vmaxs)
60
DO_2OP(VMAX_U, vmaxu)
61
DO_2OP(VMIN_S, vmins)
62
DO_2OP(VMIN_U, vminu)
63
+DO_2OP(VABD_S, vabds)
64
+DO_2OP(VABD_U, vabdu)
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement MVE VHADD and VHSUB insns, which perform an addition
2
or subtraction and then halve the result.
2
3
3
The Clock Control Unit is responsible for clock signal generation,
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
configuration and distribution in the Allwinner H3 System on Chip.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
This commit adds support for the Clock Control Unit which emulates
6
Message-id: 20210617121628.20116-18-peter.maydell@linaro.org
6
a simple read/write register interface.
7
---
8
target/arm/helper-mve.h | 14 ++++++++++++++
9
target/arm/mve.decode | 5 +++++
10
target/arm/mve_helper.c | 25 +++++++++++++++++++++++++
11
target/arm/translate-mve.c | 4 ++++
12
4 files changed, 48 insertions(+)
7
13
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Message-id: 20200311221854.30370-4-nieklinnenbank@gmail.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/misc/Makefile.objs | 1 +
16
include/hw/arm/allwinner-h3.h | 3 +
17
include/hw/misc/allwinner-h3-ccu.h | 66 ++++++++
18
hw/arm/allwinner-h3.c | 9 +-
19
hw/misc/allwinner-h3-ccu.c | 242 +++++++++++++++++++++++++++++
20
5 files changed, 320 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/misc/allwinner-h3-ccu.h
22
create mode 100644 hw/misc/allwinner-h3-ccu.c
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/Makefile.objs
16
--- a/target/arm/helper-mve.h
27
+++ b/hw/misc/Makefile.objs
17
+++ b/target/arm/helper-mve.h
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vabdsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
19
DEF_HELPER_FLAGS_4(mve_vabdub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
20
DEF_HELPER_FLAGS_4(mve_vabduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
21
DEF_HELPER_FLAGS_4(mve_vabduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
22
+
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
23
+DEF_HELPER_FLAGS_4(mve_vhaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
common-obj-$(CONFIG_NSERIES) += cbus.o
24
+DEF_HELPER_FLAGS_4(mve_vhaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
25
+DEF_HELPER_FLAGS_4(mve_vhaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
26
+DEF_HELPER_FLAGS_4(mve_vhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vhadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vhsubsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vhsubsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vhsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vhsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vhsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+DEF_HELPER_FLAGS_4(mve_vhsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
38
--- a/target/arm/mve.decode
39
+++ b/include/hw/arm/allwinner-h3.h
39
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@ VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
41
#include "hw/arm/boot.h"
41
VABD_S 111 0 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
42
#include "hw/timer/allwinner-a10-pit.h"
42
VABD_U 111 1 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
43
#include "hw/intc/arm_gic.h"
43
44
+#include "hw/misc/allwinner-h3-ccu.h"
44
+VHADD_S 111 0 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
45
#include "target/arm/cpu.h"
45
+VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
46
46
+VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
47
/**
47
+VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
48
@@ -XXX,XX +XXX,XX @@ enum {
49
AW_H3_SRAM_A1,
50
AW_H3_SRAM_A2,
51
AW_H3_SRAM_C,
52
+ AW_H3_CCU,
53
AW_H3_PIT,
54
AW_H3_UART0,
55
AW_H3_UART1,
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
57
ARMCPU cpus[AW_H3_NUM_CPUS];
58
const hwaddr *memmap;
59
AwA10PITState timer;
60
+ AwH3ClockCtlState ccu;
61
GICState gic;
62
MemoryRegion sram_a1;
63
MemoryRegion sram_a2;
64
diff --git a/include/hw/misc/allwinner-h3-ccu.h b/include/hw/misc/allwinner-h3-ccu.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/allwinner-h3-ccu.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * Allwinner H3 Clock Control Unit emulation
72
+ *
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
74
+ *
75
+ * This program is free software: you can redistribute it and/or modify
76
+ * it under the terms of the GNU General Public License as published by
77
+ * the Free Software Foundation, either version 2 of the License, or
78
+ * (at your option) any later version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful,
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
+ * GNU General Public License for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
88
+
48
+
89
+#ifndef HW_MISC_ALLWINNER_H3_CCU_H
49
# Vector miscellaneous
90
+#define HW_MISC_ALLWINNER_H3_CCU_H
50
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vminu, DO_MIN)
57
58
DO_2OP_S(vabds, DO_ABD)
59
DO_2OP_U(vabdu, DO_ABD)
91
+
60
+
92
+#include "qom/object.h"
61
+static inline uint32_t do_vhadd_u(uint32_t n, uint32_t m)
93
+#include "hw/sysbus.h"
94
+
95
+/**
96
+ * @name Constants
97
+ * @{
98
+ */
99
+
100
+/** Size of register I/O address space used by CCU device */
101
+#define AW_H3_CCU_IOSIZE (0x400)
102
+
103
+/** Total number of known registers */
104
+#define AW_H3_CCU_REGS_NUM (AW_H3_CCU_IOSIZE / sizeof(uint32_t))
105
+
106
+/** @} */
107
+
108
+/**
109
+ * @name Object model
110
+ * @{
111
+ */
112
+
113
+#define TYPE_AW_H3_CCU "allwinner-h3-ccu"
114
+#define AW_H3_CCU(obj) \
115
+ OBJECT_CHECK(AwH3ClockCtlState, (obj), TYPE_AW_H3_CCU)
116
+
117
+/** @} */
118
+
119
+/**
120
+ * Allwinner H3 CCU object instance state.
121
+ */
122
+typedef struct AwH3ClockCtlState {
123
+ /*< private >*/
124
+ SysBusDevice parent_obj;
125
+ /*< public >*/
126
+
127
+ /** Maps I/O registers in physical memory */
128
+ MemoryRegion iomem;
129
+
130
+ /** Array of hardware registers */
131
+ uint32_t regs[AW_H3_CCU_REGS_NUM];
132
+
133
+} AwH3ClockCtlState;
134
+
135
+#endif /* HW_MISC_ALLWINNER_H3_CCU_H */
136
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/arm/allwinner-h3.c
139
+++ b/hw/arm/allwinner-h3.c
140
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
141
[AW_H3_SRAM_A1] = 0x00000000,
142
[AW_H3_SRAM_A2] = 0x00044000,
143
[AW_H3_SRAM_C] = 0x00010000,
144
+ [AW_H3_CCU] = 0x01c20000,
145
[AW_H3_PIT] = 0x01c20c00,
146
[AW_H3_UART0] = 0x01c28000,
147
[AW_H3_UART1] = 0x01c28400,
148
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
149
{ "usb2-phy", 0x01c1c000, 4 * KiB },
150
{ "usb3-phy", 0x01c1d000, 4 * KiB },
151
{ "smc", 0x01c1e000, 4 * KiB },
152
- { "ccu", 0x01c20000, 1 * KiB },
153
{ "pio", 0x01c20800, 1 * KiB },
154
{ "owa", 0x01c21000, 1 * KiB },
155
{ "pwm", 0x01c21400, 1 * KiB },
156
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
157
"clk0-freq", &error_abort);
158
object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
159
"clk1-freq", &error_abort);
160
+
161
+ sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu),
162
+ TYPE_AW_H3_CCU);
163
}
164
165
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
166
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
167
memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_C],
168
&s->sram_c);
169
170
+ /* Clock Control Unit */
171
+ qdev_init_nofail(DEVICE(&s->ccu));
172
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
173
+
174
/* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
175
serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
176
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
177
diff --git a/hw/misc/allwinner-h3-ccu.c b/hw/misc/allwinner-h3-ccu.c
178
new file mode 100644
179
index XXXXXXX..XXXXXXX
180
--- /dev/null
181
+++ b/hw/misc/allwinner-h3-ccu.c
182
@@ -XXX,XX +XXX,XX @@
183
+/*
184
+ * Allwinner H3 Clock Control Unit emulation
185
+ *
186
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
187
+ *
188
+ * This program is free software: you can redistribute it and/or modify
189
+ * it under the terms of the GNU General Public License as published by
190
+ * the Free Software Foundation, either version 2 of the License, or
191
+ * (at your option) any later version.
192
+ *
193
+ * This program is distributed in the hope that it will be useful,
194
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
195
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
196
+ * GNU General Public License for more details.
197
+ *
198
+ * You should have received a copy of the GNU General Public License
199
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
200
+ */
201
+
202
+#include "qemu/osdep.h"
203
+#include "qemu/units.h"
204
+#include "hw/sysbus.h"
205
+#include "migration/vmstate.h"
206
+#include "qemu/log.h"
207
+#include "qemu/module.h"
208
+#include "hw/misc/allwinner-h3-ccu.h"
209
+
210
+/* CCU register offsets */
211
+enum {
212
+ REG_PLL_CPUX = 0x0000, /* PLL CPUX Control */
213
+ REG_PLL_AUDIO = 0x0008, /* PLL Audio Control */
214
+ REG_PLL_VIDEO = 0x0010, /* PLL Video Control */
215
+ REG_PLL_VE = 0x0018, /* PLL VE Control */
216
+ REG_PLL_DDR = 0x0020, /* PLL DDR Control */
217
+ REG_PLL_PERIPH0 = 0x0028, /* PLL Peripherals 0 Control */
218
+ REG_PLL_GPU = 0x0038, /* PLL GPU Control */
219
+ REG_PLL_PERIPH1 = 0x0044, /* PLL Peripherals 1 Control */
220
+ REG_PLL_DE = 0x0048, /* PLL Display Engine Control */
221
+ REG_CPUX_AXI = 0x0050, /* CPUX/AXI Configuration */
222
+ REG_APB1 = 0x0054, /* ARM Peripheral Bus 1 Config */
223
+ REG_APB2 = 0x0058, /* ARM Peripheral Bus 2 Config */
224
+ REG_DRAM_CFG = 0x00F4, /* DRAM Configuration */
225
+ REG_MBUS = 0x00FC, /* MBUS Reset */
226
+ REG_PLL_TIME0 = 0x0200, /* PLL Stable Time 0 */
227
+ REG_PLL_TIME1 = 0x0204, /* PLL Stable Time 1 */
228
+ REG_PLL_CPUX_BIAS = 0x0220, /* PLL CPUX Bias */
229
+ REG_PLL_AUDIO_BIAS = 0x0224, /* PLL Audio Bias */
230
+ REG_PLL_VIDEO_BIAS = 0x0228, /* PLL Video Bias */
231
+ REG_PLL_VE_BIAS = 0x022C, /* PLL VE Bias */
232
+ REG_PLL_DDR_BIAS = 0x0230, /* PLL DDR Bias */
233
+ REG_PLL_PERIPH0_BIAS = 0x0234, /* PLL Peripherals 0 Bias */
234
+ REG_PLL_GPU_BIAS = 0x023C, /* PLL GPU Bias */
235
+ REG_PLL_PERIPH1_BIAS = 0x0244, /* PLL Peripherals 1 Bias */
236
+ REG_PLL_DE_BIAS = 0x0248, /* PLL Display Engine Bias */
237
+ REG_PLL_CPUX_TUNING = 0x0250, /* PLL CPUX Tuning */
238
+ REG_PLL_DDR_TUNING = 0x0260, /* PLL DDR Tuning */
239
+};
240
+
241
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
242
+
243
+/* CCU register flags */
244
+enum {
245
+ REG_DRAM_CFG_UPDATE = (1 << 16),
246
+};
247
+
248
+enum {
249
+ REG_PLL_ENABLE = (1 << 31),
250
+ REG_PLL_LOCK = (1 << 28),
251
+};
252
+
253
+
254
+/* CCU register reset values */
255
+enum {
256
+ REG_PLL_CPUX_RST = 0x00001000,
257
+ REG_PLL_AUDIO_RST = 0x00035514,
258
+ REG_PLL_VIDEO_RST = 0x03006207,
259
+ REG_PLL_VE_RST = 0x03006207,
260
+ REG_PLL_DDR_RST = 0x00001000,
261
+ REG_PLL_PERIPH0_RST = 0x00041811,
262
+ REG_PLL_GPU_RST = 0x03006207,
263
+ REG_PLL_PERIPH1_RST = 0x00041811,
264
+ REG_PLL_DE_RST = 0x03006207,
265
+ REG_CPUX_AXI_RST = 0x00010000,
266
+ REG_APB1_RST = 0x00001010,
267
+ REG_APB2_RST = 0x01000000,
268
+ REG_DRAM_CFG_RST = 0x00000000,
269
+ REG_MBUS_RST = 0x80000000,
270
+ REG_PLL_TIME0_RST = 0x000000FF,
271
+ REG_PLL_TIME1_RST = 0x000000FF,
272
+ REG_PLL_CPUX_BIAS_RST = 0x08100200,
273
+ REG_PLL_AUDIO_BIAS_RST = 0x10100000,
274
+ REG_PLL_VIDEO_BIAS_RST = 0x10100000,
275
+ REG_PLL_VE_BIAS_RST = 0x10100000,
276
+ REG_PLL_DDR_BIAS_RST = 0x81104000,
277
+ REG_PLL_PERIPH0_BIAS_RST = 0x10100010,
278
+ REG_PLL_GPU_BIAS_RST = 0x10100000,
279
+ REG_PLL_PERIPH1_BIAS_RST = 0x10100010,
280
+ REG_PLL_DE_BIAS_RST = 0x10100000,
281
+ REG_PLL_CPUX_TUNING_RST = 0x0A101000,
282
+ REG_PLL_DDR_TUNING_RST = 0x14880000,
283
+};
284
+
285
+static uint64_t allwinner_h3_ccu_read(void *opaque, hwaddr offset,
286
+ unsigned size)
287
+{
62
+{
288
+ const AwH3ClockCtlState *s = AW_H3_CCU(opaque);
63
+ return ((uint64_t)n + m) >> 1;
289
+ const uint32_t idx = REG_INDEX(offset);
290
+
291
+ switch (offset) {
292
+ case 0x308 ... AW_H3_CCU_IOSIZE:
293
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
294
+ __func__, (uint32_t)offset);
295
+ return 0;
296
+ }
297
+
298
+ return s->regs[idx];
299
+}
64
+}
300
+
65
+
301
+static void allwinner_h3_ccu_write(void *opaque, hwaddr offset,
66
+static inline int32_t do_vhadd_s(int32_t n, int32_t m)
302
+ uint64_t val, unsigned size)
303
+{
67
+{
304
+ AwH3ClockCtlState *s = AW_H3_CCU(opaque);
68
+ return ((int64_t)n + m) >> 1;
305
+ const uint32_t idx = REG_INDEX(offset);
306
+
307
+ switch (offset) {
308
+ case REG_DRAM_CFG: /* DRAM Configuration */
309
+ val &= ~REG_DRAM_CFG_UPDATE;
310
+ break;
311
+ case REG_PLL_CPUX: /* PLL CPUX Control */
312
+ case REG_PLL_AUDIO: /* PLL Audio Control */
313
+ case REG_PLL_VIDEO: /* PLL Video Control */
314
+ case REG_PLL_VE: /* PLL VE Control */
315
+ case REG_PLL_DDR: /* PLL DDR Control */
316
+ case REG_PLL_PERIPH0: /* PLL Peripherals 0 Control */
317
+ case REG_PLL_GPU: /* PLL GPU Control */
318
+ case REG_PLL_PERIPH1: /* PLL Peripherals 1 Control */
319
+ case REG_PLL_DE: /* PLL Display Engine Control */
320
+ if (val & REG_PLL_ENABLE) {
321
+ val |= REG_PLL_LOCK;
322
+ }
323
+ break;
324
+ case 0x308 ... AW_H3_CCU_IOSIZE:
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
326
+ __func__, (uint32_t)offset);
327
+ break;
328
+ default:
329
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
330
+ __func__, (uint32_t)offset);
331
+ break;
332
+ }
333
+
334
+ s->regs[idx] = (uint32_t) val;
335
+}
69
+}
336
+
70
+
337
+static const MemoryRegionOps allwinner_h3_ccu_ops = {
71
+static inline uint32_t do_vhsub_u(uint32_t n, uint32_t m)
338
+ .read = allwinner_h3_ccu_read,
339
+ .write = allwinner_h3_ccu_write,
340
+ .endianness = DEVICE_NATIVE_ENDIAN,
341
+ .valid = {
342
+ .min_access_size = 4,
343
+ .max_access_size = 4,
344
+ },
345
+ .impl.min_access_size = 4,
346
+};
347
+
348
+static void allwinner_h3_ccu_reset(DeviceState *dev)
349
+{
72
+{
350
+ AwH3ClockCtlState *s = AW_H3_CCU(dev);
73
+ return ((uint64_t)n - m) >> 1;
351
+
352
+ /* Set default values for registers */
353
+ s->regs[REG_INDEX(REG_PLL_CPUX)] = REG_PLL_CPUX_RST;
354
+ s->regs[REG_INDEX(REG_PLL_AUDIO)] = REG_PLL_AUDIO_RST;
355
+ s->regs[REG_INDEX(REG_PLL_VIDEO)] = REG_PLL_VIDEO_RST;
356
+ s->regs[REG_INDEX(REG_PLL_VE)] = REG_PLL_VE_RST;
357
+ s->regs[REG_INDEX(REG_PLL_DDR)] = REG_PLL_DDR_RST;
358
+ s->regs[REG_INDEX(REG_PLL_PERIPH0)] = REG_PLL_PERIPH0_RST;
359
+ s->regs[REG_INDEX(REG_PLL_GPU)] = REG_PLL_GPU_RST;
360
+ s->regs[REG_INDEX(REG_PLL_PERIPH1)] = REG_PLL_PERIPH1_RST;
361
+ s->regs[REG_INDEX(REG_PLL_DE)] = REG_PLL_DE_RST;
362
+ s->regs[REG_INDEX(REG_CPUX_AXI)] = REG_CPUX_AXI_RST;
363
+ s->regs[REG_INDEX(REG_APB1)] = REG_APB1_RST;
364
+ s->regs[REG_INDEX(REG_APB2)] = REG_APB2_RST;
365
+ s->regs[REG_INDEX(REG_DRAM_CFG)] = REG_DRAM_CFG_RST;
366
+ s->regs[REG_INDEX(REG_MBUS)] = REG_MBUS_RST;
367
+ s->regs[REG_INDEX(REG_PLL_TIME0)] = REG_PLL_TIME0_RST;
368
+ s->regs[REG_INDEX(REG_PLL_TIME1)] = REG_PLL_TIME1_RST;
369
+ s->regs[REG_INDEX(REG_PLL_CPUX_BIAS)] = REG_PLL_CPUX_BIAS_RST;
370
+ s->regs[REG_INDEX(REG_PLL_AUDIO_BIAS)] = REG_PLL_AUDIO_BIAS_RST;
371
+ s->regs[REG_INDEX(REG_PLL_VIDEO_BIAS)] = REG_PLL_VIDEO_BIAS_RST;
372
+ s->regs[REG_INDEX(REG_PLL_VE_BIAS)] = REG_PLL_VE_BIAS_RST;
373
+ s->regs[REG_INDEX(REG_PLL_DDR_BIAS)] = REG_PLL_DDR_BIAS_RST;
374
+ s->regs[REG_INDEX(REG_PLL_PERIPH0_BIAS)] = REG_PLL_PERIPH0_BIAS_RST;
375
+ s->regs[REG_INDEX(REG_PLL_GPU_BIAS)] = REG_PLL_GPU_BIAS_RST;
376
+ s->regs[REG_INDEX(REG_PLL_PERIPH1_BIAS)] = REG_PLL_PERIPH1_BIAS_RST;
377
+ s->regs[REG_INDEX(REG_PLL_DE_BIAS)] = REG_PLL_DE_BIAS_RST;
378
+ s->regs[REG_INDEX(REG_PLL_CPUX_TUNING)] = REG_PLL_CPUX_TUNING_RST;
379
+ s->regs[REG_INDEX(REG_PLL_DDR_TUNING)] = REG_PLL_DDR_TUNING_RST;
380
+}
74
+}
381
+
75
+
382
+static void allwinner_h3_ccu_init(Object *obj)
76
+static inline int32_t do_vhsub_s(int32_t n, int32_t m)
383
+{
77
+{
384
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
78
+ return ((int64_t)n - m) >> 1;
385
+ AwH3ClockCtlState *s = AW_H3_CCU(obj);
386
+
387
+ /* Memory mapping */
388
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_h3_ccu_ops, s,
389
+ TYPE_AW_H3_CCU, AW_H3_CCU_IOSIZE);
390
+ sysbus_init_mmio(sbd, &s->iomem);
391
+}
79
+}
392
+
80
+
393
+static const VMStateDescription allwinner_h3_ccu_vmstate = {
81
+DO_2OP_S(vhadds, do_vhadd_s)
394
+ .name = "allwinner-h3-ccu",
82
+DO_2OP_U(vhaddu, do_vhadd_u)
395
+ .version_id = 1,
83
+DO_2OP_S(vhsubs, do_vhsub_s)
396
+ .minimum_version_id = 1,
84
+DO_2OP_U(vhsubu, do_vhsub_u)
397
+ .fields = (VMStateField[]) {
85
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
398
+ VMSTATE_UINT32_ARRAY(regs, AwH3ClockCtlState, AW_H3_CCU_REGS_NUM),
86
index XXXXXXX..XXXXXXX 100644
399
+ VMSTATE_END_OF_LIST()
87
--- a/target/arm/translate-mve.c
400
+ }
88
+++ b/target/arm/translate-mve.c
401
+};
89
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMIN_S, vmins)
402
+
90
DO_2OP(VMIN_U, vminu)
403
+static void allwinner_h3_ccu_class_init(ObjectClass *klass, void *data)
91
DO_2OP(VABD_S, vabds)
404
+{
92
DO_2OP(VABD_U, vabdu)
405
+ DeviceClass *dc = DEVICE_CLASS(klass);
93
+DO_2OP(VHADD_S, vhadds)
406
+
94
+DO_2OP(VHADD_U, vhaddu)
407
+ dc->reset = allwinner_h3_ccu_reset;
95
+DO_2OP(VHSUB_S, vhsubs)
408
+ dc->vmsd = &allwinner_h3_ccu_vmstate;
96
+DO_2OP(VHSUB_U, vhsubu)
409
+}
410
+
411
+static const TypeInfo allwinner_h3_ccu_info = {
412
+ .name = TYPE_AW_H3_CCU,
413
+ .parent = TYPE_SYS_BUS_DEVICE,
414
+ .instance_init = allwinner_h3_ccu_init,
415
+ .instance_size = sizeof(AwH3ClockCtlState),
416
+ .class_init = allwinner_h3_ccu_class_init,
417
+};
418
+
419
+static void allwinner_h3_ccu_register(void)
420
+{
421
+ type_register_static(&allwinner_h3_ccu_info);
422
+}
423
+
424
+type_init(allwinner_h3_ccu_register)
425
--
97
--
426
2.20.1
98
2.20.1
427
99
428
100
diff view generated by jsdifflib
New patch
1
Implement the MVE VMULL insn, which multiplies two single
2
width integer elements to produce a double width result.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-19-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 14 ++++++++++++++
9
target/arm/mve.decode | 5 +++++
10
target/arm/mve_helper.c | 34 ++++++++++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 4 ++++
12
4 files changed, 57 insertions(+)
13
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vhsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vhsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
DEF_HELPER_FLAGS_4(mve_vhsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vmullbsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vmullbsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vmullbsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vmullbub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vmullbuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vmullbuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vmulltsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vmulltsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vmulltsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/mve.decode
39
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@ VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
41
VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
42
VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
43
44
+VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
45
+VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
46
+VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
47
+VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
48
+
49
# Vector miscellaneous
50
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
57
DO_2OP(OP##h, 2, int16_t, FN) \
58
DO_2OP(OP##w, 4, int32_t, FN)
59
60
+/*
61
+ * "Long" operations where two half-sized inputs (taken from either the
62
+ * top or the bottom of the input vector) produce a double-width result.
63
+ * Here ESIZE, TYPE are for the input, and LESIZE, LTYPE for the output.
64
+ */
65
+#define DO_2OP_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN) \
66
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
67
+ { \
68
+ LTYPE *d = vd; \
69
+ TYPE *n = vn, *m = vm; \
70
+ uint16_t mask = mve_element_mask(env); \
71
+ unsigned le; \
72
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
73
+ LTYPE r = FN((LTYPE)n[H##ESIZE(le * 2 + TOP)], \
74
+ m[H##ESIZE(le * 2 + TOP)]); \
75
+ mergemask(&d[H##LESIZE(le)], r, mask); \
76
+ } \
77
+ mve_advance_vpt(env); \
78
+ }
79
+
80
#define DO_AND(N, M) ((N) & (M))
81
#define DO_BIC(N, M) ((N) & ~(M))
82
#define DO_ORR(N, M) ((N) | (M))
83
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vadd, DO_ADD)
84
DO_2OP_U(vsub, DO_SUB)
85
DO_2OP_U(vmul, DO_MUL)
86
87
+DO_2OP_L(vmullbsb, 0, 1, int8_t, 2, int16_t, DO_MUL)
88
+DO_2OP_L(vmullbsh, 0, 2, int16_t, 4, int32_t, DO_MUL)
89
+DO_2OP_L(vmullbsw, 0, 4, int32_t, 8, int64_t, DO_MUL)
90
+DO_2OP_L(vmullbub, 0, 1, uint8_t, 2, uint16_t, DO_MUL)
91
+DO_2OP_L(vmullbuh, 0, 2, uint16_t, 4, uint32_t, DO_MUL)
92
+DO_2OP_L(vmullbuw, 0, 4, uint32_t, 8, uint64_t, DO_MUL)
93
+
94
+DO_2OP_L(vmulltsb, 1, 1, int8_t, 2, int16_t, DO_MUL)
95
+DO_2OP_L(vmulltsh, 1, 2, int16_t, 4, int32_t, DO_MUL)
96
+DO_2OP_L(vmulltsw, 1, 4, int32_t, 8, int64_t, DO_MUL)
97
+DO_2OP_L(vmulltub, 1, 1, uint8_t, 2, uint16_t, DO_MUL)
98
+DO_2OP_L(vmulltuh, 1, 2, uint16_t, 4, uint32_t, DO_MUL)
99
+DO_2OP_L(vmulltuw, 1, 4, uint32_t, 8, uint64_t, DO_MUL)
100
+
101
/*
102
* Because the computation type is at least twice as large as required,
103
* these work for both signed and unsigned source types.
104
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/target/arm/translate-mve.c
107
+++ b/target/arm/translate-mve.c
108
@@ -XXX,XX +XXX,XX @@ DO_2OP(VHADD_S, vhadds)
109
DO_2OP(VHADD_U, vhaddu)
110
DO_2OP(VHSUB_S, vhsubs)
111
DO_2OP(VHSUB_U, vhsubu)
112
+DO_2OP(VMULL_BS, vmullbs)
113
+DO_2OP(VMULL_BU, vmullbu)
114
+DO_2OP(VMULL_TS, vmullts)
115
+DO_2OP(VMULL_TU, vmulltu)
116
--
117
2.20.1
118
119
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
Implement the MVE VMLALDAV insn, which multiplies pairs of integer
2
2
elements, accumulating them into a 64-bit result in a pair of
3
The Aspeed SMC Controller can operate in different modes : Read, Fast
3
general-purpose registers.
4
Read, Write and User modes. When the User mode is configured, it
4
5
selects automatically the SPI slave device until the CE_STOP_ACTIVE
6
bit is set to 1. When any other modes are configured the device is
7
unselected. The HW logic handles the chip select automatically when
8
the flash is accessed through its AHB window.
9
10
When configuring the CEx Control Register, the User mode logic to
11
select and unselect the slave is incorrect and data corruption can be
12
seen on machines using two chips, witherspoon and romulus.
13
14
Rework the handler setting the CEx Control Register to fix this issue.
15
16
Fixes: 7c1c69bca43c ("ast2400: add SMC controllers (FMC and SPI)")
17
Signed-off-by: Cédric Le Goater <clg@kaod.org>
18
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
19
Message-id: 20200206112645.21275-3-clg@kaod.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210617121628.20116-20-peter.maydell@linaro.org
21
---
8
---
22
hw/ssi/aspeed_smc.c | 39 +++++++++++++++++++++++----------------
9
target/arm/helper-mve.h | 8 ++++
23
hw/ssi/trace-events | 1 +
10
target/arm/translate.h | 10 ++++
24
2 files changed, 24 insertions(+), 16 deletions(-)
11
target/arm/mve.decode | 15 ++++++
25
12
target/arm/mve_helper.c | 34 ++++++++++++++
26
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
13
target/arm/translate-mve.c | 96 ++++++++++++++++++++++++++++++++++++++
27
index XXXXXXX..XXXXXXX 100644
14
5 files changed, 163 insertions(+)
28
--- a/hw/ssi/aspeed_smc.c
15
29
+++ b/hw/ssi/aspeed_smc.c
16
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
30
@@ -XXX,XX +XXX,XX @@ static inline int aspeed_smc_flash_is_4byte(const AspeedSMCFlash *fl)
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper-mve.h
19
+++ b/target/arm/helper-mve.h
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+
25
+DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
26
+DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
+DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
+DEF_HELPER_FLAGS_4(mve_vmlaldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vmlaldavuh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
31
+DEF_HELPER_FLAGS_4(mve_vmlaldavuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
32
diff --git a/target/arm/translate.h b/target/arm/translate.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate.h
35
+++ b/target/arm/translate.h
36
@@ -XXX,XX +XXX,XX @@ static inline int negate(DisasContext *s, int x)
37
return -x;
38
}
39
40
+static inline int plus_1(DisasContext *s, int x)
41
+{
42
+ return x + 1;
43
+}
44
+
45
static inline int plus_2(DisasContext *s, int x)
46
{
47
return x + 2;
48
@@ -XXX,XX +XXX,XX @@ static inline int times_4(DisasContext *s, int x)
49
return x * 4;
50
}
51
52
+static inline int times_2_plus_1(DisasContext *s, int x)
53
+{
54
+ return x * 2 + 1;
55
+}
56
+
57
static inline int arm_dc_feature(DisasContext *dc, int feature)
58
{
59
return (dc->features & (1ULL << feature)) != 0;
60
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/mve.decode
63
+++ b/target/arm/mve.decode
64
@@ -XXX,XX +XXX,XX @@ VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
65
VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
66
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
67
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
68
+
69
+# multiply-add long dual accumulate
70
+# rdahi: bits [3:1] from insn, bit 0 is 1
71
+# rdalo: bits [3:1] from insn, bit 0 is 0
72
+%rdahi 20:3 !function=times_2_plus_1
73
+%rdalo 13:3 !function=times_2
74
+# size bit is 0 for 16 bit, 1 for 32 bit
75
+%size_16 16:1 !function=plus_1
76
+
77
+&vmlaldav rdahi rdalo size qn qm x a
78
+
79
+@vmlaldav .... .... . ... ... . ... . .... .... qm:3 . \
80
+ qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
81
+VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
82
+VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
83
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/mve_helper.c
86
+++ b/target/arm/mve_helper.c
87
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vhadds, do_vhadd_s)
88
DO_2OP_U(vhaddu, do_vhadd_u)
89
DO_2OP_S(vhsubs, do_vhsub_s)
90
DO_2OP_U(vhsubu, do_vhsub_u)
91
+
92
+
93
+/*
94
+ * Multiply add long dual accumulate ops.
95
+ */
96
+#define DO_LDAV(OP, ESIZE, TYPE, XCHG, EVENACC, ODDACC) \
97
+ uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
98
+ void *vm, uint64_t a) \
99
+ { \
100
+ uint16_t mask = mve_element_mask(env); \
101
+ unsigned e; \
102
+ TYPE *n = vn, *m = vm; \
103
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
104
+ if (mask & 1) { \
105
+ if (e & 1) { \
106
+ a ODDACC \
107
+ (int64_t)n[H##ESIZE(e - 1 * XCHG)] * m[H##ESIZE(e)]; \
108
+ } else { \
109
+ a EVENACC \
110
+ (int64_t)n[H##ESIZE(e + 1 * XCHG)] * m[H##ESIZE(e)]; \
111
+ } \
112
+ } \
113
+ } \
114
+ mve_advance_vpt(env); \
115
+ return a; \
116
+ }
117
+
118
+DO_LDAV(vmlaldavsh, 2, int16_t, false, +=, +=)
119
+DO_LDAV(vmlaldavxsh, 2, int16_t, true, +=, +=)
120
+DO_LDAV(vmlaldavsw, 4, int32_t, false, +=, +=)
121
+DO_LDAV(vmlaldavxsw, 4, int32_t, true, +=, +=)
122
+
123
+DO_LDAV(vmlaldavuh, 2, uint16_t, false, +=, +=)
124
+DO_LDAV(vmlaldavuw, 4, uint32_t, false, +=, +=)
125
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/translate-mve.c
128
+++ b/target/arm/translate-mve.c
129
@@ -XXX,XX +XXX,XX @@
130
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
131
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
132
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
133
+typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
134
135
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
136
static inline long mve_qreg_offset(unsigned reg)
137
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
31
}
138
}
32
}
139
}
33
140
34
-static inline bool aspeed_smc_is_ce_stop_active(const AspeedSMCFlash *fl)
141
+static bool mve_skip_first_beat(DisasContext *s)
35
+static void aspeed_smc_flash_do_select(AspeedSMCFlash *fl, bool unselect)
142
+{
143
+ /* Return true if PSR.ECI says we must skip the first beat of this insn */
144
+ switch (s->eci) {
145
+ case ECI_NONE:
146
+ return false;
147
+ case ECI_A0:
148
+ case ECI_A0A1:
149
+ case ECI_A0A1A2:
150
+ case ECI_A0A1A2B0:
151
+ return true;
152
+ default:
153
+ g_assert_not_reached();
154
+ }
155
+}
156
+
157
static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn)
36
{
158
{
37
- const AspeedSMCState *s = fl->controller;
159
TCGv_i32 addr;
38
+ AspeedSMCState *s = fl->controller;
160
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BS, vmullbs)
39
161
DO_2OP(VMULL_BU, vmullbu)
40
- return s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE;
162
DO_2OP(VMULL_TS, vmullts)
41
+ trace_aspeed_smc_flash_select(fl->id, unselect ? "un" : "");
163
DO_2OP(VMULL_TU, vmulltu)
42
+
164
+
43
+ qemu_set_irq(s->cs_lines[fl->id], unselect);
165
+static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
44
}
166
+ MVEGenDualAccOpFn *fn)
45
167
+{
46
static void aspeed_smc_flash_select(AspeedSMCFlash *fl)
168
+ TCGv_ptr qn, qm;
47
{
169
+ TCGv_i64 rda;
48
- AspeedSMCState *s = fl->controller;
170
+ TCGv_i32 rdalo, rdahi;
49
-
171
+
50
- s->regs[s->r_ctrl0 + fl->id] &= ~CTRL_CE_STOP_ACTIVE;
172
+ if (!dc_isar_feature(aa32_mve, s) ||
51
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
173
+ !mve_check_qreg_bank(s, a->qn | a->qm) ||
52
+ aspeed_smc_flash_do_select(fl, false);
174
+ !fn) {
53
}
175
+ return false;
54
176
+ }
55
static void aspeed_smc_flash_unselect(AspeedSMCFlash *fl)
177
+ /*
56
{
178
+ * rdahi == 13 is UNPREDICTABLE; rdahi == 15 is a related
57
- AspeedSMCState *s = fl->controller;
179
+ * encoding; rdalo always has bit 0 clear so cannot be 13 or 15.
58
-
180
+ */
59
- s->regs[s->r_ctrl0 + fl->id] |= CTRL_CE_STOP_ACTIVE;
181
+ if (a->rdahi == 13 || a->rdahi == 15) {
60
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
182
+ return false;
61
+ aspeed_smc_flash_do_select(fl, true);
183
+ }
62
}
184
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
63
185
+ return true;
64
static uint32_t aspeed_smc_check_segment_addr(const AspeedSMCFlash *fl,
186
+ }
65
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
187
+
66
},
188
+ qn = mve_qreg_ptr(a->qn);
67
};
189
+ qm = mve_qreg_ptr(a->qm);
68
190
+
69
-static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
191
+ /*
70
+static void aspeed_smc_flash_update_ctrl(AspeedSMCFlash *fl, uint32_t value)
192
+ * This insn is subject to beat-wise execution. Partial execution
71
{
193
+ * of an A=0 (no-accumulate) insn which does not execute the first
72
AspeedSMCState *s = fl->controller;
194
+ * beat must start with the current rda value, not 0.
73
+ bool unselect;
195
+ */
74
196
+ if (a->a || mve_skip_first_beat(s)) {
75
- s->snoop_index = aspeed_smc_is_ce_stop_active(fl) ? SNOOP_OFF : SNOOP_START;
197
+ rda = tcg_temp_new_i64();
76
+ /* User mode selects the CS, other modes unselect */
198
+ rdalo = load_reg(s, a->rdalo);
77
+ unselect = (value & CTRL_CMD_MODE_MASK) != CTRL_USERMODE;
199
+ rdahi = load_reg(s, a->rdahi);
78
200
+ tcg_gen_concat_i32_i64(rda, rdalo, rdahi);
79
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
201
+ tcg_temp_free_i32(rdalo);
80
+ /* A change of CTRL_CE_STOP_ACTIVE from 0 to 1, unselects the CS */
202
+ tcg_temp_free_i32(rdahi);
81
+ if (!(s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE) &&
203
+ } else {
82
+ value & CTRL_CE_STOP_ACTIVE) {
204
+ rda = tcg_const_i64(0);
83
+ unselect = true;
205
+ }
84
+ }
206
+
85
+
207
+ fn(rda, cpu_env, qn, qm, rda);
86
+ s->regs[s->r_ctrl0 + fl->id] = value;
208
+ tcg_temp_free_ptr(qn);
87
+
209
+ tcg_temp_free_ptr(qm);
88
+ s->snoop_index = unselect ? SNOOP_OFF : SNOOP_START;
210
+
89
+
211
+ rdalo = tcg_temp_new_i32();
90
+ aspeed_smc_flash_do_select(fl, unselect);
212
+ rdahi = tcg_temp_new_i32();
91
}
213
+ tcg_gen_extrl_i64_i32(rdalo, rda);
92
214
+ tcg_gen_extrh_i64_i32(rdahi, rda);
93
static void aspeed_smc_reset(DeviceState *d)
215
+ store_reg(s, a->rdalo, rdalo);
94
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
216
+ store_reg(s, a->rdahi, rdahi);
95
s->regs[addr] = value;
217
+ tcg_temp_free_i64(rda);
96
} else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
218
+ mve_update_eci(s);
97
int cs = addr - s->r_ctrl0;
219
+ return true;
98
- s->regs[addr] = value;
220
+}
99
- aspeed_smc_flash_update_cs(&s->flashes[cs]);
221
+
100
+ aspeed_smc_flash_update_ctrl(&s->flashes[cs], value);
222
+static bool trans_VMLALDAV_S(DisasContext *s, arg_vmlaldav *a)
101
} else if (addr >= R_SEG_ADDR0 &&
223
+{
102
addr < R_SEG_ADDR0 + s->ctrl->max_slaves) {
224
+ static MVEGenDualAccOpFn * const fns[4][2] = {
103
int cs = addr - R_SEG_ADDR0;
225
+ { NULL, NULL },
104
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
226
+ { gen_helper_mve_vmlaldavsh, gen_helper_mve_vmlaldavxsh },
105
index XXXXXXX..XXXXXXX 100644
227
+ { gen_helper_mve_vmlaldavsw, gen_helper_mve_vmlaldavxsw },
106
--- a/hw/ssi/trace-events
228
+ { NULL, NULL },
107
+++ b/hw/ssi/trace-events
229
+ };
108
@@ -XXX,XX +XXX,XX @@ aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int
230
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
109
aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
231
+}
110
aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
232
+
111
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
233
+static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
112
+aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
234
+{
235
+ static MVEGenDualAccOpFn * const fns[4][2] = {
236
+ { NULL, NULL },
237
+ { gen_helper_mve_vmlaldavuh, NULL },
238
+ { gen_helper_mve_vmlaldavuw, NULL },
239
+ { NULL, NULL },
240
+ };
241
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
242
+}
113
--
243
--
114
2.20.1
244
2.20.1
115
245
116
246
diff view generated by jsdifflib
New patch
1
Implement the MVE insn VMLSLDAV, which multiplies source elements,
2
alternately adding and subtracting them, and accumulates into a
3
64-bit result in a pair of general purpose registers.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210617121628.20116-21-peter.maydell@linaro.org
8
---
9
target/arm/helper-mve.h | 5 +++++
10
target/arm/mve.decode | 2 ++
11
target/arm/mve_helper.c | 5 +++++
12
target/arm/translate-mve.c | 11 +++++++++++
13
4 files changed, 23 insertions(+)
14
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-mve.h
18
+++ b/target/arm/helper-mve.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmlaldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
20
21
DEF_HELPER_FLAGS_4(mve_vmlaldavuh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
22
DEF_HELPER_FLAGS_4(mve_vmlaldavuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
23
+
24
+DEF_HELPER_FLAGS_4(mve_vmlsldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
25
+DEF_HELPER_FLAGS_4(mve_vmlsldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
26
+DEF_HELPER_FLAGS_4(mve_vmlsldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
+DEF_HELPER_FLAGS_4(mve_vmlsldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
33
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
34
VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
35
VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
36
+
37
+VMLSLDAV 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@ DO_LDAV(vmlaldavxsw, 4, int32_t, true, +=, +=)
43
44
DO_LDAV(vmlaldavuh, 2, uint16_t, false, +=, +=)
45
DO_LDAV(vmlaldavuw, 4, uint32_t, false, +=, +=)
46
+
47
+DO_LDAV(vmlsldavsh, 2, int16_t, false, +=, -=)
48
+DO_LDAV(vmlsldavxsh, 2, int16_t, true, +=, -=)
49
+DO_LDAV(vmlsldavsw, 4, int32_t, false, +=, -=)
50
+DO_LDAV(vmlsldavxsw, 4, int32_t, true, +=, -=)
51
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-mve.c
54
+++ b/target/arm/translate-mve.c
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
56
};
57
return do_long_dual_acc(s, a, fns[a->size][a->x]);
58
}
59
+
60
+static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
61
+{
62
+ static MVEGenDualAccOpFn * const fns[4][2] = {
63
+ { NULL, NULL },
64
+ { gen_helper_mve_vmlsldavsh, gen_helper_mve_vmlsldavxsh },
65
+ { gen_helper_mve_vmlsldavsw, gen_helper_mve_vmlsldavxsw },
66
+ { NULL, NULL },
67
+ };
68
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
69
+}
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement the MVE VRMLALDAVH and VRMLSLDAVH insns, which accumulate
2
the results of a rounded multiply of pairs of elements into a 72-bit
3
accumulator, returning the top 64 bits in a pair of general purpose
4
registers.
2
5
3
The Allwinner H3 is a System on Chip containing four ARM Cortex A7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
processor cores. Features and specifications include DDR2/DDR3 memory,
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
SD/MMC storage cards, 10/100/1000Mbit Ethernet, USB 2.0, HDMI and
8
Message-id: 20210617121628.20116-22-peter.maydell@linaro.org
6
various I/O modules. This commit adds support for the Allwinner H3
9
---
7
System on Chip.
10
target/arm/helper-mve.h | 8 ++++++++
11
target/arm/mve.decode | 7 +++++++
12
target/arm/mve_helper.c | 37 +++++++++++++++++++++++++++++++++++++
13
target/arm/translate-mve.c | 24 ++++++++++++++++++++++++
14
4 files changed, 76 insertions(+)
8
15
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
16
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20200311221854.30370-2-nieklinnenbank@gmail.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
hw/arm/Makefile.objs | 1 +
17
include/hw/arm/allwinner-h3.h | 106 +++++++++++
18
hw/arm/allwinner-h3.c | 327 ++++++++++++++++++++++++++++++++
19
MAINTAINERS | 7 +
20
default-configs/arm-softmmu.mak | 1 +
21
hw/arm/Kconfig | 8 +
22
6 files changed, 450 insertions(+)
23
create mode 100644 include/hw/arm/allwinner-h3.h
24
create mode 100644 hw/arm/allwinner-h3.c
25
26
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/Makefile.objs
18
--- a/target/arm/helper-mve.h
29
+++ b/hw/arm/Makefile.objs
19
+++ b/target/arm/helper-mve.h
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DIGIC) += digic.o
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmlsldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
31
obj-$(CONFIG_OMAP) += omap1.o omap2.o
21
DEF_HELPER_FLAGS_4(mve_vmlsldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
32
obj-$(CONFIG_STRONGARM) += strongarm.o
22
DEF_HELPER_FLAGS_4(mve_vmlsldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
33
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
23
DEF_HELPER_FLAGS_4(mve_vmlsldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o
24
+
35
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
25
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
36
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
26
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
37
obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
27
+
38
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
28
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
39
new file mode 100644
29
+
40
index XXXXXXX..XXXXXXX
30
+DEF_HELPER_FLAGS_4(mve_vrmlsldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
41
--- /dev/null
31
+DEF_HELPER_FLAGS_4(mve_vrmlsldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
42
+++ b/include/hw/arm/allwinner-h3.h
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
37
38
@vmlaldav .... .... . ... ... . ... . .... .... qm:3 . \
39
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
40
+@vmlaldav_nosz .... .... . ... ... . ... . .... .... qm:3 . \
41
+ qn=%qn rdahi=%rdahi rdalo=%rdalo size=0 &vmlaldav
42
VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
43
VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
44
45
VMLSLDAV 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav
46
+
47
+VRMLALDAVH_S 1110 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
48
+VRMLALDAVH_U 1111 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
49
+
50
+VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_nosz
51
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/mve_helper.c
54
+++ b/target/arm/mve_helper.c
43
@@ -XXX,XX +XXX,XX @@
55
@@ -XXX,XX +XXX,XX @@
44
+/*
56
*/
45
+ * Allwinner H3 System on Chip emulation
57
46
+ *
58
#include "qemu/osdep.h"
47
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
59
+#include "qemu/int128.h"
48
+ *
60
#include "cpu.h"
49
+ * This program is free software: you can redistribute it and/or modify
61
#include "internals.h"
50
+ * it under the terms of the GNU General Public License as published by
62
#include "vec_internal.h"
51
+ * the Free Software Foundation, either version 2 of the License, or
63
@@ -XXX,XX +XXX,XX @@ DO_LDAV(vmlsldavsh, 2, int16_t, false, +=, -=)
52
+ * (at your option) any later version.
64
DO_LDAV(vmlsldavxsh, 2, int16_t, true, +=, -=)
53
+ *
65
DO_LDAV(vmlsldavsw, 4, int32_t, false, +=, -=)
54
+ * This program is distributed in the hope that it will be useful,
66
DO_LDAV(vmlsldavxsw, 4, int32_t, true, +=, -=)
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
61
+ */
62
+
67
+
63
+/*
68
+/*
64
+ * The Allwinner H3 is a System on Chip containing four ARM Cortex A7
69
+ * Rounding multiply add long dual accumulate high: we must keep
65
+ * processor cores. Features and specifications include DDR2/DDR3 memory,
70
+ * a 72-bit internal accumulator value and return the top 64 bits.
66
+ * SD/MMC storage cards, 10/100/1000Mbit Ethernet, USB 2.0, HDMI and
67
+ * various I/O modules.
68
+ *
69
+ * This implementation is based on the following datasheet:
70
+ *
71
+ * https://linux-sunxi.org/File:Allwinner_H3_Datasheet_V1.2.pdf
72
+ *
73
+ * The latest datasheet and more info can be found on the Linux Sunxi wiki:
74
+ *
75
+ * https://linux-sunxi.org/H3
76
+ */
71
+ */
77
+
72
+#define DO_LDAVH(OP, ESIZE, TYPE, XCHG, EVENACC, ODDACC, TO128) \
78
+#ifndef HW_ARM_ALLWINNER_H3_H
73
+ uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
79
+#define HW_ARM_ALLWINNER_H3_H
74
+ void *vm, uint64_t a) \
80
+
75
+ { \
81
+#include "qom/object.h"
76
+ uint16_t mask = mve_element_mask(env); \
82
+#include "hw/arm/boot.h"
77
+ unsigned e; \
83
+#include "hw/timer/allwinner-a10-pit.h"
78
+ TYPE *n = vn, *m = vm; \
84
+#include "hw/intc/arm_gic.h"
79
+ Int128 acc = int128_lshift(TO128(a), 8); \
85
+#include "target/arm/cpu.h"
80
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
86
+
81
+ if (mask & 1) { \
87
+/**
82
+ if (e & 1) { \
88
+ * Allwinner H3 device list
83
+ acc = ODDACC(acc, TO128(n[H##ESIZE(e - 1 * XCHG)] * \
89
+ *
84
+ m[H##ESIZE(e)])); \
90
+ * This enumeration is can be used refer to a particular device in the
85
+ } else { \
91
+ * Allwinner H3 SoC. For example, the physical memory base address for
86
+ acc = EVENACC(acc, TO128(n[H##ESIZE(e + 1 * XCHG)] * \
92
+ * each device can be found in the AwH3State object in the memmap member
87
+ m[H##ESIZE(e)])); \
93
+ * using the device enum value as index.
88
+ } \
94
+ *
89
+ acc = int128_add(acc, 1 << 7); \
95
+ * @see AwH3State
90
+ } \
96
+ */
91
+ } \
97
+enum {
92
+ mve_advance_vpt(env); \
98
+ AW_H3_SRAM_A1,
93
+ return int128_getlo(int128_rshift(acc, 8)); \
99
+ AW_H3_SRAM_A2,
100
+ AW_H3_SRAM_C,
101
+ AW_H3_PIT,
102
+ AW_H3_UART0,
103
+ AW_H3_UART1,
104
+ AW_H3_UART2,
105
+ AW_H3_UART3,
106
+ AW_H3_GIC_DIST,
107
+ AW_H3_GIC_CPU,
108
+ AW_H3_GIC_HYP,
109
+ AW_H3_GIC_VCPU,
110
+ AW_H3_SDRAM
111
+};
112
+
113
+/** Total number of CPU cores in the H3 SoC */
114
+#define AW_H3_NUM_CPUS (4)
115
+
116
+/**
117
+ * Allwinner H3 object model
118
+ * @{
119
+ */
120
+
121
+/** Object type for the Allwinner H3 SoC */
122
+#define TYPE_AW_H3 "allwinner-h3"
123
+
124
+/** Convert input object to Allwinner H3 state object */
125
+#define AW_H3(obj) OBJECT_CHECK(AwH3State, (obj), TYPE_AW_H3)
126
+
127
+/** @} */
128
+
129
+/**
130
+ * Allwinner H3 object
131
+ *
132
+ * This struct contains the state of all the devices
133
+ * which are currently emulated by the H3 SoC code.
134
+ */
135
+typedef struct AwH3State {
136
+ /*< private >*/
137
+ DeviceState parent_obj;
138
+ /*< public >*/
139
+
140
+ ARMCPU cpus[AW_H3_NUM_CPUS];
141
+ const hwaddr *memmap;
142
+ AwA10PITState timer;
143
+ GICState gic;
144
+ MemoryRegion sram_a1;
145
+ MemoryRegion sram_a2;
146
+ MemoryRegion sram_c;
147
+} AwH3State;
148
+
149
+#endif /* HW_ARM_ALLWINNER_H3_H */
150
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
151
new file mode 100644
152
index XXXXXXX..XXXXXXX
153
--- /dev/null
154
+++ b/hw/arm/allwinner-h3.c
155
@@ -XXX,XX +XXX,XX @@
156
+/*
157
+ * Allwinner H3 System on Chip emulation
158
+ *
159
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
160
+ *
161
+ * This program is free software: you can redistribute it and/or modify
162
+ * it under the terms of the GNU General Public License as published by
163
+ * the Free Software Foundation, either version 2 of the License, or
164
+ * (at your option) any later version.
165
+ *
166
+ * This program is distributed in the hope that it will be useful,
167
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
168
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
169
+ * GNU General Public License for more details.
170
+ *
171
+ * You should have received a copy of the GNU General Public License
172
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
173
+ */
174
+
175
+#include "qemu/osdep.h"
176
+#include "exec/address-spaces.h"
177
+#include "qapi/error.h"
178
+#include "qemu/error-report.h"
179
+#include "qemu/module.h"
180
+#include "qemu/units.h"
181
+#include "hw/qdev-core.h"
182
+#include "cpu.h"
183
+#include "hw/sysbus.h"
184
+#include "hw/char/serial.h"
185
+#include "hw/misc/unimp.h"
186
+#include "sysemu/sysemu.h"
187
+#include "hw/arm/allwinner-h3.h"
188
+
189
+/* Memory map */
190
+const hwaddr allwinner_h3_memmap[] = {
191
+ [AW_H3_SRAM_A1] = 0x00000000,
192
+ [AW_H3_SRAM_A2] = 0x00044000,
193
+ [AW_H3_SRAM_C] = 0x00010000,
194
+ [AW_H3_PIT] = 0x01c20c00,
195
+ [AW_H3_UART0] = 0x01c28000,
196
+ [AW_H3_UART1] = 0x01c28400,
197
+ [AW_H3_UART2] = 0x01c28800,
198
+ [AW_H3_UART3] = 0x01c28c00,
199
+ [AW_H3_GIC_DIST] = 0x01c81000,
200
+ [AW_H3_GIC_CPU] = 0x01c82000,
201
+ [AW_H3_GIC_HYP] = 0x01c84000,
202
+ [AW_H3_GIC_VCPU] = 0x01c86000,
203
+ [AW_H3_SDRAM] = 0x40000000
204
+};
205
+
206
+/* List of unimplemented devices */
207
+struct AwH3Unimplemented {
208
+ const char *device_name;
209
+ hwaddr base;
210
+ hwaddr size;
211
+} unimplemented[] = {
212
+ { "d-engine", 0x01000000, 4 * MiB },
213
+ { "d-inter", 0x01400000, 128 * KiB },
214
+ { "syscon", 0x01c00000, 4 * KiB },
215
+ { "dma", 0x01c02000, 4 * KiB },
216
+ { "nfdc", 0x01c03000, 4 * KiB },
217
+ { "ts", 0x01c06000, 4 * KiB },
218
+ { "keymem", 0x01c0b000, 4 * KiB },
219
+ { "lcd0", 0x01c0c000, 4 * KiB },
220
+ { "lcd1", 0x01c0d000, 4 * KiB },
221
+ { "ve", 0x01c0e000, 4 * KiB },
222
+ { "mmc0", 0x01c0f000, 4 * KiB },
223
+ { "mmc1", 0x01c10000, 4 * KiB },
224
+ { "mmc2", 0x01c11000, 4 * KiB },
225
+ { "sid", 0x01c14000, 1 * KiB },
226
+ { "crypto", 0x01c15000, 4 * KiB },
227
+ { "msgbox", 0x01c17000, 4 * KiB },
228
+ { "spinlock", 0x01c18000, 4 * KiB },
229
+ { "usb0-otg", 0x01c19000, 4 * KiB },
230
+ { "usb0-phy", 0x01c1a000, 4 * KiB },
231
+ { "usb1-phy", 0x01c1b000, 4 * KiB },
232
+ { "usb2-phy", 0x01c1c000, 4 * KiB },
233
+ { "usb3-phy", 0x01c1d000, 4 * KiB },
234
+ { "smc", 0x01c1e000, 4 * KiB },
235
+ { "ccu", 0x01c20000, 1 * KiB },
236
+ { "pio", 0x01c20800, 1 * KiB },
237
+ { "owa", 0x01c21000, 1 * KiB },
238
+ { "pwm", 0x01c21400, 1 * KiB },
239
+ { "keyadc", 0x01c21800, 1 * KiB },
240
+ { "pcm0", 0x01c22000, 1 * KiB },
241
+ { "pcm1", 0x01c22400, 1 * KiB },
242
+ { "pcm2", 0x01c22800, 1 * KiB },
243
+ { "audio", 0x01c22c00, 2 * KiB },
244
+ { "smta", 0x01c23400, 1 * KiB },
245
+ { "ths", 0x01c25000, 1 * KiB },
246
+ { "uart0", 0x01c28000, 1 * KiB },
247
+ { "uart1", 0x01c28400, 1 * KiB },
248
+ { "uart2", 0x01c28800, 1 * KiB },
249
+ { "uart3", 0x01c28c00, 1 * KiB },
250
+ { "twi0", 0x01c2ac00, 1 * KiB },
251
+ { "twi1", 0x01c2b000, 1 * KiB },
252
+ { "twi2", 0x01c2b400, 1 * KiB },
253
+ { "scr", 0x01c2c400, 1 * KiB },
254
+ { "emac", 0x01c30000, 64 * KiB },
255
+ { "gpu", 0x01c40000, 64 * KiB },
256
+ { "hstmr", 0x01c60000, 4 * KiB },
257
+ { "dramcom", 0x01c62000, 4 * KiB },
258
+ { "dramctl0", 0x01c63000, 4 * KiB },
259
+ { "dramphy0", 0x01c65000, 4 * KiB },
260
+ { "spi0", 0x01c68000, 4 * KiB },
261
+ { "spi1", 0x01c69000, 4 * KiB },
262
+ { "csi", 0x01cb0000, 320 * KiB },
263
+ { "tve", 0x01e00000, 64 * KiB },
264
+ { "hdmi", 0x01ee0000, 128 * KiB },
265
+ { "rtc", 0x01f00000, 1 * KiB },
266
+ { "r_timer", 0x01f00800, 1 * KiB },
267
+ { "r_intc", 0x01f00c00, 1 * KiB },
268
+ { "r_wdog", 0x01f01000, 1 * KiB },
269
+ { "r_prcm", 0x01f01400, 1 * KiB },
270
+ { "r_twd", 0x01f01800, 1 * KiB },
271
+ { "r_cpucfg", 0x01f01c00, 1 * KiB },
272
+ { "r_cir-rx", 0x01f02000, 1 * KiB },
273
+ { "r_twi", 0x01f02400, 1 * KiB },
274
+ { "r_uart", 0x01f02800, 1 * KiB },
275
+ { "r_pio", 0x01f02c00, 1 * KiB },
276
+ { "r_pwm", 0x01f03800, 1 * KiB },
277
+ { "core-dbg", 0x3f500000, 128 * KiB },
278
+ { "tsgen-ro", 0x3f506000, 4 * KiB },
279
+ { "tsgen-ctl", 0x3f507000, 4 * KiB },
280
+ { "ddr-mem", 0x40000000, 2 * GiB },
281
+ { "n-brom", 0xffff0000, 32 * KiB },
282
+ { "s-brom", 0xffff0000, 64 * KiB }
283
+};
284
+
285
+/* Per Processor Interrupts */
286
+enum {
287
+ AW_H3_GIC_PPI_MAINT = 9,
288
+ AW_H3_GIC_PPI_HYPTIMER = 10,
289
+ AW_H3_GIC_PPI_VIRTTIMER = 11,
290
+ AW_H3_GIC_PPI_SECTIMER = 13,
291
+ AW_H3_GIC_PPI_PHYSTIMER = 14
292
+};
293
+
294
+/* Shared Processor Interrupts */
295
+enum {
296
+ AW_H3_GIC_SPI_UART0 = 0,
297
+ AW_H3_GIC_SPI_UART1 = 1,
298
+ AW_H3_GIC_SPI_UART2 = 2,
299
+ AW_H3_GIC_SPI_UART3 = 3,
300
+ AW_H3_GIC_SPI_TIMER0 = 18,
301
+ AW_H3_GIC_SPI_TIMER1 = 19,
302
+};
303
+
304
+/* Allwinner H3 general constants */
305
+enum {
306
+ AW_H3_GIC_NUM_SPI = 128
307
+};
308
+
309
+static void allwinner_h3_init(Object *obj)
310
+{
311
+ AwH3State *s = AW_H3(obj);
312
+
313
+ s->memmap = allwinner_h3_memmap;
314
+
315
+ for (int i = 0; i < AW_H3_NUM_CPUS; i++) {
316
+ object_initialize_child(obj, "cpu[*]", &s->cpus[i], sizeof(s->cpus[i]),
317
+ ARM_CPU_TYPE_NAME("cortex-a7"),
318
+ &error_abort, NULL);
319
+ }
94
+ }
320
+
95
+
321
+ sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic),
96
+DO_LDAVH(vrmlaldavhsw, 4, int32_t, false, int128_add, int128_add, int128_makes64)
322
+ TYPE_ARM_GIC);
97
+DO_LDAVH(vrmlaldavhxsw, 4, int32_t, true, int128_add, int128_add, int128_makes64)
323
+
98
+
324
+ sysbus_init_child_obj(obj, "timer", &s->timer, sizeof(s->timer),
99
+DO_LDAVH(vrmlaldavhuw, 4, uint32_t, false, int128_add, int128_add, int128_make64)
325
+ TYPE_AW_A10_PIT);
100
+
326
+ object_property_add_alias(obj, "clk0-freq", OBJECT(&s->timer),
101
+DO_LDAVH(vrmlsldavhsw, 4, int32_t, false, int128_add, int128_sub, int128_makes64)
327
+ "clk0-freq", &error_abort);
102
+DO_LDAVH(vrmlsldavhxsw, 4, int32_t, true, int128_add, int128_sub, int128_makes64)
328
+ object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
103
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
329
+ "clk1-freq", &error_abort);
104
index XXXXXXX..XXXXXXX 100644
105
--- a/target/arm/translate-mve.c
106
+++ b/target/arm/translate-mve.c
107
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
108
};
109
return do_long_dual_acc(s, a, fns[a->size][a->x]);
110
}
111
+
112
+static bool trans_VRMLALDAVH_S(DisasContext *s, arg_vmlaldav *a)
113
+{
114
+ static MVEGenDualAccOpFn * const fns[] = {
115
+ gen_helper_mve_vrmlaldavhsw, gen_helper_mve_vrmlaldavhxsw,
116
+ };
117
+ return do_long_dual_acc(s, a, fns[a->x]);
330
+}
118
+}
331
+
119
+
332
+static void allwinner_h3_realize(DeviceState *dev, Error **errp)
120
+static bool trans_VRMLALDAVH_U(DisasContext *s, arg_vmlaldav *a)
333
+{
121
+{
334
+ AwH3State *s = AW_H3(dev);
122
+ static MVEGenDualAccOpFn * const fns[] = {
335
+ unsigned i;
123
+ gen_helper_mve_vrmlaldavhuw, NULL,
336
+
124
+ };
337
+ /* CPUs */
125
+ return do_long_dual_acc(s, a, fns[a->x]);
338
+ for (i = 0; i < AW_H3_NUM_CPUS; i++) {
339
+
340
+ /* Provide Power State Coordination Interface */
341
+ qdev_prop_set_int32(DEVICE(&s->cpus[i]), "psci-conduit",
342
+ QEMU_PSCI_CONDUIT_HVC);
343
+
344
+ /* Disable secondary CPUs */
345
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
346
+ i > 0);
347
+
348
+ /* All exception levels required */
349
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el3", true);
350
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el2", true);
351
+
352
+ /* Mark realized */
353
+ qdev_init_nofail(DEVICE(&s->cpus[i]));
354
+ }
355
+
356
+ /* Generic Interrupt Controller */
357
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", AW_H3_GIC_NUM_SPI +
358
+ GIC_INTERNAL);
359
+ qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
360
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", AW_H3_NUM_CPUS);
361
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-security-extensions", false);
362
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-virtualization-extensions", true);
363
+ qdev_init_nofail(DEVICE(&s->gic));
364
+
365
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0, s->memmap[AW_H3_GIC_DIST]);
366
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1, s->memmap[AW_H3_GIC_CPU]);
367
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2, s->memmap[AW_H3_GIC_HYP]);
368
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3, s->memmap[AW_H3_GIC_VCPU]);
369
+
370
+ /*
371
+ * Wire the outputs from each CPU's generic timer and the GICv3
372
+ * maintenance interrupt signal to the appropriate GIC PPI inputs,
373
+ * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
374
+ */
375
+ for (i = 0; i < AW_H3_NUM_CPUS; i++) {
376
+ DeviceState *cpudev = DEVICE(&s->cpus[i]);
377
+ int ppibase = AW_H3_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS;
378
+ int irq;
379
+ /*
380
+ * Mapping from the output timer irq lines from the CPU to the
381
+ * GIC PPI inputs used for this board.
382
+ */
383
+ const int timer_irq[] = {
384
+ [GTIMER_PHYS] = AW_H3_GIC_PPI_PHYSTIMER,
385
+ [GTIMER_VIRT] = AW_H3_GIC_PPI_VIRTTIMER,
386
+ [GTIMER_HYP] = AW_H3_GIC_PPI_HYPTIMER,
387
+ [GTIMER_SEC] = AW_H3_GIC_PPI_SECTIMER,
388
+ };
389
+
390
+ /* Connect CPU timer outputs to GIC PPI inputs */
391
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
392
+ qdev_connect_gpio_out(cpudev, irq,
393
+ qdev_get_gpio_in(DEVICE(&s->gic),
394
+ ppibase + timer_irq[irq]));
395
+ }
396
+
397
+ /* Connect GIC outputs to CPU interrupt inputs */
398
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
399
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
400
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + AW_H3_NUM_CPUS,
401
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
402
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (2 * AW_H3_NUM_CPUS),
403
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
404
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (3 * AW_H3_NUM_CPUS),
405
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
406
+
407
+ /* GIC maintenance signal */
408
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (4 * AW_H3_NUM_CPUS),
409
+ qdev_get_gpio_in(DEVICE(&s->gic),
410
+ ppibase + AW_H3_GIC_PPI_MAINT));
411
+ }
412
+
413
+ /* Timer */
414
+ qdev_init_nofail(DEVICE(&s->timer));
415
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, s->memmap[AW_H3_PIT]);
416
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0,
417
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TIMER0));
418
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 1,
419
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TIMER1));
420
+
421
+ /* SRAM */
422
+ memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
423
+ 64 * KiB, &error_abort);
424
+ memory_region_init_ram(&s->sram_a2, OBJECT(dev), "sram A2",
425
+ 32 * KiB, &error_abort);
426
+ memory_region_init_ram(&s->sram_c, OBJECT(dev), "sram C",
427
+ 44 * KiB, &error_abort);
428
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_A1],
429
+ &s->sram_a1);
430
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_A2],
431
+ &s->sram_a2);
432
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_C],
433
+ &s->sram_c);
434
+
435
+ /* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
436
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
437
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
438
+ 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
439
+ /* UART1 */
440
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART1], 2,
441
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART1),
442
+ 115200, serial_hd(1), DEVICE_NATIVE_ENDIAN);
443
+ /* UART2 */
444
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART2], 2,
445
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART2),
446
+ 115200, serial_hd(2), DEVICE_NATIVE_ENDIAN);
447
+ /* UART3 */
448
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART3], 2,
449
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART3),
450
+ 115200, serial_hd(3), DEVICE_NATIVE_ENDIAN);
451
+
452
+ /* Unimplemented devices */
453
+ for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
454
+ create_unimplemented_device(unimplemented[i].device_name,
455
+ unimplemented[i].base,
456
+ unimplemented[i].size);
457
+ }
458
+}
126
+}
459
+
127
+
460
+static void allwinner_h3_class_init(ObjectClass *oc, void *data)
128
+static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
461
+{
129
+{
462
+ DeviceClass *dc = DEVICE_CLASS(oc);
130
+ static MVEGenDualAccOpFn * const fns[] = {
463
+
131
+ gen_helper_mve_vrmlsldavhsw, gen_helper_mve_vrmlsldavhxsw,
464
+ dc->realize = allwinner_h3_realize;
132
+ };
465
+ /* Reason: uses serial_hd() in realize function */
133
+ return do_long_dual_acc(s, a, fns[a->x]);
466
+ dc->user_creatable = false;
467
+}
134
+}
468
+
469
+static const TypeInfo allwinner_h3_type_info = {
470
+ .name = TYPE_AW_H3,
471
+ .parent = TYPE_DEVICE,
472
+ .instance_size = sizeof(AwH3State),
473
+ .instance_init = allwinner_h3_init,
474
+ .class_init = allwinner_h3_class_init,
475
+};
476
+
477
+static void allwinner_h3_register_types(void)
478
+{
479
+ type_register_static(&allwinner_h3_type_info);
480
+}
481
+
482
+type_init(allwinner_h3_register_types)
483
diff --git a/MAINTAINERS b/MAINTAINERS
484
index XXXXXXX..XXXXXXX 100644
485
--- a/MAINTAINERS
486
+++ b/MAINTAINERS
487
@@ -XXX,XX +XXX,XX @@ F: hw/*/allwinner*
488
F: include/hw/*/allwinner*
489
F: hw/arm/cubieboard.c
490
491
+Allwinner-h3
492
+M: Niek Linnenbank <nieklinnenbank@gmail.com>
493
+L: qemu-arm@nongnu.org
494
+S: Maintained
495
+F: hw/*/allwinner-h3*
496
+F: include/hw/*/allwinner-h3*
497
+
498
ARM PrimeCell and CMSDK devices
499
M: Peter Maydell <peter.maydell@linaro.org>
500
L: qemu-arm@nongnu.org
501
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
502
index XXXXXXX..XXXXXXX 100644
503
--- a/default-configs/arm-softmmu.mak
504
+++ b/default-configs/arm-softmmu.mak
505
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX25=y
506
CONFIG_FSL_IMX7=y
507
CONFIG_FSL_IMX6UL=y
508
CONFIG_SEMIHOSTING=y
509
+CONFIG_ALLWINNER_H3=y
510
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
511
index XXXXXXX..XXXXXXX 100644
512
--- a/hw/arm/Kconfig
513
+++ b/hw/arm/Kconfig
514
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
515
select SERIAL
516
select UNIMP
517
518
+config ALLWINNER_H3
519
+ bool
520
+ select ALLWINNER_A10_PIT
521
+ select SERIAL
522
+ select ARM_TIMER
523
+ select ARM_GIC
524
+ select UNIMP
525
+
526
config RASPI
527
bool
528
select FRAMEBUFFER
529
--
135
--
530
2.20.1
136
2.20.1
531
137
532
138
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement the scalar form of the MVE VADD insn. This takes the
2
scalar operand from a general purpose register.
2
3
3
A real Allwinner H3 SoC contains a Boot ROM which is the
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
first code that runs right after the SoC is powered on.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
The Boot ROM is responsible for loading user code (e.g. a bootloader)
6
Message-id: 20210617121628.20116-23-peter.maydell@linaro.org
6
from any of the supported external devices and writing the downloaded
7
---
7
code to internal SRAM. After loading the SoC begins executing the code
8
target/arm/helper-mve.h | 4 ++++
8
written to SRAM.
9
target/arm/mve.decode | 7 ++++++
10
target/arm/mve_helper.c | 22 +++++++++++++++++++
11
target/arm/translate-mve.c | 45 ++++++++++++++++++++++++++++++++++++++
12
4 files changed, 78 insertions(+)
9
13
10
This commits adds emulation of the Boot ROM firmware setup functionality
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
11
by loading user code from SD card in the A1 SRAM. While the A1 SRAM is
12
64KiB, we limit the size to 32KiB because the real H3 Boot ROM also rejects
13
sizes larger than 32KiB. For reference, this behaviour is documented
14
by the Linux Sunxi project wiki at:
15
16
https://linux-sunxi.org/BROM#U-Boot_SPL_limitations
17
18
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
20
Message-id: 20200311221854.30370-11-nieklinnenbank@gmail.com
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
include/hw/arm/allwinner-h3.h | 21 +++++++++++++++++++++
24
hw/arm/allwinner-h3.c | 17 +++++++++++++++++
25
hw/arm/orangepi.c | 5 +++++
26
3 files changed, 43 insertions(+)
27
28
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
29
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/allwinner-h3.h
16
--- a/target/arm/helper-mve.h
31
+++ b/include/hw/arm/allwinner-h3.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
22
+DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+
26
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@
33
#include "hw/sd/allwinner-sdhost.h"
34
&vldr_vstr rn qd imm p a w size l u
34
#include "hw/net/allwinner-sun8i-emac.h"
35
&1op qd qm size
35
#include "target/arm/cpu.h"
36
&2op qd qm qn size
36
+#include "sysemu/block-backend.h"
37
+&2scalar qd qn rm size
37
38
38
/**
39
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
39
* Allwinner H3 device list
40
# Note that both Rn and Qd are 3 bits only (no D bit)
40
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
41
@@ -XXX,XX +XXX,XX @@
41
MemoryRegion sram_c;
42
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
42
} AwH3State;
43
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
43
44
44
+/**
45
+@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
45
+ * Emulate Boot ROM firmware setup functionality.
46
+ *
47
+ * A real Allwinner H3 SoC contains a Boot ROM
48
+ * which is the first code that runs right after
49
+ * the SoC is powered on. The Boot ROM is responsible
50
+ * for loading user code (e.g. a bootloader) from any
51
+ * of the supported external devices and writing the
52
+ * downloaded code to internal SRAM. After loading the SoC
53
+ * begins executing the code written to SRAM.
54
+ *
55
+ * This function emulates the Boot ROM by copying 32 KiB
56
+ * of data from the given block device and writes it to
57
+ * the start of the first internal SRAM memory.
58
+ *
59
+ * @s: Allwinner H3 state object pointer
60
+ * @blk: Block backend device object pointer
61
+ */
62
+void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk);
63
+
46
+
64
#endif /* HW_ARM_ALLWINNER_H3_H */
47
# Vector loads and stores
65
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
48
49
# Widening loads and narrowing stores:
50
@@ -XXX,XX +XXX,XX @@ VRMLALDAVH_S 1110 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_no
51
VRMLALDAVH_U 1111 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
52
53
VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_nosz
54
+
55
+# Scalar operations
56
+
57
+VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
66
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/allwinner-h3.c
60
--- a/target/arm/mve_helper.c
68
+++ b/hw/arm/allwinner-h3.c
61
+++ b/target/arm/mve_helper.c
69
@@ -XXX,XX +XXX,XX @@
62
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vhsubs, do_vhsub_s)
70
#include "hw/char/serial.h"
63
DO_2OP_U(vhsubu, do_vhsub_u)
71
#include "hw/misc/unimp.h"
64
72
#include "hw/usb/hcd-ehci.h"
65
73
+#include "hw/loader.h"
66
+#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
74
#include "sysemu/sysemu.h"
67
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
75
#include "hw/arm/allwinner-h3.h"
68
+ uint32_t rm) \
76
69
+ { \
77
@@ -XXX,XX +XXX,XX @@ enum {
70
+ TYPE *d = vd, *n = vn; \
78
AW_H3_GIC_NUM_SPI = 128
71
+ TYPE m = rm; \
79
};
72
+ uint16_t mask = mve_element_mask(env); \
80
73
+ unsigned e; \
81
+void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk)
74
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
82
+{
75
+ mergemask(&d[H##ESIZE(e)], FN(n[H##ESIZE(e)], m), mask); \
83
+ const int64_t rom_size = 32 * KiB;
76
+ } \
84
+ g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
77
+ mve_advance_vpt(env); \
85
+
86
+ if (blk_pread(blk, 8 * KiB, buffer, rom_size) < 0) {
87
+ error_setg(&error_fatal, "%s: failed to read BlockBackend data",
88
+ __func__);
89
+ return;
90
+ }
78
+ }
91
+
79
+
92
+ rom_add_blob("allwinner-h3.bootrom", buffer, rom_size,
80
+/* provide unsigned 2-op scalar helpers for all sizes */
93
+ rom_size, s->memmap[AW_H3_SRAM_A1],
81
+#define DO_2OP_SCALAR_U(OP, FN) \
94
+ NULL, NULL, NULL, NULL, false);
82
+ DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
83
+ DO_2OP_SCALAR(OP##h, 2, uint16_t, FN) \
84
+ DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
85
+
86
+DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
87
+
88
/*
89
* Multiply add long dual accumulate ops.
90
*/
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/translate-mve.c
94
+++ b/target/arm/translate-mve.c
95
@@ -XXX,XX +XXX,XX @@
96
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
97
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
98
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
99
+typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
100
typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
101
102
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
103
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BU, vmullbu)
104
DO_2OP(VMULL_TS, vmullts)
105
DO_2OP(VMULL_TU, vmulltu)
106
107
+static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
108
+ MVEGenTwoOpScalarFn fn)
109
+{
110
+ TCGv_ptr qd, qn;
111
+ TCGv_i32 rm;
112
+
113
+ if (!dc_isar_feature(aa32_mve, s) ||
114
+ !mve_check_qreg_bank(s, a->qd | a->qn) ||
115
+ !fn) {
116
+ return false;
117
+ }
118
+ if (a->rm == 13 || a->rm == 15) {
119
+ /* UNPREDICTABLE */
120
+ return false;
121
+ }
122
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
123
+ return true;
124
+ }
125
+
126
+ qd = mve_qreg_ptr(a->qd);
127
+ qn = mve_qreg_ptr(a->qn);
128
+ rm = load_reg(s, a->rm);
129
+ fn(cpu_env, qd, qn, rm);
130
+ tcg_temp_free_i32(rm);
131
+ tcg_temp_free_ptr(qd);
132
+ tcg_temp_free_ptr(qn);
133
+ mve_update_eci(s);
134
+ return true;
95
+}
135
+}
96
+
136
+
97
static void allwinner_h3_init(Object *obj)
137
+#define DO_2OP_SCALAR(INSN, FN) \
138
+ static bool trans_##INSN(DisasContext *s, arg_2scalar *a) \
139
+ { \
140
+ static MVEGenTwoOpScalarFn * const fns[] = { \
141
+ gen_helper_mve_##FN##b, \
142
+ gen_helper_mve_##FN##h, \
143
+ gen_helper_mve_##FN##w, \
144
+ NULL, \
145
+ }; \
146
+ return do_2op_scalar(s, a, fns[a->size]); \
147
+ }
148
+
149
+DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
150
+
151
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
152
MVEGenDualAccOpFn *fn)
98
{
153
{
99
AwH3State *s = AW_H3(obj);
100
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/hw/arm/orangepi.c
103
+++ b/hw/arm/orangepi.c
104
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
105
memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
106
machine->ram);
107
108
+ /* Load target kernel or start using BootROM */
109
+ if (!machine->kernel_filename && blk_is_available(blk)) {
110
+ /* Use Boot ROM to copy data from SD card to SRAM */
111
+ allwinner_h3_bootrom_setup(h3, blk);
112
+ }
113
orangepi_binfo.loader_start = h3->memmap[AW_H3_SDRAM];
114
orangepi_binfo.ram_size = machine->ram_size;
115
arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
116
--
154
--
117
2.20.1
155
2.20.1
118
156
119
157
diff view generated by jsdifflib
New patch
1
Implement the scalar forms of the MVE VSUB and VMUL insns.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-24-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 8 ++++++++
8
target/arm/mve.decode | 2 ++
9
target/arm/mve_helper.c | 2 ++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 14 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
21
+DEF_HELPER_FLAGS_4(mve_vsub_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
+DEF_HELPER_FLAGS_4(mve_vsub_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vsub_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+
25
+DEF_HELPER_FLAGS_4(mve_vmul_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(mve_vmul_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(mve_vmul_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
+
29
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
30
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
31
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_no
37
# Scalar operations
38
39
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
40
+VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
41
+VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
47
DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
48
49
DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
50
+DO_2OP_SCALAR_U(vsub_scalar, DO_SUB)
51
+DO_2OP_SCALAR_U(vmul_scalar, DO_MUL)
52
53
/*
54
* Multiply add long dual accumulate ops.
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-mve.c
58
+++ b/target/arm/translate-mve.c
59
@@ -XXX,XX +XXX,XX @@ static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
60
}
61
62
DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
63
+DO_2OP_SCALAR(VSUB_scalar, vsub_scalar)
64
+DO_2OP_SCALAR(VMUL_scalar, vmul_scalar)
65
66
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
67
MVEGenDualAccOpFn *fn)
68
--
69
2.20.1
70
71
diff view generated by jsdifflib
1
Fix a couple of comment typos.
1
Implement the scalar variants of the MVE VHADD and VHSUB insns.
2
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200303174950.3298-5-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-25-peter.maydell@linaro.org
6
---
6
---
7
target/arm/helper.c | 2 +-
7
target/arm/helper-mve.h | 16 ++++++++++++++++
8
target/arm/translate.c | 2 +-
8
target/arm/mve.decode | 4 ++++
9
2 files changed, 2 insertions(+), 2 deletions(-)
9
target/arm/mve_helper.c | 8 ++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 32 insertions(+)
10
12
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
15
--- a/target/arm/helper-mve.h
14
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper-mve.h
15
@@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmul_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
DEF_HELPER_FLAGS_4(mve_vmul_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_4(mve_vmul_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
21
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+
25
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
+
29
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
+
33
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
+
37
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
38
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
39
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
40
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/mve.decode
43
+++ b/target/arm/mve.decode
44
@@ -XXX,XX +XXX,XX @@ VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_no
45
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
46
VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
47
VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
48
+VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
49
+VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
50
+VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
51
+VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
57
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
58
DO_2OP_SCALAR(OP##h, 2, uint16_t, FN) \
59
DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
60
+#define DO_2OP_SCALAR_S(OP, FN) \
61
+ DO_2OP_SCALAR(OP##b, 1, int8_t, FN) \
62
+ DO_2OP_SCALAR(OP##h, 2, int16_t, FN) \
63
+ DO_2OP_SCALAR(OP##w, 4, int32_t, FN)
64
65
DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
66
DO_2OP_SCALAR_U(vsub_scalar, DO_SUB)
67
DO_2OP_SCALAR_U(vmul_scalar, DO_MUL)
68
+DO_2OP_SCALAR_S(vhadds_scalar, do_vhadd_s)
69
+DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
70
+DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
71
+DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
16
72
17
/*
73
/*
18
* If we have triggered a EL state change we can't rely on the
74
* Multiply add long dual accumulate ops.
19
- * translator having passed it too us, we need to recompute.
75
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
20
+ * translator having passed it to us, we need to recompute.
21
*/
22
void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env)
23
{
24
diff --git a/target/arm/translate.c b/target/arm/translate.c
25
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/translate.c
77
--- a/target/arm/translate-mve.c
27
+++ b/target/arm/translate.c
78
+++ b/target/arm/translate-mve.c
28
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
79
@@ -XXX,XX +XXX,XX @@ static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
29
80
DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
30
if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
81
DO_2OP_SCALAR(VSUB_scalar, vsub_scalar)
31
/*
82
DO_2OP_SCALAR(VMUL_scalar, vmul_scalar)
32
- * A write to any coprocessor regiser that ends a TB
83
+DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
33
+ * A write to any coprocessor register that ends a TB
84
+DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
34
* must rebuild the hflags for the next TB.
85
+DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
35
*/
86
+DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
36
TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
87
88
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
89
MVEGenDualAccOpFn *fn)
37
--
90
--
38
2.20.1
91
2.20.1
39
92
40
93
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement the MVE VBRSR insn, which reverses a specified
2
number of bits in each element, setting the rest to zero.
2
3
3
The Security Identifier device found in various Allwinner System on Chip
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
designs gives applications a per-board unique identifier. This commit
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
adds support for the Allwinner Security Identifier using a 128-bit
6
Message-id: 20210617121628.20116-26-peter.maydell@linaro.org
6
UUID value as input.
7
---
8
target/arm/helper-mve.h | 4 ++++
9
target/arm/mve.decode | 1 +
10
target/arm/mve_helper.c | 43 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 1 +
12
4 files changed, 49 insertions(+)
7
13
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Message-id: 20200311221854.30370-8-nieklinnenbank@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/misc/Makefile.objs | 1 +
14
include/hw/arm/allwinner-h3.h | 3 +
15
include/hw/misc/allwinner-sid.h | 60 ++++++++++++
16
hw/arm/allwinner-h3.c | 11 ++-
17
hw/arm/orangepi.c | 8 ++
18
hw/misc/allwinner-sid.c | 168 ++++++++++++++++++++++++++++++++
19
hw/misc/trace-events | 4 +
20
7 files changed, 254 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/misc/allwinner-sid.h
22
create mode 100644 hw/misc/allwinner-sid.c
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/Makefile.objs
16
--- a/target/arm/helper-mve.h
27
+++ b/hw/misc/Makefile.objs
17
+++ b/target/arm/helper-mve.h
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
19
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
20
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
21
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sid.o
22
+DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
23
+DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
common-obj-$(CONFIG_NSERIES) += cbus.o
24
+DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
25
+
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
26
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
31
--- a/target/arm/mve.decode
39
+++ b/include/hw/arm/allwinner-h3.h
32
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@ VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
41
#include "hw/misc/allwinner-h3-ccu.h"
34
VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
42
#include "hw/misc/allwinner-cpucfg.h"
35
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
43
#include "hw/misc/allwinner-h3-sysctrl.h"
36
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
44
+#include "hw/misc/allwinner-sid.h"
37
+VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
45
#include "target/arm/cpu.h"
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
46
47
/**
48
@@ -XXX,XX +XXX,XX @@ enum {
49
AW_H3_SRAM_A2,
50
AW_H3_SRAM_C,
51
AW_H3_SYSCTRL,
52
+ AW_H3_SID,
53
AW_H3_EHCI0,
54
AW_H3_OHCI0,
55
AW_H3_EHCI1,
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
57
AwH3ClockCtlState ccu;
58
AwCpuCfgState cpucfg;
59
AwH3SysCtrlState sysctrl;
60
+ AwSidState sid;
61
GICState gic;
62
MemoryRegion sram_a1;
63
MemoryRegion sram_a2;
64
diff --git a/include/hw/misc/allwinner-sid.h b/include/hw/misc/allwinner-sid.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/allwinner-sid.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * Allwinner Security ID emulation
72
+ *
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
74
+ *
75
+ * This program is free software: you can redistribute it and/or modify
76
+ * it under the terms of the GNU General Public License as published by
77
+ * the Free Software Foundation, either version 2 of the License, or
78
+ * (at your option) any later version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful,
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
+ * GNU General Public License for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
88
+
89
+#ifndef HW_MISC_ALLWINNER_SID_H
90
+#define HW_MISC_ALLWINNER_SID_H
91
+
92
+#include "qom/object.h"
93
+#include "hw/sysbus.h"
94
+#include "qemu/uuid.h"
95
+
96
+/**
97
+ * Object model
98
+ * @{
99
+ */
100
+
101
+#define TYPE_AW_SID "allwinner-sid"
102
+#define AW_SID(obj) \
103
+ OBJECT_CHECK(AwSidState, (obj), TYPE_AW_SID)
104
+
105
+/** @} */
106
+
107
+/**
108
+ * Allwinner Security ID object instance state
109
+ */
110
+typedef struct AwSidState {
111
+ /*< private >*/
112
+ SysBusDevice parent_obj;
113
+ /*< public >*/
114
+
115
+ /** Maps I/O registers in physical memory */
116
+ MemoryRegion iomem;
117
+
118
+ /** Control register defines how and what to read */
119
+ uint32_t control;
120
+
121
+ /** RdKey register contains the data retrieved by the device */
122
+ uint32_t rdkey;
123
+
124
+ /** Stores the emulated device identifier */
125
+ QemuUUID identifier;
126
+
127
+} AwSidState;
128
+
129
+#endif /* HW_MISC_ALLWINNER_SID_H */
130
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
131
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/arm/allwinner-h3.c
40
--- a/target/arm/mve_helper.c
133
+++ b/hw/arm/allwinner-h3.c
41
+++ b/target/arm/mve_helper.c
134
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
42
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
135
[AW_H3_SRAM_A2] = 0x00044000,
43
DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
136
[AW_H3_SRAM_C] = 0x00010000,
44
DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
137
[AW_H3_SYSCTRL] = 0x01c00000,
45
138
+ [AW_H3_SID] = 0x01c14000,
46
+static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
139
[AW_H3_EHCI0] = 0x01c1a000,
140
[AW_H3_OHCI0] = 0x01c1a400,
141
[AW_H3_EHCI1] = 0x01c1b000,
142
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
143
{ "mmc0", 0x01c0f000, 4 * KiB },
144
{ "mmc1", 0x01c10000, 4 * KiB },
145
{ "mmc2", 0x01c11000, 4 * KiB },
146
- { "sid", 0x01c14000, 1 * KiB },
147
{ "crypto", 0x01c15000, 4 * KiB },
148
{ "msgbox", 0x01c17000, 4 * KiB },
149
{ "spinlock", 0x01c18000, 4 * KiB },
150
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
151
152
sysbus_init_child_obj(obj, "cpucfg", &s->cpucfg, sizeof(s->cpucfg),
153
TYPE_AW_CPUCFG);
154
+
155
+ sysbus_init_child_obj(obj, "sid", &s->sid, sizeof(s->sid),
156
+ TYPE_AW_SID);
157
+ object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
158
+ "identifier", &error_abort);
159
}
160
161
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
162
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
163
qdev_init_nofail(DEVICE(&s->cpucfg));
164
sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0, s->memmap[AW_H3_CPUCFG]);
165
166
+ /* Security Identifier */
167
+ qdev_init_nofail(DEVICE(&s->sid));
168
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H3_SID]);
169
+
170
/* Universal Serial Bus */
171
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
172
qdev_get_gpio_in(DEVICE(&s->gic),
173
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/hw/arm/orangepi.c
176
+++ b/hw/arm/orangepi.c
177
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
178
object_property_set_int(OBJECT(h3), 24 * 1000 * 1000, "clk1-freq",
179
&error_abort);
180
181
+ /* Setup SID properties. Currently using a default fixed SID identifier. */
182
+ if (qemu_uuid_is_null(&h3->sid.identifier)) {
183
+ qdev_prop_set_string(DEVICE(h3), "identifier",
184
+ "02c00081-1111-2222-3333-000044556677");
185
+ } else if (ldl_be_p(&h3->sid.identifier.data[0]) != 0x02c00081) {
186
+ warn_report("Security Identifier value does not include H3 prefix");
187
+ }
188
+
189
/* Mark H3 object realized */
190
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
191
192
diff --git a/hw/misc/allwinner-sid.c b/hw/misc/allwinner-sid.c
193
new file mode 100644
194
index XXXXXXX..XXXXXXX
195
--- /dev/null
196
+++ b/hw/misc/allwinner-sid.c
197
@@ -XXX,XX +XXX,XX @@
198
+/*
199
+ * Allwinner Security ID emulation
200
+ *
201
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
202
+ *
203
+ * This program is free software: you can redistribute it and/or modify
204
+ * it under the terms of the GNU General Public License as published by
205
+ * the Free Software Foundation, either version 2 of the License, or
206
+ * (at your option) any later version.
207
+ *
208
+ * This program is distributed in the hope that it will be useful,
209
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
210
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
211
+ * GNU General Public License for more details.
212
+ *
213
+ * You should have received a copy of the GNU General Public License
214
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
215
+ */
216
+
217
+#include "qemu/osdep.h"
218
+#include "qemu/units.h"
219
+#include "hw/sysbus.h"
220
+#include "migration/vmstate.h"
221
+#include "qemu/log.h"
222
+#include "qemu/module.h"
223
+#include "qemu/guest-random.h"
224
+#include "qapi/error.h"
225
+#include "hw/qdev-properties.h"
226
+#include "hw/misc/allwinner-sid.h"
227
+#include "trace.h"
228
+
229
+/* SID register offsets */
230
+enum {
231
+ REG_PRCTL = 0x40, /* Control */
232
+ REG_RDKEY = 0x60, /* Read Key */
233
+};
234
+
235
+/* SID register flags */
236
+enum {
237
+ REG_PRCTL_WRITE = 0x0002, /* Unknown write flag */
238
+ REG_PRCTL_OP_LOCK = 0xAC00, /* Lock operation */
239
+};
240
+
241
+static uint64_t allwinner_sid_read(void *opaque, hwaddr offset,
242
+ unsigned size)
243
+{
47
+{
244
+ const AwSidState *s = AW_SID(opaque);
48
+ m &= 0xff;
245
+ uint64_t val = 0;
49
+ if (m == 0) {
246
+
247
+ switch (offset) {
248
+ case REG_PRCTL: /* Control */
249
+ val = s->control;
250
+ break;
251
+ case REG_RDKEY: /* Read Key */
252
+ val = s->rdkey;
253
+ break;
254
+ default:
255
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
256
+ __func__, (uint32_t)offset);
257
+ return 0;
50
+ return 0;
258
+ }
51
+ }
259
+
52
+ n = revbit8(n);
260
+ trace_allwinner_sid_read(offset, val, size);
53
+ if (m < 8) {
261
+
54
+ n >>= 8 - m;
262
+ return val;
55
+ }
56
+ return n;
263
+}
57
+}
264
+
58
+
265
+static void allwinner_sid_write(void *opaque, hwaddr offset,
59
+static inline uint32_t do_vbrsrh(uint32_t n, uint32_t m)
266
+ uint64_t val, unsigned size)
267
+{
60
+{
268
+ AwSidState *s = AW_SID(opaque);
61
+ m &= 0xff;
269
+
62
+ if (m == 0) {
270
+ trace_allwinner_sid_write(offset, val, size);
63
+ return 0;
271
+
272
+ switch (offset) {
273
+ case REG_PRCTL: /* Control */
274
+ s->control = val;
275
+
276
+ if ((s->control & REG_PRCTL_OP_LOCK) &&
277
+ (s->control & REG_PRCTL_WRITE)) {
278
+ uint32_t id = s->control >> 16;
279
+
280
+ if (id <= sizeof(QemuUUID) - sizeof(s->rdkey)) {
281
+ s->rdkey = ldl_be_p(&s->identifier.data[id]);
282
+ }
283
+ }
284
+ s->control &= ~REG_PRCTL_WRITE;
285
+ break;
286
+ case REG_RDKEY: /* Read Key */
287
+ break;
288
+ default:
289
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
290
+ __func__, (uint32_t)offset);
291
+ break;
292
+ }
64
+ }
65
+ n = revbit16(n);
66
+ if (m < 16) {
67
+ n >>= 16 - m;
68
+ }
69
+ return n;
293
+}
70
+}
294
+
71
+
295
+static const MemoryRegionOps allwinner_sid_ops = {
72
+static inline uint32_t do_vbrsrw(uint32_t n, uint32_t m)
296
+ .read = allwinner_sid_read,
297
+ .write = allwinner_sid_write,
298
+ .endianness = DEVICE_NATIVE_ENDIAN,
299
+ .valid = {
300
+ .min_access_size = 4,
301
+ .max_access_size = 4,
302
+ },
303
+ .impl.min_access_size = 4,
304
+};
305
+
306
+static void allwinner_sid_reset(DeviceState *dev)
307
+{
73
+{
308
+ AwSidState *s = AW_SID(dev);
74
+ m &= 0xff;
309
+
75
+ if (m == 0) {
310
+ /* Set default values for registers */
76
+ return 0;
311
+ s->control = 0;
77
+ }
312
+ s->rdkey = 0;
78
+ n = revbit32(n);
79
+ if (m < 32) {
80
+ n >>= 32 - m;
81
+ }
82
+ return n;
313
+}
83
+}
314
+
84
+
315
+static void allwinner_sid_init(Object *obj)
85
+DO_2OP_SCALAR(vbrsrb, 1, uint8_t, do_vbrsrb)
316
+{
86
+DO_2OP_SCALAR(vbrsrh, 2, uint16_t, do_vbrsrh)
317
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
87
+DO_2OP_SCALAR(vbrsrw, 4, uint32_t, do_vbrsrw)
318
+ AwSidState *s = AW_SID(obj);
319
+
88
+
320
+ /* Memory mapping */
89
/*
321
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_sid_ops, s,
90
* Multiply add long dual accumulate ops.
322
+ TYPE_AW_SID, 1 * KiB);
91
*/
323
+ sysbus_init_mmio(sbd, &s->iomem);
92
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
324
+}
325
+
326
+static Property allwinner_sid_properties[] = {
327
+ DEFINE_PROP_UUID_NODEFAULT("identifier", AwSidState, identifier),
328
+ DEFINE_PROP_END_OF_LIST()
329
+};
330
+
331
+static const VMStateDescription allwinner_sid_vmstate = {
332
+ .name = "allwinner-sid",
333
+ .version_id = 1,
334
+ .minimum_version_id = 1,
335
+ .fields = (VMStateField[]) {
336
+ VMSTATE_UINT32(control, AwSidState),
337
+ VMSTATE_UINT32(rdkey, AwSidState),
338
+ VMSTATE_UINT8_ARRAY_V(identifier.data, AwSidState, sizeof(QemuUUID), 1),
339
+ VMSTATE_END_OF_LIST()
340
+ }
341
+};
342
+
343
+static void allwinner_sid_class_init(ObjectClass *klass, void *data)
344
+{
345
+ DeviceClass *dc = DEVICE_CLASS(klass);
346
+
347
+ dc->reset = allwinner_sid_reset;
348
+ dc->vmsd = &allwinner_sid_vmstate;
349
+ device_class_set_props(dc, allwinner_sid_properties);
350
+}
351
+
352
+static const TypeInfo allwinner_sid_info = {
353
+ .name = TYPE_AW_SID,
354
+ .parent = TYPE_SYS_BUS_DEVICE,
355
+ .instance_init = allwinner_sid_init,
356
+ .instance_size = sizeof(AwSidState),
357
+ .class_init = allwinner_sid_class_init,
358
+};
359
+
360
+static void allwinner_sid_register(void)
361
+{
362
+ type_register_static(&allwinner_sid_info);
363
+}
364
+
365
+type_init(allwinner_sid_register)
366
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
367
index XXXXXXX..XXXXXXX 100644
93
index XXXXXXX..XXXXXXX 100644
368
--- a/hw/misc/trace-events
94
--- a/target/arm/translate-mve.c
369
+++ b/hw/misc/trace-events
95
+++ b/target/arm/translate-mve.c
370
@@ -XXX,XX +XXX,XX @@ allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_ad
96
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
371
allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
97
DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
372
allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
98
DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
373
99
DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
374
+# allwinner-sid.c
100
+DO_2OP_SCALAR(VBRSR, vbrsr)
375
+allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
101
376
+allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
102
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
377
+
103
MVEGenDualAccOpFn *fn)
378
# eccmemctl.c
379
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
380
ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x"
381
--
104
--
382
2.20.1
105
2.20.1
383
106
384
107
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement the MVE VPST insn, which sets the predicate mask
2
fields in the VPR to the immediate value encoded in the insn.
2
3
3
Various Allwinner System on Chip designs contain multiple processors
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
that can be configured and reset using the generic CPU Configuration
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
module interface. This commit adds support for the Allwinner CPU
6
Message-id: 20210617121628.20116-27-peter.maydell@linaro.org
6
configuration interface which emulates the following features:
7
---
8
target/arm/mve.decode | 4 +++
9
target/arm/translate-mve.c | 59 ++++++++++++++++++++++++++++++++++++++
10
2 files changed, 63 insertions(+)
7
11
8
* CPU reset
12
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
9
* CPU status
10
11
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Message-id: 20200311221854.30370-7-nieklinnenbank@gmail.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
hw/misc/Makefile.objs | 1 +
17
include/hw/arm/allwinner-h3.h | 3 +
18
include/hw/misc/allwinner-cpucfg.h | 52 ++++++
19
hw/arm/allwinner-h3.c | 9 +-
20
hw/misc/allwinner-cpucfg.c | 282 +++++++++++++++++++++++++++++
21
hw/misc/trace-events | 5 +
22
6 files changed, 351 insertions(+), 1 deletion(-)
23
create mode 100644 include/hw/misc/allwinner-cpucfg.h
24
create mode 100644 hw/misc/allwinner-cpucfg.c
25
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/Makefile.objs
14
--- a/target/arm/mve.decode
29
+++ b/hw/misc/Makefile.objs
15
+++ b/target/arm/mve.decode
30
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
16
@@ -XXX,XX +XXX,XX @@ VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
31
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
17
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
32
18
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
33
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
19
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
20
+
35
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
21
+# Predicate operations
36
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
22
+%mask_22_13 22:1 13:3
37
common-obj-$(CONFIG_NSERIES) += cbus.o
23
+VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
38
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
24
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
39
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/arm/allwinner-h3.h
26
--- a/target/arm/translate-mve.c
41
+++ b/include/hw/arm/allwinner-h3.h
27
+++ b/target/arm/translate-mve.c
42
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
43
#include "hw/timer/allwinner-a10-pit.h"
29
}
44
#include "hw/intc/arm_gic.h"
45
#include "hw/misc/allwinner-h3-ccu.h"
46
+#include "hw/misc/allwinner-cpucfg.h"
47
#include "hw/misc/allwinner-h3-sysctrl.h"
48
#include "target/arm/cpu.h"
49
50
@@ -XXX,XX +XXX,XX @@ enum {
51
AW_H3_GIC_CPU,
52
AW_H3_GIC_HYP,
53
AW_H3_GIC_VCPU,
54
+ AW_H3_CPUCFG,
55
AW_H3_SDRAM
56
};
57
58
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
59
const hwaddr *memmap;
60
AwA10PITState timer;
61
AwH3ClockCtlState ccu;
62
+ AwCpuCfgState cpucfg;
63
AwH3SysCtrlState sysctrl;
64
GICState gic;
65
MemoryRegion sram_a1;
66
diff --git a/include/hw/misc/allwinner-cpucfg.h b/include/hw/misc/allwinner-cpucfg.h
67
new file mode 100644
68
index XXXXXXX..XXXXXXX
69
--- /dev/null
70
+++ b/include/hw/misc/allwinner-cpucfg.h
71
@@ -XXX,XX +XXX,XX @@
72
+/*
73
+ * Allwinner CPU Configuration Module emulation
74
+ *
75
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
76
+ *
77
+ * This program is free software: you can redistribute it and/or modify
78
+ * it under the terms of the GNU General Public License as published by
79
+ * the Free Software Foundation, either version 2 of the License, or
80
+ * (at your option) any later version.
81
+ *
82
+ * This program is distributed in the hope that it will be useful,
83
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
84
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85
+ * GNU General Public License for more details.
86
+ *
87
+ * You should have received a copy of the GNU General Public License
88
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
89
+ */
90
+
91
+#ifndef HW_MISC_ALLWINNER_CPUCFG_H
92
+#define HW_MISC_ALLWINNER_CPUCFG_H
93
+
94
+#include "qom/object.h"
95
+#include "hw/sysbus.h"
96
+
97
+/**
98
+ * Object model
99
+ * @{
100
+ */
101
+
102
+#define TYPE_AW_CPUCFG "allwinner-cpucfg"
103
+#define AW_CPUCFG(obj) \
104
+ OBJECT_CHECK(AwCpuCfgState, (obj), TYPE_AW_CPUCFG)
105
+
106
+/** @} */
107
+
108
+/**
109
+ * Allwinner CPU Configuration Module instance state
110
+ */
111
+typedef struct AwCpuCfgState {
112
+ /*< private >*/
113
+ SysBusDevice parent_obj;
114
+ /*< public >*/
115
+
116
+ MemoryRegion iomem;
117
+ uint32_t gen_ctrl;
118
+ uint32_t super_standby;
119
+ uint32_t entry_addr;
120
+
121
+} AwCpuCfgState;
122
+
123
+#endif /* HW_MISC_ALLWINNER_CPUCFG_H */
124
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/hw/arm/allwinner-h3.c
127
+++ b/hw/arm/allwinner-h3.c
128
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
129
[AW_H3_GIC_CPU] = 0x01c82000,
130
[AW_H3_GIC_HYP] = 0x01c84000,
131
[AW_H3_GIC_VCPU] = 0x01c86000,
132
+ [AW_H3_CPUCFG] = 0x01f01c00,
133
[AW_H3_SDRAM] = 0x40000000
134
};
135
136
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
137
{ "r_wdog", 0x01f01000, 1 * KiB },
138
{ "r_prcm", 0x01f01400, 1 * KiB },
139
{ "r_twd", 0x01f01800, 1 * KiB },
140
- { "r_cpucfg", 0x01f01c00, 1 * KiB },
141
{ "r_cir-rx", 0x01f02000, 1 * KiB },
142
{ "r_twi", 0x01f02400, 1 * KiB },
143
{ "r_uart", 0x01f02800, 1 * KiB },
144
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
145
146
sysbus_init_child_obj(obj, "sysctrl", &s->sysctrl, sizeof(s->sysctrl),
147
TYPE_AW_H3_SYSCTRL);
148
+
149
+ sysbus_init_child_obj(obj, "cpucfg", &s->cpucfg, sizeof(s->cpucfg),
150
+ TYPE_AW_CPUCFG);
151
}
30
}
152
31
153
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
32
+static void mve_update_and_store_eci(DisasContext *s)
154
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
155
qdev_init_nofail(DEVICE(&s->sysctrl));
156
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, s->memmap[AW_H3_SYSCTRL]);
157
158
+ /* CPU Configuration */
159
+ qdev_init_nofail(DEVICE(&s->cpucfg));
160
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0, s->memmap[AW_H3_CPUCFG]);
161
+
162
/* Universal Serial Bus */
163
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
164
qdev_get_gpio_in(DEVICE(&s->gic),
165
diff --git a/hw/misc/allwinner-cpucfg.c b/hw/misc/allwinner-cpucfg.c
166
new file mode 100644
167
index XXXXXXX..XXXXXXX
168
--- /dev/null
169
+++ b/hw/misc/allwinner-cpucfg.c
170
@@ -XXX,XX +XXX,XX @@
171
+/*
172
+ * Allwinner CPU Configuration Module emulation
173
+ *
174
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
175
+ *
176
+ * This program is free software: you can redistribute it and/or modify
177
+ * it under the terms of the GNU General Public License as published by
178
+ * the Free Software Foundation, either version 2 of the License, or
179
+ * (at your option) any later version.
180
+ *
181
+ * This program is distributed in the hope that it will be useful,
182
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
183
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
184
+ * GNU General Public License for more details.
185
+ *
186
+ * You should have received a copy of the GNU General Public License
187
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
188
+ */
189
+
190
+#include "qemu/osdep.h"
191
+#include "qemu/units.h"
192
+#include "hw/sysbus.h"
193
+#include "migration/vmstate.h"
194
+#include "qemu/log.h"
195
+#include "qemu/module.h"
196
+#include "qemu/error-report.h"
197
+#include "qemu/timer.h"
198
+#include "hw/core/cpu.h"
199
+#include "target/arm/arm-powerctl.h"
200
+#include "target/arm/cpu.h"
201
+#include "hw/misc/allwinner-cpucfg.h"
202
+#include "trace.h"
203
+
204
+/* CPUCFG register offsets */
205
+enum {
206
+ REG_CPUS_RST_CTRL = 0x0000, /* CPUs Reset Control */
207
+ REG_CPU0_RST_CTRL = 0x0040, /* CPU#0 Reset Control */
208
+ REG_CPU0_CTRL = 0x0044, /* CPU#0 Control */
209
+ REG_CPU0_STATUS = 0x0048, /* CPU#0 Status */
210
+ REG_CPU1_RST_CTRL = 0x0080, /* CPU#1 Reset Control */
211
+ REG_CPU1_CTRL = 0x0084, /* CPU#1 Control */
212
+ REG_CPU1_STATUS = 0x0088, /* CPU#1 Status */
213
+ REG_CPU2_RST_CTRL = 0x00C0, /* CPU#2 Reset Control */
214
+ REG_CPU2_CTRL = 0x00C4, /* CPU#2 Control */
215
+ REG_CPU2_STATUS = 0x00C8, /* CPU#2 Status */
216
+ REG_CPU3_RST_CTRL = 0x0100, /* CPU#3 Reset Control */
217
+ REG_CPU3_CTRL = 0x0104, /* CPU#3 Control */
218
+ REG_CPU3_STATUS = 0x0108, /* CPU#3 Status */
219
+ REG_CPU_SYS_RST = 0x0140, /* CPU System Reset */
220
+ REG_CLK_GATING = 0x0144, /* CPU Clock Gating */
221
+ REG_GEN_CTRL = 0x0184, /* General Control */
222
+ REG_SUPER_STANDBY = 0x01A0, /* Super Standby Flag */
223
+ REG_ENTRY_ADDR = 0x01A4, /* Reset Entry Address */
224
+ REG_DBG_EXTERN = 0x01E4, /* Debug External */
225
+ REG_CNT64_CTRL = 0x0280, /* 64-bit Counter Control */
226
+ REG_CNT64_LOW = 0x0284, /* 64-bit Counter Low */
227
+ REG_CNT64_HIGH = 0x0288, /* 64-bit Counter High */
228
+};
229
+
230
+/* CPUCFG register flags */
231
+enum {
232
+ CPUX_RESET_RELEASED = ((1 << 1) | (1 << 0)),
233
+ CPUX_STATUS_SMP = (1 << 0),
234
+ CPU_SYS_RESET_RELEASED = (1 << 0),
235
+ CLK_GATING_ENABLE = ((1 << 8) | 0xF),
236
+};
237
+
238
+/* CPUCFG register reset values */
239
+enum {
240
+ REG_CLK_GATING_RST = 0x0000010F,
241
+ REG_GEN_CTRL_RST = 0x00000020,
242
+ REG_SUPER_STANDBY_RST = 0x0,
243
+ REG_CNT64_CTRL_RST = 0x0,
244
+};
245
+
246
+/* CPUCFG constants */
247
+enum {
248
+ CPU_EXCEPTION_LEVEL_ON_RESET = 3, /* EL3 */
249
+};
250
+
251
+static void allwinner_cpucfg_cpu_reset(AwCpuCfgState *s, uint8_t cpu_id)
252
+{
33
+{
253
+ int ret;
34
+ /*
254
+
35
+ * For insns which don't call a helper function that will call
255
+ trace_allwinner_cpucfg_cpu_reset(cpu_id, s->entry_addr);
36
+ * mve_advance_vpt(), this version updates s->eci and also stores
256
+
37
+ * it out to the CPUState field.
257
+ ARMCPU *target_cpu = ARM_CPU(arm_get_cpu_by_id(cpu_id));
38
+ */
258
+ if (!target_cpu) {
39
+ if (s->eci) {
259
+ /*
40
+ mve_update_eci(s);
260
+ * Called with a bogus value for cpu_id. Guest error will
41
+ store_cpu_field(tcg_constant_i32(s->eci << 4), condexec_bits);
261
+ * already have been logged, we can simply return here.
262
+ */
263
+ return;
264
+ }
265
+ bool target_aa64 = arm_feature(&target_cpu->env, ARM_FEATURE_AARCH64);
266
+
267
+ ret = arm_set_cpu_on(cpu_id, s->entry_addr, 0,
268
+ CPU_EXCEPTION_LEVEL_ON_RESET, target_aa64);
269
+ if (ret != QEMU_ARM_POWERCTL_RET_SUCCESS) {
270
+ error_report("%s: failed to bring up CPU %d: err %d",
271
+ __func__, cpu_id, ret);
272
+ return;
273
+ }
42
+ }
274
+}
43
+}
275
+
44
+
276
+static uint64_t allwinner_cpucfg_read(void *opaque, hwaddr offset,
45
static bool mve_skip_first_beat(DisasContext *s)
277
+ unsigned size)
46
{
47
/* Return true if PSR.ECI says we must skip the first beat of this insn */
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
49
};
50
return do_long_dual_acc(s, a, fns[a->x]);
51
}
52
+
53
+static bool trans_VPST(DisasContext *s, arg_VPST *a)
278
+{
54
+{
279
+ const AwCpuCfgState *s = AW_CPUCFG(opaque);
55
+ TCGv_i32 vpr;
280
+ uint64_t val = 0;
281
+
56
+
282
+ switch (offset) {
57
+ /* mask == 0 is a "related encoding" */
283
+ case REG_CPUS_RST_CTRL: /* CPUs Reset Control */
58
+ if (!dc_isar_feature(aa32_mve, s) || !a->mask) {
284
+ case REG_CPU_SYS_RST: /* CPU System Reset */
59
+ return false;
285
+ val = CPU_SYS_RESET_RELEASED;
60
+ }
61
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
62
+ return true;
63
+ }
64
+ /*
65
+ * Set the VPR mask fields. We take advantage of MASK01 and MASK23
66
+ * being adjacent fields in the register.
67
+ *
68
+ * This insn is not predicated, but it is subject to beat-wise
69
+ * execution, and the mask is updated on the odd-numbered beats.
70
+ * So if PSR.ECI says we should skip beat 1, we mustn't update the
71
+ * 01 mask field.
72
+ */
73
+ vpr = load_cpu_field(v7m.vpr);
74
+ switch (s->eci) {
75
+ case ECI_NONE:
76
+ case ECI_A0:
77
+ /* Update both 01 and 23 fields */
78
+ tcg_gen_deposit_i32(vpr, vpr,
79
+ tcg_constant_i32(a->mask | (a->mask << 4)),
80
+ R_V7M_VPR_MASK01_SHIFT,
81
+ R_V7M_VPR_MASK01_LENGTH + R_V7M_VPR_MASK23_LENGTH);
286
+ break;
82
+ break;
287
+ case REG_CPU0_RST_CTRL: /* CPU#0 Reset Control */
83
+ case ECI_A0A1:
288
+ case REG_CPU1_RST_CTRL: /* CPU#1 Reset Control */
84
+ case ECI_A0A1A2:
289
+ case REG_CPU2_RST_CTRL: /* CPU#2 Reset Control */
85
+ case ECI_A0A1A2B0:
290
+ case REG_CPU3_RST_CTRL: /* CPU#3 Reset Control */
86
+ /* Update only the 23 mask field */
291
+ val = CPUX_RESET_RELEASED;
87
+ tcg_gen_deposit_i32(vpr, vpr,
292
+ break;
88
+ tcg_constant_i32(a->mask),
293
+ case REG_CPU0_CTRL: /* CPU#0 Control */
89
+ R_V7M_VPR_MASK23_SHIFT, R_V7M_VPR_MASK23_LENGTH);
294
+ case REG_CPU1_CTRL: /* CPU#1 Control */
295
+ case REG_CPU2_CTRL: /* CPU#2 Control */
296
+ case REG_CPU3_CTRL: /* CPU#3 Control */
297
+ val = 0;
298
+ break;
299
+ case REG_CPU0_STATUS: /* CPU#0 Status */
300
+ case REG_CPU1_STATUS: /* CPU#1 Status */
301
+ case REG_CPU2_STATUS: /* CPU#2 Status */
302
+ case REG_CPU3_STATUS: /* CPU#3 Status */
303
+ val = CPUX_STATUS_SMP;
304
+ break;
305
+ case REG_CLK_GATING: /* CPU Clock Gating */
306
+ val = CLK_GATING_ENABLE;
307
+ break;
308
+ case REG_GEN_CTRL: /* General Control */
309
+ val = s->gen_ctrl;
310
+ break;
311
+ case REG_SUPER_STANDBY: /* Super Standby Flag */
312
+ val = s->super_standby;
313
+ break;
314
+ case REG_ENTRY_ADDR: /* Reset Entry Address */
315
+ val = s->entry_addr;
316
+ break;
317
+ case REG_DBG_EXTERN: /* Debug External */
318
+ case REG_CNT64_CTRL: /* 64-bit Counter Control */
319
+ case REG_CNT64_LOW: /* 64-bit Counter Low */
320
+ case REG_CNT64_HIGH: /* 64-bit Counter High */
321
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register at 0x%04x\n",
322
+ __func__, (uint32_t)offset);
323
+ break;
90
+ break;
324
+ default:
91
+ default:
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
92
+ g_assert_not_reached();
326
+ __func__, (uint32_t)offset);
327
+ break;
328
+ }
93
+ }
329
+
94
+ store_cpu_field(vpr, v7m.vpr);
330
+ trace_allwinner_cpucfg_read(offset, val, size);
95
+ mve_update_and_store_eci(s);
331
+
96
+ return true;
332
+ return val;
333
+}
97
+}
334
+
335
+static void allwinner_cpucfg_write(void *opaque, hwaddr offset,
336
+ uint64_t val, unsigned size)
337
+{
338
+ AwCpuCfgState *s = AW_CPUCFG(opaque);
339
+
340
+ trace_allwinner_cpucfg_write(offset, val, size);
341
+
342
+ switch (offset) {
343
+ case REG_CPUS_RST_CTRL: /* CPUs Reset Control */
344
+ case REG_CPU_SYS_RST: /* CPU System Reset */
345
+ break;
346
+ case REG_CPU0_RST_CTRL: /* CPU#0 Reset Control */
347
+ case REG_CPU1_RST_CTRL: /* CPU#1 Reset Control */
348
+ case REG_CPU2_RST_CTRL: /* CPU#2 Reset Control */
349
+ case REG_CPU3_RST_CTRL: /* CPU#3 Reset Control */
350
+ if (val) {
351
+ allwinner_cpucfg_cpu_reset(s, (offset - REG_CPU0_RST_CTRL) >> 6);
352
+ }
353
+ break;
354
+ case REG_CPU0_CTRL: /* CPU#0 Control */
355
+ case REG_CPU1_CTRL: /* CPU#1 Control */
356
+ case REG_CPU2_CTRL: /* CPU#2 Control */
357
+ case REG_CPU3_CTRL: /* CPU#3 Control */
358
+ case REG_CPU0_STATUS: /* CPU#0 Status */
359
+ case REG_CPU1_STATUS: /* CPU#1 Status */
360
+ case REG_CPU2_STATUS: /* CPU#2 Status */
361
+ case REG_CPU3_STATUS: /* CPU#3 Status */
362
+ case REG_CLK_GATING: /* CPU Clock Gating */
363
+ break;
364
+ case REG_GEN_CTRL: /* General Control */
365
+ s->gen_ctrl = val;
366
+ break;
367
+ case REG_SUPER_STANDBY: /* Super Standby Flag */
368
+ s->super_standby = val;
369
+ break;
370
+ case REG_ENTRY_ADDR: /* Reset Entry Address */
371
+ s->entry_addr = val;
372
+ break;
373
+ case REG_DBG_EXTERN: /* Debug External */
374
+ case REG_CNT64_CTRL: /* 64-bit Counter Control */
375
+ case REG_CNT64_LOW: /* 64-bit Counter Low */
376
+ case REG_CNT64_HIGH: /* 64-bit Counter High */
377
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register at 0x%04x\n",
378
+ __func__, (uint32_t)offset);
379
+ break;
380
+ default:
381
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
382
+ __func__, (uint32_t)offset);
383
+ break;
384
+ }
385
+}
386
+
387
+static const MemoryRegionOps allwinner_cpucfg_ops = {
388
+ .read = allwinner_cpucfg_read,
389
+ .write = allwinner_cpucfg_write,
390
+ .endianness = DEVICE_NATIVE_ENDIAN,
391
+ .valid = {
392
+ .min_access_size = 4,
393
+ .max_access_size = 4,
394
+ },
395
+ .impl.min_access_size = 4,
396
+};
397
+
398
+static void allwinner_cpucfg_reset(DeviceState *dev)
399
+{
400
+ AwCpuCfgState *s = AW_CPUCFG(dev);
401
+
402
+ /* Set default values for registers */
403
+ s->gen_ctrl = REG_GEN_CTRL_RST;
404
+ s->super_standby = REG_SUPER_STANDBY_RST;
405
+ s->entry_addr = 0;
406
+}
407
+
408
+static void allwinner_cpucfg_init(Object *obj)
409
+{
410
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
411
+ AwCpuCfgState *s = AW_CPUCFG(obj);
412
+
413
+ /* Memory mapping */
414
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_cpucfg_ops, s,
415
+ TYPE_AW_CPUCFG, 1 * KiB);
416
+ sysbus_init_mmio(sbd, &s->iomem);
417
+}
418
+
419
+static const VMStateDescription allwinner_cpucfg_vmstate = {
420
+ .name = "allwinner-cpucfg",
421
+ .version_id = 1,
422
+ .minimum_version_id = 1,
423
+ .fields = (VMStateField[]) {
424
+ VMSTATE_UINT32(gen_ctrl, AwCpuCfgState),
425
+ VMSTATE_UINT32(super_standby, AwCpuCfgState),
426
+ VMSTATE_UINT32(entry_addr, AwCpuCfgState),
427
+ VMSTATE_END_OF_LIST()
428
+ }
429
+};
430
+
431
+static void allwinner_cpucfg_class_init(ObjectClass *klass, void *data)
432
+{
433
+ DeviceClass *dc = DEVICE_CLASS(klass);
434
+
435
+ dc->reset = allwinner_cpucfg_reset;
436
+ dc->vmsd = &allwinner_cpucfg_vmstate;
437
+}
438
+
439
+static const TypeInfo allwinner_cpucfg_info = {
440
+ .name = TYPE_AW_CPUCFG,
441
+ .parent = TYPE_SYS_BUS_DEVICE,
442
+ .instance_init = allwinner_cpucfg_init,
443
+ .instance_size = sizeof(AwCpuCfgState),
444
+ .class_init = allwinner_cpucfg_class_init,
445
+};
446
+
447
+static void allwinner_cpucfg_register(void)
448
+{
449
+ type_register_static(&allwinner_cpucfg_info);
450
+}
451
+
452
+type_init(allwinner_cpucfg_register)
453
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
454
index XXXXXXX..XXXXXXX 100644
455
--- a/hw/misc/trace-events
456
+++ b/hw/misc/trace-events
457
@@ -XXX,XX +XXX,XX @@
458
# See docs/devel/tracing.txt for syntax documentation.
459
460
+# allwinner-cpucfg.c
461
+allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIu32
462
+allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
463
+allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
464
+
465
# eccmemctl.c
466
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
467
ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x"
468
--
98
--
469
2.20.1
99
2.20.1
470
100
471
101
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Implement the MVE VQADD and VQSUB insns, which perform saturating
2
addition of a scalar to each element. Note that individual bytes of
3
each result element are used or discarded according to the predicate
4
mask, but FPSCR.QC is only set if the predicate mask for the lowest
5
byte of the element is set.
2
6
3
Convert kvm_arm_vgic_probe() so that it returns a
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
bitmap of supported in-kernel emulation VGIC versions instead
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
of the max version: at the moment values can be v2 and v3.
9
Message-id: 20210617121628.20116-28-peter.maydell@linaro.org
6
This allows to expose the case where the host GICv3 also
10
---
7
supports GICv2 emulation. This will be useful to choose the
11
target/arm/helper-mve.h | 16 ++++++++++
8
default version in KVM accelerated mode.
12
target/arm/mve.decode | 5 +++
13
target/arm/mve_helper.c | 62 ++++++++++++++++++++++++++++++++++++++
14
target/arm/translate-mve.c | 4 +++
15
4 files changed, 87 insertions(+)
9
16
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20200311131618.7187-5-eric.auger@redhat.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/kvm_arm.h | 3 +++
17
hw/arm/virt.c | 11 +++++++++--
18
target/arm/kvm.c | 14 ++++++++------
19
3 files changed, 20 insertions(+), 8 deletions(-)
20
21
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/kvm_arm.h
19
--- a/target/arm/helper-mve.h
24
+++ b/target/arm/kvm_arm.h
20
+++ b/target/arm/helper-mve.h
25
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
#include "exec/memory.h"
22
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
#include "qemu/error-report.h"
23
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
24
29
+#define KVM_ARM_VGIC_V2 (1 << 0)
25
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
+#define KVM_ARM_VGIC_V3 (1 << 1)
26
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
+
28
+
32
/**
29
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
* kvm_arm_vcpu_init:
30
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
* @cs: CPUState
31
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
32
+
33
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
+
37
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
+
41
DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
43
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
44
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
36
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/virt.c
46
--- a/target/arm/mve.decode
38
+++ b/hw/arm/virt.c
47
+++ b/target/arm/mve.decode
39
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
48
@@ -XXX,XX +XXX,XX @@ VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
40
vms->gic_version = VIRT_GIC_VERSION_3;
49
VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
41
}
50
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
42
} else {
51
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
43
- vms->gic_version = kvm_arm_vgic_probe();
44
- if (!vms->gic_version) {
45
+ int probe_bitmap = kvm_arm_vgic_probe();
46
+
52
+
47
+ if (!probe_bitmap) {
53
+VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
48
error_report(
54
+VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
49
"Unable to determine GIC version supported by host");
55
+VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
50
exit(1);
56
+VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
51
+ } else {
57
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
52
+ if (probe_bitmap & KVM_ARM_VGIC_V3) {
58
53
+ vms->gic_version = VIRT_GIC_VERSION_3;
59
# Predicate operations
54
+ } else {
60
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
55
+ vms->gic_version = VIRT_GIC_VERSION_2;
56
+ }
57
}
58
}
59
} else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
60
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
61
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/kvm.c
62
--- a/target/arm/mve_helper.c
63
+++ b/target/arm/kvm.c
63
+++ b/target/arm/mve_helper.c
64
@@ -XXX,XX +XXX,XX @@ int kvm_arch_irqchip_create(KVMState *s)
64
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhaddu, do_vhadd_u)
65
65
DO_2OP_S(vhsubs, do_vhsub_s)
66
int kvm_arm_vgic_probe(void)
66
DO_2OP_U(vhsubu, do_vhsub_u)
67
{
67
68
+ int val = 0;
68
+static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
69
+
69
+{
70
if (kvm_create_device(kvm_state,
70
+ if (val > max) {
71
KVM_DEV_TYPE_ARM_VGIC_V3, true) == 0) {
71
+ *s = true;
72
- return 3;
72
+ return max;
73
- } else if (kvm_create_device(kvm_state,
73
+ } else if (val < min) {
74
- KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) {
74
+ *s = true;
75
- return 2;
75
+ return min;
76
- } else {
77
- return 0;
78
+ val |= KVM_ARM_VGIC_V3;
79
}
80
+ if (kvm_create_device(kvm_state,
81
+ KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) {
82
+ val |= KVM_ARM_VGIC_V2;
83
+ }
76
+ }
84
+ return val;
77
+ return val;
85
}
78
+}
86
79
+
87
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level)
80
+#define DO_SQADD_B(n, m, s) do_sat_bhw((int64_t)n + m, INT8_MIN, INT8_MAX, s)
81
+#define DO_SQADD_H(n, m, s) do_sat_bhw((int64_t)n + m, INT16_MIN, INT16_MAX, s)
82
+#define DO_SQADD_W(n, m, s) do_sat_bhw((int64_t)n + m, INT32_MIN, INT32_MAX, s)
83
+
84
+#define DO_UQADD_B(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT8_MAX, s)
85
+#define DO_UQADD_H(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT16_MAX, s)
86
+#define DO_UQADD_W(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT32_MAX, s)
87
+
88
+#define DO_SQSUB_B(n, m, s) do_sat_bhw((int64_t)n - m, INT8_MIN, INT8_MAX, s)
89
+#define DO_SQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, INT16_MIN, INT16_MAX, s)
90
+#define DO_SQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, INT32_MIN, INT32_MAX, s)
91
+
92
+#define DO_UQSUB_B(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT8_MAX, s)
93
+#define DO_UQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT16_MAX, s)
94
+#define DO_UQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT32_MAX, s)
95
96
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
97
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
98
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
99
mve_advance_vpt(env); \
100
}
101
102
+#define DO_2OP_SAT_SCALAR(OP, ESIZE, TYPE, FN) \
103
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
104
+ uint32_t rm) \
105
+ { \
106
+ TYPE *d = vd, *n = vn; \
107
+ TYPE m = rm; \
108
+ uint16_t mask = mve_element_mask(env); \
109
+ unsigned e; \
110
+ bool qc = false; \
111
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
112
+ bool sat = false; \
113
+ mergemask(&d[H##ESIZE(e)], FN(n[H##ESIZE(e)], m, &sat), \
114
+ mask); \
115
+ qc |= sat & mask & 1; \
116
+ } \
117
+ if (qc) { \
118
+ env->vfp.qc[0] = qc; \
119
+ } \
120
+ mve_advance_vpt(env); \
121
+ }
122
+
123
/* provide unsigned 2-op scalar helpers for all sizes */
124
#define DO_2OP_SCALAR_U(OP, FN) \
125
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
126
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
127
DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
128
DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
129
130
+DO_2OP_SAT_SCALAR(vqaddu_scalarb, 1, uint8_t, DO_UQADD_B)
131
+DO_2OP_SAT_SCALAR(vqaddu_scalarh, 2, uint16_t, DO_UQADD_H)
132
+DO_2OP_SAT_SCALAR(vqaddu_scalarw, 4, uint32_t, DO_UQADD_W)
133
+DO_2OP_SAT_SCALAR(vqadds_scalarb, 1, int8_t, DO_SQADD_B)
134
+DO_2OP_SAT_SCALAR(vqadds_scalarh, 2, int16_t, DO_SQADD_H)
135
+DO_2OP_SAT_SCALAR(vqadds_scalarw, 4, int32_t, DO_SQADD_W)
136
+
137
+DO_2OP_SAT_SCALAR(vqsubu_scalarb, 1, uint8_t, DO_UQSUB_B)
138
+DO_2OP_SAT_SCALAR(vqsubu_scalarh, 2, uint16_t, DO_UQSUB_H)
139
+DO_2OP_SAT_SCALAR(vqsubu_scalarw, 4, uint32_t, DO_UQSUB_W)
140
+DO_2OP_SAT_SCALAR(vqsubs_scalarb, 1, int8_t, DO_SQSUB_B)
141
+DO_2OP_SAT_SCALAR(vqsubs_scalarh, 2, int16_t, DO_SQSUB_H)
142
+DO_2OP_SAT_SCALAR(vqsubs_scalarw, 4, int32_t, DO_SQSUB_W)
143
+
144
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
145
{
146
m &= 0xff;
147
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/target/arm/translate-mve.c
150
+++ b/target/arm/translate-mve.c
151
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
152
DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
153
DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
154
DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
155
+DO_2OP_SCALAR(VQADD_S_scalar, vqadds_scalar)
156
+DO_2OP_SCALAR(VQADD_U_scalar, vqaddu_scalar)
157
+DO_2OP_SCALAR(VQSUB_S_scalar, vqsubs_scalar)
158
+DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
159
DO_2OP_SCALAR(VBRSR, vbrsr)
160
161
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
88
--
162
--
89
2.20.1
163
2.20.1
90
164
91
165
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Implement the MVE VQDMULH and VQRDMULH scalar insns, which multiply
2
elements by the scalar, double, possibly round, take the high half
3
and saturate.
2
4
3
At the moment if the end-user does not specify the gic-version along
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
with KVM acceleration, v2 is set by default. However most of the
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
systems now have GICv3 and sometimes they do not support GICv2
7
Message-id: 20210617121628.20116-29-peter.maydell@linaro.org
6
compatibility.
8
---
9
target/arm/helper-mve.h | 8 ++++++++
10
target/arm/mve.decode | 3 +++
11
target/arm/mve_helper.c | 25 +++++++++++++++++++++++++
12
target/arm/translate-mve.c | 2 ++
13
4 files changed, 38 insertions(+)
7
14
8
This patch keeps the default v2 selection in all cases except
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
9
in the KVM accelerated mode when either
10
- the host does not support GICv2 in-kernel emulation or
11
- number of VCPUS exceeds 8.
12
13
Those cases did not work anyway so we do not break any compatibility.
14
Now we get v3 selected in such a case.
15
16
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
18
Reviewed-by: Andrew Jones <drjones@redhat.com>
19
Message-id: 20200311131618.7187-7-eric.auger@redhat.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/arm/virt.c | 17 ++++++++++++++++-
23
1 file changed, 16 insertions(+), 1 deletion(-)
24
25
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/virt.c
17
--- a/target/arm/helper-mve.h
28
+++ b/hw/arm/virt.c
18
+++ b/target/arm/helper-mve.h
29
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
*/
20
DEF_HELPER_FLAGS_4(mve_vqsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
static void finalize_gic_version(VirtMachineState *vms)
21
DEF_HELPER_FLAGS_4(mve_vqsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
23
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+
27
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
+
31
DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/mve.decode
37
+++ b/target/arm/mve.decode
38
@@ -XXX,XX +XXX,XX @@ VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
39
VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
40
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
41
42
+VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
43
+VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
44
+
45
# Predicate operations
46
%mask_22_13 22:1 13:3
47
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
48
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/mve_helper.c
51
+++ b/target/arm/mve_helper.c
52
@@ -XXX,XX +XXX,XX @@ static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
53
#define DO_UQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT16_MAX, s)
54
#define DO_UQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT32_MAX, s)
55
56
+/*
57
+ * For QDMULH and QRDMULH we simplify "double and shift by esize" into
58
+ * "shift by esize-1", adjusting the QRDMULH rounding constant to match.
59
+ */
60
+#define DO_QDMULH_B(n, m, s) do_sat_bhw(((int64_t)n * m) >> 7, \
61
+ INT8_MIN, INT8_MAX, s)
62
+#define DO_QDMULH_H(n, m, s) do_sat_bhw(((int64_t)n * m) >> 15, \
63
+ INT16_MIN, INT16_MAX, s)
64
+#define DO_QDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m) >> 31, \
65
+ INT32_MIN, INT32_MAX, s)
66
+
67
+#define DO_QRDMULH_B(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 6)) >> 7, \
68
+ INT8_MIN, INT8_MAX, s)
69
+#define DO_QRDMULH_H(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 14)) >> 15, \
70
+ INT16_MIN, INT16_MAX, s)
71
+#define DO_QRDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 30)) >> 31, \
72
+ INT32_MIN, INT32_MAX, s)
73
+
74
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
75
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
76
uint32_t rm) \
77
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqsubs_scalarb, 1, int8_t, DO_SQSUB_B)
78
DO_2OP_SAT_SCALAR(vqsubs_scalarh, 2, int16_t, DO_SQSUB_H)
79
DO_2OP_SAT_SCALAR(vqsubs_scalarw, 4, int32_t, DO_SQSUB_W)
80
81
+DO_2OP_SAT_SCALAR(vqdmulh_scalarb, 1, int8_t, DO_QDMULH_B)
82
+DO_2OP_SAT_SCALAR(vqdmulh_scalarh, 2, int16_t, DO_QDMULH_H)
83
+DO_2OP_SAT_SCALAR(vqdmulh_scalarw, 4, int32_t, DO_QDMULH_W)
84
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
85
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
86
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
87
+
88
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
32
{
89
{
33
+ unsigned int max_cpus = MACHINE(vms)->smp.max_cpus;
90
m &= 0xff;
34
+
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
35
if (kvm_enabled()) {
92
index XXXXXXX..XXXXXXX 100644
36
int probe_bitmap;
93
--- a/target/arm/translate-mve.c
37
94
+++ b/target/arm/translate-mve.c
38
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
95
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQADD_S_scalar, vqadds_scalar)
39
}
96
DO_2OP_SCALAR(VQADD_U_scalar, vqaddu_scalar)
40
return;
97
DO_2OP_SCALAR(VQSUB_S_scalar, vqsubs_scalar)
41
case VIRT_GIC_VERSION_NOSEL:
98
DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
42
- vms->gic_version = VIRT_GIC_VERSION_2;
99
+DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
43
+ if ((probe_bitmap & KVM_ARM_VGIC_V2) && max_cpus <= GIC_NCPU) {
100
+DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
44
+ vms->gic_version = VIRT_GIC_VERSION_2;
101
DO_2OP_SCALAR(VBRSR, vbrsr)
45
+ } else if (probe_bitmap & KVM_ARM_VGIC_V3) {
102
46
+ /*
103
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
47
+ * in case the host does not support v2 in-kernel emulation or
48
+ * the end-user requested more than 8 VCPUs we now default
49
+ * to v3. In any case defaulting to v2 would be broken.
50
+ */
51
+ vms->gic_version = VIRT_GIC_VERSION_3;
52
+ } else if (max_cpus > GIC_NCPU) {
53
+ error_report("host only supports in-kernel GICv2 emulation "
54
+ "but more than 8 vcpus are requested");
55
+ exit(1);
56
+ }
57
break;
58
case VIRT_GIC_VERSION_2:
59
case VIRT_GIC_VERSION_3:
60
--
104
--
61
2.20.1
105
2.20.1
62
106
63
107
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Implement the MVE VQDMULL scalar insn. This multiplies the top or
2
2
bottom half of each element by the scalar, doubles and saturates
3
This test boots U-Boot then NetBSD (stored on a SD card) on
3
to a double-width result.
4
a OrangePi PC board.
4
5
5
Note that this encoding overlaps with VQADD and VQSUB; it uses
6
As it requires ~1.3GB of storage, it is disabled by default.
6
what in VQADD and VQSUB would be the 'size=0b11' encoding.
7
7
8
U-Boot is built by the Debian project [1], and the SD card image
9
is provided by the NetBSD organization [2].
10
11
Once the compressed SD card image is downloaded (304MB) and
12
extracted, this test is fast:
13
14
$ AVOCADO_ALLOW_LARGE_STORAGE=yes \
15
avocado --show=app,console run -t machine:orangepi-pc \
16
tests/acceptance/boot_linux_console.py
17
console: U-Boot SPL 2020.01+dfsg-1 (Jan 08 2020 - 08:19:44 +0000)
18
console: DRAM: 1024 MiB
19
console: U-Boot 2020.01+dfsg-1 (Jan 08 2020 - 08:19:44 +0000) Allwinner Technology
20
console: CPU: Allwinner H3 (SUN8I 0000)
21
console: scanning bus usb@1c1b000 for devices... 1 USB Device(s) found
22
console: scanning bus usb@1c1d000 for devices... 1 USB Device(s) found
23
console: scanning usb for storage devices... 0 Storage Device(s) found
24
console: Hit any key to stop autoboot: 0
25
console: => setenv bootargs root=ld0a
26
console: => setenv kernel netbsd-GENERIC.ub
27
console: => setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb
28
console: => boot
29
console: ## Booting kernel from Legacy Image at 42000000 ...
30
console: Image Name: NetBSD/earmv7hf 9.0_RC1
31
console: Image Type: ARM Linux Kernel Image (no loading done) (uncompressed)
32
console: XIP Kernel Image (no loading done)
33
console: Loading Device Tree to 49ff6000, end 49fffe01 ... OK
34
console: Starting kernel ...
35
console: [ 1.0000000] NetBSD/evbarm (fdt) booting ...
36
console: [ 1.0000000] NetBSD 9.0 (GENERIC) #0: Fri Feb 14 00:06:28 UTC 2020
37
console: [ 1.0000000] mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/GENERIC
38
console: [ 1.0000000] total memory = 1024 MB
39
console: [ 1.0000000] avail memory = 1003 MB
40
console: [ 1.0000000] armfdt0 (root)
41
console: [ 1.0000000] simplebus0 at armfdt0: Xunlong Orange Pi PC
42
console: [ 1.0000000] cpu0 at cpus0: Cortex-A7 r0p5 (Cortex V7A core)
43
console: [ 1.0000000] cpu0: DC enabled IC enabled WB enabled LABT branch prediction enabled
44
console: [ 1.0000000] cpu0: 32KB/64B 2-way L1 VIPT Instruction cache
45
console: [ 1.0000000] cpu0: 32KB/64B 2-way write-back-locking-C L1 PIPT Data cache
46
console: [ 1.0000000] cpu0: 2304KB/64B 16-way write-through L2 PIPT Unified cache
47
console: [ 1.0000000] vfp0 at cpu0: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
48
...
49
console: [ 2.3812082] sdmmc0: SD card status: 4-bit, C0
50
console: [ 2.3812082] ld0 at sdmmc0: <0xaa:0x5859:QEMU!:0x01:0xdeadbeef:0x062>
51
console: [ 2.4012856] ld0: 1226 MB, 622 cyl, 64 head, 63 sec, 512 bytes/sect x 2511872 sectors
52
console: [ 2.5321222] ld0: 4-bit width, High-Speed/SDR25, 50.000 MHz
53
console: [ 3.1068718] WARNING: 4 errors while detecting hardware; check system log.
54
console: [ 3.1179868] boot device: ld0
55
console: [ 3.1470623] root on ld0a dumps on ld0b
56
console: [ 3.2464436] root file system type: ffs
57
console: [ 3.2897123] kern.module.path=/stand/evbarm/9.0/modules
58
console: Mon Feb 17 20:33:35 UTC 2020
59
console: Starting root file system check:
60
PASS (35.96 s)
61
RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
62
JOB TIME : 36.09 s
63
64
Note, this test only took ~65 seconds to run on Travis-CI, see: [3].
65
66
This test is based on a description from Niek Linnenbank from [4].
67
68
[1] https://wiki.debian.org/InstallingDebianOn/Allwinner#Creating_a_bootable_SD_Card_with_u-boot
69
[2] https://wiki.netbsd.org/ports/evbarm/allwinner/
70
[3] https://travis-ci.org/philmd/qemu/jobs/638823612#L3778
71
[4] https://www.mail-archive.com/qemu-devel@nongnu.org/msg669347.html
72
73
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
74
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
75
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
76
Tested-by: Alex Bennée <alex.bennee@linaro.org>
77
Message-id: 20200311221854.30370-18-nieklinnenbank@gmail.com
78
[NL: changed test to use NetBSD 9.0 final release and -global allwinner-rtc.base-year]
79
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210617121628.20116-30-peter.maydell@linaro.org
80
---
11
---
81
tests/acceptance/boot_linux_console.py | 70 ++++++++++++++++++++++++++
12
target/arm/helper-mve.h | 5 +++
82
1 file changed, 70 insertions(+)
13
target/arm/mve.decode | 23 +++++++++++---
83
14
target/arm/mve_helper.c | 65 ++++++++++++++++++++++++++++++++++++++
84
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
15
target/arm/translate-mve.c | 30 ++++++++++++++++++
85
index XXXXXXX..XXXXXXX 100644
16
4 files changed, 119 insertions(+), 4 deletions(-)
86
--- a/tests/acceptance/boot_linux_console.py
17
87
+++ b/tests/acceptance/boot_linux_console.py
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
88
@@ -XXX,XX +XXX,XX @@ import shutil
19
index XXXXXXX..XXXXXXX 100644
89
from avocado import skipUnless
20
--- a/target/arm/helper-mve.h
90
from avocado_qemu import Test
21
+++ b/target/arm/helper-mve.h
91
from avocado_qemu import exec_command_and_wait_for_pattern
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
92
+from avocado_qemu import interrupt_interactive_console_until_pattern
23
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
93
from avocado_qemu import wait_for_console_pattern
24
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
94
from avocado.utils import process
25
95
from avocado.utils import archive
26
+DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
96
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
27
+DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
97
'to <orangepipc>')
28
+DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
98
self.wait_for_console_pattern('Starting Load Kernel Modules...')
29
+DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
99
30
+
100
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
31
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
101
+ def test_arm_orangepi_uboot_netbsd9(self):
32
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
102
+ """
33
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
103
+ :avocado: tags=arch:arm
34
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
104
+ :avocado: tags=machine:orangepi-pc
35
index XXXXXXX..XXXXXXX 100644
105
+ """
36
--- a/target/arm/mve.decode
106
+ # This test download a 304MB compressed image and expand it to 1.3GB...
37
+++ b/target/arm/mve.decode
107
+ deb_url = ('http://snapshot.debian.org/archive/debian/'
38
@@ -XXX,XX +XXX,XX @@
108
+ '20200108T145233Z/pool/main/u/u-boot/'
39
%qm 5:1 1:3
109
+ 'u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb')
40
%qn 7:1 17:3
110
+ deb_hash = 'f67f404a80753ca3d1258f13e38f2b060e13db99'
41
111
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
42
+# VQDMULL has size in bit 28: 0 for 16 bit, 1 for 32 bit
112
+ # We use the common OrangePi PC 'plus' build of U-Boot for our secondary
43
+%size_28 28:1 !function=plus_1
113
+ # program loader (SPL). We will then set the path to the more specific
44
+
114
+ # OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt,
45
&vldr_vstr rn qd imm p a w size l u
115
+ # before to boot NetBSD.
46
&1op qd qm size
116
+ uboot_path = '/usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin'
47
&2op qd qm qn size
117
+ uboot_path = self.extract_from_deb(deb_path, uboot_path)
48
@@ -XXX,XX +XXX,XX @@
118
+ image_url = ('https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/'
49
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
119
+ 'evbarm-earmv7hf/binary/gzimg/armv7.img.gz')
50
120
+ image_hash = '2babb29d36d8360adcb39c09e31060945259917a'
51
@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
121
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
52
+@2scalar_nosz .... .... .... .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
122
+ image_path = os.path.join(self.workdir, 'armv7.img')
53
123
+ image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path
54
# Vector loads and stores
124
+ archive.gzip_uncompress(image_path_gz, image_path)
55
125
+
56
@@ -XXX,XX +XXX,XX @@ VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
126
+ # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc
57
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
127
+ with open(uboot_path, 'rb') as f_in:
58
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
128
+ with open(image_path, 'r+b') as f_out:
59
129
+ f_out.seek(8 * 1024)
60
-VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
130
+ shutil.copyfileobj(f_in, f_out)
61
-VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
131
+
62
-VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
132
+ # Extend image, to avoid that NetBSD thinks the partition
63
-VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
133
+ # inside the image is larger than device size itself
64
+{
134
+ f_out.seek(0, 2)
65
+ VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
135
+ f_out.seek(64 * 1024 * 1024, 1)
66
+ VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
136
+ f_out.write(bytearray([0x00]))
67
+ VQDMULLB_scalar 111 . 1110 0 . 11 ... 0 ... 0 1111 . 110 .... @2scalar_nosz \
137
+
68
+ size=%size_28
138
+ self.vm.set_console()
69
+}
139
+ self.vm.add_args('-nic', 'user',
70
+
140
+ '-drive', image_drive_args,
71
+{
141
+ '-global', 'allwinner-rtc.base-year=2000',
72
+ VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
142
+ '-no-reboot')
73
+ VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
143
+ self.vm.launch()
74
+ VQDMULLT_scalar 111 . 1110 0 . 11 ... 0 ... 1 1111 . 110 .... @2scalar_nosz \
144
+ wait_for_console_pattern(self, 'U-Boot 2020.01+dfsg-1')
75
+ size=%size_28
145
+ interrupt_interactive_console_until_pattern(self,
76
+}
146
+ 'Hit any key to stop autoboot:',
77
+
147
+ 'switch to partitions #0, OK')
78
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
148
+
79
149
+ exec_command_and_wait_for_pattern(self, '', '=>')
80
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
150
+ cmd = 'setenv bootargs root=ld0a'
81
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
151
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
82
152
+ cmd = 'setenv kernel netbsd-GENERIC.ub'
83
+
153
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
84
# Predicate operations
154
+ cmd = 'setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb'
85
%mask_22_13 22:1 13:3
155
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
86
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
156
+ cmd = ("setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; "
87
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
157
+ "fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; "
88
index XXXXXXX..XXXXXXX 100644
158
+ "fdt addr ${fdt_addr_r}; "
89
--- a/target/arm/mve_helper.c
159
+ "bootm ${kernel_addr_r} - ${fdt_addr_r}'")
90
+++ b/target/arm/mve_helper.c
160
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
91
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
161
+
92
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
162
+ exec_command_and_wait_for_pattern(self, 'boot',
93
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
163
+ 'Booting kernel from Legacy Image')
94
164
+ wait_for_console_pattern(self, 'Starting kernel ...')
95
+/*
165
+ wait_for_console_pattern(self, 'NetBSD 9.0 (GENERIC)')
96
+ * Long saturating scalar ops. As with DO_2OP_L, TYPE and H are for the
166
+ # Wait for user-space
97
+ * input (smaller) type and LESIZE, LTYPE, LH for the output (long) type.
167
+ wait_for_console_pattern(self, 'Starting root file system check')
98
+ * SATMASK specifies which bits of the predicate mask matter for determining
168
+
99
+ * whether to propagate a saturation indication into FPSCR.QC -- for
169
def test_s390x_s390_ccw_virtio(self):
100
+ * the 16x16->32 case we must check only the bit corresponding to the T or B
170
"""
101
+ * half that we used, but for the 32x32->64 case we propagate if the mask
171
:avocado: tags=arch:s390x
102
+ * bit is set for either half.
103
+ */
104
+#define DO_2OP_SAT_SCALAR_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN, SATMASK) \
105
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
106
+ uint32_t rm) \
107
+ { \
108
+ LTYPE *d = vd; \
109
+ TYPE *n = vn; \
110
+ TYPE m = rm; \
111
+ uint16_t mask = mve_element_mask(env); \
112
+ unsigned le; \
113
+ bool qc = false; \
114
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
115
+ bool sat = false; \
116
+ LTYPE r = FN((LTYPE)n[H##ESIZE(le * 2 + TOP)], m, &sat); \
117
+ mergemask(&d[H##LESIZE(le)], r, mask); \
118
+ qc |= sat && (mask & SATMASK); \
119
+ } \
120
+ if (qc) { \
121
+ env->vfp.qc[0] = qc; \
122
+ } \
123
+ mve_advance_vpt(env); \
124
+ }
125
+
126
+static inline int32_t do_qdmullh(int16_t n, int16_t m, bool *sat)
127
+{
128
+ int64_t r = ((int64_t)n * m) * 2;
129
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat);
130
+}
131
+
132
+static inline int64_t do_qdmullw(int32_t n, int32_t m, bool *sat)
133
+{
134
+ /* The multiply can't overflow, but the doubling might */
135
+ int64_t r = (int64_t)n * m;
136
+ if (r > INT64_MAX / 2) {
137
+ *sat = true;
138
+ return INT64_MAX;
139
+ } else if (r < INT64_MIN / 2) {
140
+ *sat = true;
141
+ return INT64_MIN;
142
+ } else {
143
+ return r * 2;
144
+ }
145
+}
146
+
147
+#define SATMASK16B 1
148
+#define SATMASK16T (1 << 2)
149
+#define SATMASK32 ((1 << 4) | 1)
150
+
151
+DO_2OP_SAT_SCALAR_L(vqdmullb_scalarh, 0, 2, int16_t, 4, int32_t, \
152
+ do_qdmullh, SATMASK16B)
153
+DO_2OP_SAT_SCALAR_L(vqdmullb_scalarw, 0, 4, int32_t, 8, int64_t, \
154
+ do_qdmullw, SATMASK32)
155
+DO_2OP_SAT_SCALAR_L(vqdmullt_scalarh, 1, 2, int16_t, 4, int32_t, \
156
+ do_qdmullh, SATMASK16T)
157
+DO_2OP_SAT_SCALAR_L(vqdmullt_scalarw, 1, 4, int32_t, 8, int64_t, \
158
+ do_qdmullw, SATMASK32)
159
+
160
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
161
{
162
m &= 0xff;
163
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/arm/translate-mve.c
166
+++ b/target/arm/translate-mve.c
167
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
168
DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
169
DO_2OP_SCALAR(VBRSR, vbrsr)
170
171
+static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
172
+{
173
+ static MVEGenTwoOpScalarFn * const fns[] = {
174
+ NULL,
175
+ gen_helper_mve_vqdmullb_scalarh,
176
+ gen_helper_mve_vqdmullb_scalarw,
177
+ NULL,
178
+ };
179
+ if (a->qd == a->qn && a->size == MO_32) {
180
+ /* UNPREDICTABLE; we choose to undef */
181
+ return false;
182
+ }
183
+ return do_2op_scalar(s, a, fns[a->size]);
184
+}
185
+
186
+static bool trans_VQDMULLT_scalar(DisasContext *s, arg_2scalar *a)
187
+{
188
+ static MVEGenTwoOpScalarFn * const fns[] = {
189
+ NULL,
190
+ gen_helper_mve_vqdmullt_scalarh,
191
+ gen_helper_mve_vqdmullt_scalarw,
192
+ NULL,
193
+ };
194
+ if (a->qd == a->qn && a->size == MO_32) {
195
+ /* UNPREDICTABLE; we choose to undef */
196
+ return false;
197
+ }
198
+ return do_2op_scalar(s, a, fns[a->size]);
199
+}
200
+
201
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
202
MVEGenDualAccOpFn *fn)
203
{
172
--
204
--
173
2.20.1
205
2.20.1
174
206
175
207
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
Implement the vector forms of the MVE VQDMULH and VQRDMULH insns.
2
2
3
Signed-off-by: Cédric Le Goater <clg@kaod.org>
4
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
5
Reviewed-by: Joel Stanley <joel@jms.id.au>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20200206112645.21275-2-clg@kaod.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-31-peter.maydell@linaro.org
9
---
6
---
10
Makefile.objs | 1 +
7
target/arm/helper-mve.h | 8 ++++++++
11
hw/ssi/aspeed_smc.c | 17 +++++++++++++++++
8
target/arm/mve.decode | 3 +++
12
hw/ssi/trace-events | 9 +++++++++
9
target/arm/mve_helper.c | 27 +++++++++++++++++++++++++++
13
3 files changed, 27 insertions(+)
10
target/arm/translate-mve.c | 2 ++
14
create mode 100644 hw/ssi/trace-events
11
4 files changed, 40 insertions(+)
15
12
16
diff --git a/Makefile.objs b/Makefile.objs
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/Makefile.objs
15
--- a/target/arm/helper-mve.h
19
+++ b/Makefile.objs
16
+++ b/target/arm/helper-mve.h
20
@@ -XXX,XX +XXX,XX @@ trace-events-subdirs += hw/scsi
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
trace-events-subdirs += hw/sd
18
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
trace-events-subdirs += hw/sparc
19
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
trace-events-subdirs += hw/sparc64
20
24
+trace-events-subdirs += hw/ssi
21
+DEF_HELPER_FLAGS_4(mve_vqdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
trace-events-subdirs += hw/timer
22
+DEF_HELPER_FLAGS_4(mve_vqdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
trace-events-subdirs += hw/tpm
23
+DEF_HELPER_FLAGS_4(mve_vqdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
trace-events-subdirs += hw/usb
24
+
28
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
25
+DEF_HELPER_FLAGS_4(mve_vqrdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vqrdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vqrdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+
29
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/ssi/aspeed_smc.c
34
--- a/target/arm/mve.decode
31
+++ b/hw/ssi/aspeed_smc.c
35
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@ VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
33
#include "qapi/error.h"
37
VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
34
#include "exec/address-spaces.h"
38
VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
35
#include "qemu/units.h"
39
36
+#include "trace.h"
40
+VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
37
41
+VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
38
#include "hw/irq.h"
39
#include "hw/qdev-properties.h"
40
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
41
42
s->ctrl->reg_to_segment(s, new, &seg);
43
44
+ trace_aspeed_smc_flash_set_segment(cs, new, seg.addr, seg.addr + seg.size);
45
+
42
+
46
/* The start address of CS0 is read-only */
43
# Vector miscellaneous
47
if (cs == 0 && seg.addr != s->ctrl->flash_window_base) {
44
48
qemu_log_mask(LOG_GUEST_ERROR,
45
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
49
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
50
__func__, aspeed_smc_flash_mode(fl));
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
51
mve_advance_vpt(env); \
51
}
52
}
52
53
53
+ trace_aspeed_smc_flash_read(fl->id, addr, size, ret,
54
+#define DO_2OP_SAT(OP, ESIZE, TYPE, FN) \
54
+ aspeed_smc_flash_mode(fl));
55
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
55
return ret;
56
+ { \
56
}
57
+ TYPE *d = vd, *n = vn, *m = vm; \
57
58
+ uint16_t mask = mve_element_mask(env); \
58
@@ -XXX,XX +XXX,XX @@ static bool aspeed_smc_do_snoop(AspeedSMCFlash *fl, uint64_t data,
59
+ unsigned e; \
59
AspeedSMCState *s = fl->controller;
60
+ bool qc = false; \
60
uint8_t addr_width = aspeed_smc_flash_is_4byte(fl) ? 4 : 3;
61
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
61
62
+ bool sat = false; \
62
+ trace_aspeed_smc_do_snoop(fl->id, s->snoop_index, s->snoop_dummies,
63
+ TYPE r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], &sat); \
63
+ (uint8_t) data & 0xff);
64
+ mergemask(&d[H##ESIZE(e)], r, mask); \
65
+ qc |= sat & mask & 1; \
66
+ } \
67
+ if (qc) { \
68
+ env->vfp.qc[0] = qc; \
69
+ } \
70
+ mve_advance_vpt(env); \
71
+ }
64
+
72
+
65
if (s->snoop_index == SNOOP_OFF) {
73
#define DO_AND(N, M) ((N) & (M))
66
return false; /* Do nothing */
74
#define DO_BIC(N, M) ((N) & ~(M))
67
75
#define DO_ORR(N, M) ((N) | (M))
68
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
76
@@ -XXX,XX +XXX,XX @@ static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
69
AspeedSMCState *s = fl->controller;
77
#define DO_QRDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 30)) >> 31, \
70
int i;
78
INT32_MIN, INT32_MAX, s)
71
79
72
+ trace_aspeed_smc_flash_write(fl->id, addr, size, data,
80
+DO_2OP_SAT(vqdmulhb, 1, int8_t, DO_QDMULH_B)
73
+ aspeed_smc_flash_mode(fl));
81
+DO_2OP_SAT(vqdmulhh, 2, int16_t, DO_QDMULH_H)
82
+DO_2OP_SAT(vqdmulhw, 4, int32_t, DO_QDMULH_W)
74
+
83
+
75
if (!aspeed_smc_is_writable(fl)) {
84
+DO_2OP_SAT(vqrdmulhb, 1, int8_t, DO_QRDMULH_B)
76
qemu_log_mask(LOG_GUEST_ERROR, "%s: flash is not writable at 0x%"
85
+DO_2OP_SAT(vqrdmulhh, 2, int16_t, DO_QRDMULH_H)
77
HWADDR_PRIx "\n", __func__, addr);
86
+DO_2OP_SAT(vqrdmulhw, 4, int32_t, DO_QRDMULH_W)
78
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
79
(s->ctrl->has_dma && addr == R_DMA_CHECKSUM) ||
80
(addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) ||
81
(addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_slaves)) {
82
+
87
+
83
+ trace_aspeed_smc_read(addr, size, s->regs[addr]);
88
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
84
+
89
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
85
return s->regs[addr];
90
uint32_t rm) \
86
} else {
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
87
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
92
index XXXXXXX..XXXXXXX 100644
88
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
93
--- a/target/arm/translate-mve.c
89
__func__, s->regs[R_DMA_FLASH_ADDR]);
94
+++ b/target/arm/translate-mve.c
90
return;
95
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BS, vmullbs)
91
}
96
DO_2OP(VMULL_BU, vmullbu)
92
+ trace_aspeed_smc_dma_checksum(s->regs[R_DMA_FLASH_ADDR], data);
97
DO_2OP(VMULL_TS, vmullts)
93
98
DO_2OP(VMULL_TU, vmulltu)
94
/*
99
+DO_2OP(VQDMULH, vqdmulh)
95
* When the DMA is on-going, the DMA registers are updated
100
+DO_2OP(VQRDMULH, vqrdmulh)
96
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
101
97
102
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
98
addr >>= 2;
103
MVEGenTwoOpScalarFn fn)
99
100
+ trace_aspeed_smc_write(addr, size, data);
101
+
102
if (addr == s->r_conf ||
103
(addr >= s->r_timings &&
104
addr < s->r_timings + s->ctrl->nregs_timings) ||
105
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
106
new file mode 100644
107
index XXXXXXX..XXXXXXX
108
--- /dev/null
109
+++ b/hw/ssi/trace-events
110
@@ -XXX,XX +XXX,XX @@
111
+# aspeed_smc.c
112
+
113
+aspeed_smc_flash_set_segment(int cs, uint64_t reg, uint64_t start, uint64_t end) "CS%d segreg=0x%"PRIx64" [ 0x%"PRIx64" - 0x%"PRIx64" ]"
114
+aspeed_smc_flash_read(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
115
+aspeed_smc_do_snoop(int cs, int index, int dummies, int data) "CS%d index:0x%x dummies:%d data:0x%x"
116
+aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
117
+aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
118
+aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
119
+aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
120
--
104
--
121
2.20.1
105
2.20.1
122
106
123
107
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Implement the vector forms of the MVE VQADD and VQSUB insns.
2
2
3
This test boots Ubuntu Bionic on a OrangePi PC board.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-32-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 16 ++++++++++++++++
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 39 insertions(+)
4
12
5
As it requires 1GB of storage, and is slow, this test is disabled
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
6
on automatic CI testing.
7
8
It is useful for workstation testing. Currently Avocado timeouts too
9
quickly, so we can't run userland commands.
10
11
The kernel image and DeviceTree blob are built by the Armbian
12
project (based on Debian):
13
https://www.armbian.com/orange-pi-pc/
14
15
The Ubuntu image is downloaded from:
16
https://dl.armbian.com/orangepipc/Bionic_current
17
18
This test can be run using:
19
20
$ AVOCADO_ALLOW_LARGE_STORAGE=yes \
21
avocado --show=app,console run -t machine:orangepi-pc \
22
tests/acceptance/boot_linux_console.py
23
console: U-Boot SPL 2019.04-armbian (Nov 18 2019 - 23:08:35 +0100)
24
console: DRAM: 1024 MiB
25
console: Failed to set core voltage! Can't set CPU frequency
26
console: Trying to boot from MMC1
27
console: U-Boot 2019.04-armbian (Nov 18 2019 - 23:08:35 +0100) Allwinner Technology
28
console: CPU: Allwinner H3 (SUN8I 0000)
29
console: Model: Xunlong Orange Pi PC
30
console: DRAM: 1 GiB
31
console: MMC: mmc@1c0f000: 0
32
[...]
33
console: Uncompressing Linux... done, booting the kernel.
34
console: Booting Linux on physical CPU 0x0
35
console: Linux version 5.3.9-sunxi (root@builder) (gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36))) #19.11.3 SMP Mon Nov 18 18:49:43 CET 2019
36
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
37
console: CPU: div instructions available: patching division code
38
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
39
console: OF: fdt: Machine model: Xunlong Orange Pi PC
40
[...]
41
console: EXT4-fs (mmcblk0p1): mounted filesystem with writeback data mode. Opts: (null)
42
console: done.
43
console: Begin: Running /scripts/local-bottom ... done.
44
console: Begin: Running /scripts/init-bottom ... done.
45
console: systemd[1]: systemd 237 running in system mode. (...)
46
console: systemd[1]: Detected architecture arm.
47
console: Welcome to Ubuntu 18.04.3 LTS!
48
console: systemd[1]: Set hostname to <orangepipc>.
49
50
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
51
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
52
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
53
Tested-by: Alex Bennée <alex.bennee@linaro.org>
54
Message-id: 20200311221854.30370-17-nieklinnenbank@gmail.com
55
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
56
[NL: changed test to boot from SD card via BootROM, added check for 7z]
57
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
58
---
59
tests/acceptance/boot_linux_console.py | 48 ++++++++++++++++++++++++++
60
1 file changed, 48 insertions(+)
61
62
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
63
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/acceptance/boot_linux_console.py
15
--- a/target/arm/helper-mve.h
65
+++ b/tests/acceptance/boot_linux_console.py
16
+++ b/target/arm/helper-mve.h
66
@@ -XXX,XX +XXX,XX @@ from avocado_qemu import exec_command_and_wait_for_pattern
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
67
from avocado_qemu import wait_for_console_pattern
18
DEF_HELPER_FLAGS_4(mve_vqrdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
68
from avocado.utils import process
19
DEF_HELPER_FLAGS_4(mve_vqrdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
69
from avocado.utils import archive
20
70
+from avocado.utils.path import find_command, CmdNotFoundError
21
+DEF_HELPER_FLAGS_4(mve_vqaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
71
22
+DEF_HELPER_FLAGS_4(mve_vqaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
72
+P7ZIP_AVAILABLE = True
23
+DEF_HELPER_FLAGS_4(mve_vqaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
73
+try:
74
+ find_command('7z')
75
+except CmdNotFoundError:
76
+ P7ZIP_AVAILABLE = False
77
78
class BootLinuxConsole(Test):
79
"""
80
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
81
exec_command_and_wait_for_pattern(self, 'reboot',
82
'reboot: Restarting system')
83
84
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
85
+ @skipUnless(P7ZIP_AVAILABLE, '7z not installed')
86
+ def test_arm_orangepi_bionic(self):
87
+ """
88
+ :avocado: tags=arch:arm
89
+ :avocado: tags=machine:orangepi-pc
90
+ """
91
+
24
+
92
+ # This test download a 196MB compressed image and expand it to 932MB...
25
+DEF_HELPER_FLAGS_4(mve_vqaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
93
+ image_url = ('https://dl.armbian.com/orangepipc/archive/'
26
+DEF_HELPER_FLAGS_4(mve_vqadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
94
+ 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z')
27
+DEF_HELPER_FLAGS_4(mve_vqadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
95
+ image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e'
96
+ image_path_7z = self.fetch_asset(image_url, asset_hash=image_hash)
97
+ image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img'
98
+ image_path = os.path.join(self.workdir, image_name)
99
+ process.run("7z e -o%s %s" % (self.workdir, image_path_7z))
100
+
28
+
101
+ self.vm.set_console()
29
+DEF_HELPER_FLAGS_4(mve_vqsubsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
102
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
30
+DEF_HELPER_FLAGS_4(mve_vqsubsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
103
+ '-nic', 'user',
31
+DEF_HELPER_FLAGS_4(mve_vqsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
104
+ '-no-reboot')
105
+ self.vm.launch()
106
+
32
+
107
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
33
+DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
108
+ 'console=ttyS0,115200 '
34
+DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
109
+ 'loglevel=7 '
35
+DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
110
+ 'nosmp '
111
+ 'systemd.default_timeout_start_sec=9000 '
112
+ 'systemd.mask=armbian-zram-config.service '
113
+ 'systemd.mask=armbian-ramlog.service')
114
+
36
+
115
+ self.wait_for_console_pattern('U-Boot SPL')
37
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
116
+ self.wait_for_console_pattern('Autoboot in ')
38
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
117
+ exec_command_and_wait_for_pattern(self, ' ', '=>')
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
118
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
40
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
119
+ kernel_command_line + "'", '=>')
41
index XXXXXXX..XXXXXXX 100644
120
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...');
42
--- a/target/arm/mve.decode
43
+++ b/target/arm/mve.decode
44
@@ -XXX,XX +XXX,XX @@ VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
45
VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
46
VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
47
48
+VQADD_S 111 0 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
49
+VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
50
+VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
51
+VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
121
+
52
+
122
+ self.wait_for_console_pattern('systemd[1]: Set hostname ' +
53
# Vector miscellaneous
123
+ 'to <orangepipc>')
54
124
+ self.wait_for_console_pattern('Starting Load Kernel Modules...')
55
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
56
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/mve_helper.c
59
+++ b/target/arm/mve_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqrdmulhb, 1, int8_t, DO_QRDMULH_B)
61
DO_2OP_SAT(vqrdmulhh, 2, int16_t, DO_QRDMULH_H)
62
DO_2OP_SAT(vqrdmulhw, 4, int32_t, DO_QRDMULH_W)
63
64
+DO_2OP_SAT(vqaddub, 1, uint8_t, DO_UQADD_B)
65
+DO_2OP_SAT(vqadduh, 2, uint16_t, DO_UQADD_H)
66
+DO_2OP_SAT(vqadduw, 4, uint32_t, DO_UQADD_W)
67
+DO_2OP_SAT(vqaddsb, 1, int8_t, DO_SQADD_B)
68
+DO_2OP_SAT(vqaddsh, 2, int16_t, DO_SQADD_H)
69
+DO_2OP_SAT(vqaddsw, 4, int32_t, DO_SQADD_W)
125
+
70
+
126
def test_s390x_s390_ccw_virtio(self):
71
+DO_2OP_SAT(vqsubub, 1, uint8_t, DO_UQSUB_B)
127
"""
72
+DO_2OP_SAT(vqsubuh, 2, uint16_t, DO_UQSUB_H)
128
:avocado: tags=arch:s390x
73
+DO_2OP_SAT(vqsubuw, 4, uint32_t, DO_UQSUB_W)
74
+DO_2OP_SAT(vqsubsb, 1, int8_t, DO_SQSUB_B)
75
+DO_2OP_SAT(vqsubsh, 2, int16_t, DO_SQSUB_H)
76
+DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
77
+
78
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
79
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
80
uint32_t rm) \
81
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/translate-mve.c
84
+++ b/target/arm/translate-mve.c
85
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_TS, vmullts)
86
DO_2OP(VMULL_TU, vmulltu)
87
DO_2OP(VQDMULH, vqdmulh)
88
DO_2OP(VQRDMULH, vqrdmulh)
89
+DO_2OP(VQADD_S, vqadds)
90
+DO_2OP(VQADD_U, vqaddu)
91
+DO_2OP(VQSUB_S, vqsubs)
92
+DO_2OP(VQSUB_U, vqsubu)
93
94
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
95
MVEGenTwoOpScalarFn fn)
129
--
96
--
130
2.20.1
97
2.20.1
131
98
132
99
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
Implement the MVE VQSHL insn (encoding T4, which is the
2
vector-shift-by-vector version).
2
3
3
SOC object returned by object_new() is leaked in current code.
4
The DO_SQSHL_OP and DO_UQSHL_OP macros here are derived from
4
Set SOC parent explicitly to board and then unref to SOC object
5
the neon_helper.c code for qshl_u{8,16,32} and qshl_s{8,16,32}.
5
to make sure that refererence returned by object_new() is taken
6
care of.
7
6
8
The SOC object will be kept alive by its parent (machine) and
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
will be automatically freed when MachineState is destroyed.
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210617121628.20116-33-peter.maydell@linaro.org
10
---
11
target/arm/helper-mve.h | 8 ++++++++
12
target/arm/mve.decode | 12 ++++++++++++
13
target/arm/mve_helper.c | 34 ++++++++++++++++++++++++++++++++++
14
target/arm/translate-mve.c | 2 ++
15
4 files changed, 56 insertions(+)
10
16
11
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
12
Reported-by: Andrew Jones <drjones@redhat.com>
13
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
Message-id: 20200303091254.22373-1-imammedo@redhat.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/arm/cubieboard.c | 3 +++
19
1 file changed, 3 insertions(+)
20
21
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/cubieboard.c
19
--- a/target/arm/helper-mve.h
24
+++ b/hw/arm/cubieboard.c
20
+++ b/target/arm/helper-mve.h
25
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
25
+DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+
29
+DEF_HELPER_FLAGS_4(mve_vqshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+DEF_HELPER_FLAGS_4(mve_vqshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vqshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+
33
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/mve.decode
39
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@
41
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
42
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
43
44
+# The _rev suffix indicates that Vn and Vm are reversed. This is
45
+# the case for shifts. In the Arm ARM these insns are documented
46
+# with the Vm and Vn fields in their usual places, but in the
47
+# assembly the operands are listed "backwards", ie in the order
48
+# Qd, Qm, Qn where other insns use Qd, Qn, Qm. For QEMU we choose
49
+# to consider Vm and Vn as being in different fields in the insn.
50
+# This gives us consistency with A64 and Neon.
51
+@2op_rev .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qn qn=%qm
52
+
53
@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
54
@2scalar_nosz .... .... .... .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
55
56
@@ -XXX,XX +XXX,XX @@ VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
57
VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
58
VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
59
60
+VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
61
+VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
62
+
63
# Vector miscellaneous
64
65
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
66
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/mve_helper.c
69
+++ b/target/arm/mve_helper.c
70
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
71
mve_advance_vpt(env); \
26
}
72
}
27
73
28
a10 = AW_A10(object_new(TYPE_AW_A10));
74
+/* provide unsigned 2-op helpers for all sizes */
29
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(a10),
75
+#define DO_2OP_SAT_U(OP, FN) \
30
+ &error_abort);
76
+ DO_2OP_SAT(OP##b, 1, uint8_t, FN) \
31
+ object_unref(OBJECT(a10));
77
+ DO_2OP_SAT(OP##h, 2, uint16_t, FN) \
32
78
+ DO_2OP_SAT(OP##w, 4, uint32_t, FN)
33
object_property_set_int(OBJECT(&a10->emac), 1, "phy-addr", &err);
79
+
34
if (err != NULL) {
80
+/* provide signed 2-op helpers for all sizes */
81
+#define DO_2OP_SAT_S(OP, FN) \
82
+ DO_2OP_SAT(OP##b, 1, int8_t, FN) \
83
+ DO_2OP_SAT(OP##h, 2, int16_t, FN) \
84
+ DO_2OP_SAT(OP##w, 4, int32_t, FN)
85
+
86
#define DO_AND(N, M) ((N) & (M))
87
#define DO_BIC(N, M) ((N) & ~(M))
88
#define DO_ORR(N, M) ((N) | (M))
89
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqsubsb, 1, int8_t, DO_SQSUB_B)
90
DO_2OP_SAT(vqsubsh, 2, int16_t, DO_SQSUB_H)
91
DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
92
93
+/*
94
+ * This wrapper fixes up the impedance mismatch between do_sqrshl_bhs()
95
+ * and friends wanting a uint32_t* sat and our needing a bool*.
96
+ */
97
+#define WRAP_QRSHL_HELPER(FN, N, M, ROUND, satp) \
98
+ ({ \
99
+ uint32_t su32 = 0; \
100
+ typeof(N) r = FN(N, (int8_t)(M), sizeof(N) * 8, ROUND, &su32); \
101
+ if (su32) { \
102
+ *satp = true; \
103
+ } \
104
+ r; \
105
+ })
106
+
107
+#define DO_SQSHL_OP(N, M, satp) \
108
+ WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, false, satp)
109
+#define DO_UQSHL_OP(N, M, satp) \
110
+ WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, false, satp)
111
+
112
+DO_2OP_SAT_S(vqshls, DO_SQSHL_OP)
113
+DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
114
+
115
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
116
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
117
uint32_t rm) \
118
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/target/arm/translate-mve.c
121
+++ b/target/arm/translate-mve.c
122
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQADD_S, vqadds)
123
DO_2OP(VQADD_U, vqaddu)
124
DO_2OP(VQSUB_S, vqsubs)
125
DO_2OP(VQSUB_U, vqsubu)
126
+DO_2OP(VQSHL_S, vqshls)
127
+DO_2OP(VQSHL_U, vqshlu)
128
129
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
130
MVEGenTwoOpScalarFn fn)
35
--
131
--
36
2.20.1
132
2.20.1
37
133
38
134
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Implement the MV VQRSHL (vector) insn. Again, the code to perform
2
the actual shifts is borrowed from neon_helper.c.
2
3
3
The kernel image and DeviceTree blob are built by the Armbian
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
project (based on Debian):
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
https://www.armbian.com/orange-pi-pc/
6
Message-id: 20210617121628.20116-34-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 8 ++++++++
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 6 ++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 19 insertions(+)
6
13
7
The SD image is from the kernelci.org project:
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
8
https://kernelci.org/faq/#the-code
9
10
If ARM is a target being built, "make check-acceptance" will
11
automatically include this test by the use of the "arch:arm" tags.
12
13
Alternatively, this test can be run using:
14
15
$ avocado --show=console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
16
console: Uncompressing Linux... done, booting the kernel.
17
console: Booting Linux on physical CPU 0x0
18
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
19
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
20
[...]
21
console: sunxi-wdt 1c20ca0.watchdog: Watchdog enabled (timeout=16 sec, nowayout=0)
22
console: sunxi-mmc 1c0f000.mmc: Linked as a consumer to regulator.2
23
console: sunxi-mmc 1c0f000.mmc: Got CD GPIO
24
console: ledtrig-cpu: registered to indicate activity on CPUs
25
console: hidraw: raw HID events driver (C) Jiri Kosina
26
console: usbcore: registered new interface driver usbhid
27
console: usbhid: USB HID core driver
28
console: Initializing XFRM netlink socket
29
console: sunxi-mmc 1c0f000.mmc: initialized, max. request size: 16384 KB
30
console: NET: Registered protocol family 10
31
console: mmc0: host does not support reading read-only switch, assuming write-enable
32
console: mmc0: Problem switching card into high-speed mode!
33
console: mmc0: new SD card at address 4567
34
console: mmcblk0: mmc0:4567 QEMU! 60.0 MiB
35
[...]
36
console: EXT4-fs (mmcblk0): mounting ext2 file system using the ext4 subsystem
37
console: EXT4-fs (mmcblk0): mounted filesystem without journal. Opts: (null)
38
console: VFS: Mounted root (ext2 filesystem) on device 179:0.
39
console: Run /sbin/init as init process
40
console: EXT4-fs (mmcblk0): re-mounted. Opts: block_validity,barrier,user_xattr,acl
41
console: Starting syslogd: OK
42
console: Starting klogd: OK
43
console: Populating /dev using udev: udevd[203]: starting version 3.2.7
44
console: /bin/sh: can't access tty; job control turned off
45
console: cat /proc/partitions
46
console: / # cat /proc/partitions
47
console: major minor #blocks name
48
console: 1 0 4096 ram0
49
console: 1 1 4096 ram1
50
console: 1 2 4096 ram2
51
console: 1 3 4096 ram3
52
console: 179 0 61440 mmcblk0
53
console: reboot
54
console: / # reboot
55
console: umount: devtmpfs busy - remounted read-only
56
console: EXT4-fs (mmcblk0): re-mounted. Opts: (null)
57
console: The system is going down NOW!
58
console: Sent SIGTERM to all processes
59
console: Sent SIGKILL to all processes
60
console: Requesting system reboot
61
console: reboot: Restarting system
62
JOB TIME : 68.64 s
63
64
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
65
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
66
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
67
Tested-by: Alex Bennée <alex.bennee@linaro.org>
68
Message-id: 20200311221854.30370-16-nieklinnenbank@gmail.com
69
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
70
[NL: extend test with ethernet device checks]
71
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
72
---
73
tests/acceptance/boot_linux_console.py | 47 ++++++++++++++++++++++++++
74
1 file changed, 47 insertions(+)
75
76
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
77
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
78
--- a/tests/acceptance/boot_linux_console.py
16
--- a/target/arm/helper-mve.h
79
+++ b/tests/acceptance/boot_linux_console.py
17
+++ b/target/arm/helper-mve.h
80
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
81
exec_command_and_wait_for_pattern(self, 'reboot',
19
DEF_HELPER_FLAGS_4(mve_vqshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
82
'reboot: Restarting system')
20
DEF_HELPER_FLAGS_4(mve_vqshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
83
21
84
+ def test_arm_orangepi_sd(self):
22
+DEF_HELPER_FLAGS_4(mve_vqrshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
85
+ """
23
+DEF_HELPER_FLAGS_4(mve_vqrshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
86
+ :avocado: tags=arch:arm
24
+DEF_HELPER_FLAGS_4(mve_vqrshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
87
+ :avocado: tags=machine:orangepi-pc
88
+ """
89
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
90
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
91
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
92
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
93
+ kernel_path = self.extract_from_deb(deb_path,
94
+ '/boot/vmlinuz-4.20.7-sunxi')
95
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
96
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
97
+ rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
98
+ 'kci-2019.02/armel/base/rootfs.ext2.xz')
99
+ rootfs_hash = '692510cb625efda31640d1de0a8d60e26040f061'
100
+ rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
101
+ rootfs_path = os.path.join(self.workdir, 'rootfs.cpio')
102
+ archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
103
+
25
+
104
+ self.vm.set_console()
26
+DEF_HELPER_FLAGS_4(mve_vqrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
105
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
27
+DEF_HELPER_FLAGS_4(mve_vqrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
106
+ 'console=ttyS0,115200 '
28
+DEF_HELPER_FLAGS_4(mve_vqrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
107
+ 'root=/dev/mmcblk0 rootwait rw '
108
+ 'panic=-1 noreboot')
109
+ self.vm.add_args('-kernel', kernel_path,
110
+ '-dtb', dtb_path,
111
+ '-drive', 'file=' + rootfs_path + ',if=sd,format=raw',
112
+ '-append', kernel_command_line,
113
+ '-no-reboot')
114
+ self.vm.launch()
115
+ shell_ready = "/bin/sh: can't access tty; job control turned off"
116
+ self.wait_for_console_pattern(shell_ready)
117
+
29
+
118
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
119
+ 'Allwinner sun8i Family')
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
120
+ exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
121
+ 'mmcblk0')
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
122
+ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up',
34
index XXXXXXX..XXXXXXX 100644
123
+ 'eth0: Link is Up')
35
--- a/target/arm/mve.decode
124
+ exec_command_and_wait_for_pattern(self, 'udhcpc eth0',
36
+++ b/target/arm/mve.decode
125
+ 'udhcpc: lease of 10.0.2.15 obtained')
37
@@ -XXX,XX +XXX,XX @@ VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
126
+ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2',
38
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
127
+ '3 packets transmitted, 3 packets received, 0% packet loss')
39
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
128
+ exec_command_and_wait_for_pattern(self, 'reboot',
40
129
+ 'reboot: Restarting system')
41
+VQRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
42
+VQRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
130
+
43
+
131
def test_s390x_s390_ccw_virtio(self):
44
# Vector miscellaneous
132
"""
45
133
:avocado: tags=arch:s390x
46
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
47
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/mve_helper.c
50
+++ b/target/arm/mve_helper.c
51
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
52
WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, false, satp)
53
#define DO_UQSHL_OP(N, M, satp) \
54
WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, false, satp)
55
+#define DO_SQRSHL_OP(N, M, satp) \
56
+ WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, true, satp)
57
+#define DO_UQRSHL_OP(N, M, satp) \
58
+ WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, true, satp)
59
60
DO_2OP_SAT_S(vqshls, DO_SQSHL_OP)
61
DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
62
+DO_2OP_SAT_S(vqrshls, DO_SQRSHL_OP)
63
+DO_2OP_SAT_U(vqrshlu, DO_UQRSHL_OP)
64
65
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
66
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
67
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/translate-mve.c
70
+++ b/target/arm/translate-mve.c
71
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSUB_S, vqsubs)
72
DO_2OP(VQSUB_U, vqsubu)
73
DO_2OP(VQSHL_S, vqshls)
74
DO_2OP(VQSHL_U, vqshlu)
75
+DO_2OP(VQRSHL_S, vqrshls)
76
+DO_2OP(VQRSHL_U, vqrshlu)
77
78
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
79
MVEGenTwoOpScalarFn fn)
134
--
80
--
135
2.20.1
81
2.20.1
136
82
137
83
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Implement the MVE VSHL insn (vector form).
2
2
3
This test boots a Linux kernel on a OrangePi PC board and verify
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the serial output is working.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-35-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 8 ++++++++
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 6 ++++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 19 insertions(+)
5
12
6
The kernel image and DeviceTree blob are built by the Armbian
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
7
project (based on Debian):
8
https://www.armbian.com/orange-pi-pc/
9
10
The cpio image used comes from the linux-build-test project:
11
https://github.com/groeck/linux-build-test
12
13
If ARM is a target being built, "make check-acceptance" will
14
automatically include this test by the use of the "arch:arm" tags.
15
16
Alternatively, this test can be run using:
17
18
$ avocado --show=console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
19
console: Uncompressing Linux... done, booting the kernel.
20
console: Booting Linux on physical CPU 0x0
21
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
22
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
23
console: CPU: div instructions available: patching division code
24
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
25
console: OF: fdt: Machine model: Xunlong Orange Pi PC
26
[...]
27
console: Trying to unpack rootfs image as initramfs...
28
console: Freeing initrd memory: 3256K
29
console: Freeing unused kernel memory: 1024K
30
console: Run /init as init process
31
console: mount: mounting devtmpfs on /dev failed: Device or resource busy
32
console: Starting logging: OK
33
console: Initializing random number generator... random: dd: uninitialized urandom read (512 bytes read)
34
console: done.
35
console: Starting network: OK
36
console: Found console ttyS0
37
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
38
console: Boot successful.
39
console: cat /proc/cpuinfo
40
console: / # cat /proc/cpuinfo
41
console: processor : 0
42
console: model name : ARMv7 Processor rev 5 (v7l)
43
console: BogoMIPS : 125.00
44
console: Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
45
console: CPU implementer : 0x41
46
console: CPU architecture: 7
47
console: CPU variant : 0x0
48
console: CPU part : 0xc07
49
console: CPU revision : 5
50
[...]
51
console: processor : 3
52
console: model name : ARMv7 Processor rev 5 (v7l)
53
console: BogoMIPS : 125.00
54
console: Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
55
console: CPU implementer : 0x41
56
console: CPU architecture: 7
57
console: CPU variant : 0x0
58
console: CPU part : 0xc07
59
console: CPU revision : 5
60
console: Hardware : Allwinner sun8i Family
61
console: Revision : 0000
62
console: Serial : 0000000000000000
63
console: cat /proc/iomem
64
console: / # cat /proc/iomem
65
console: 01000000-010fffff : clock@1000000
66
console: 01c00000-01c00fff : system-control@1c00000
67
console: 01c02000-01c02fff : dma-controller@1c02000
68
[...]
69
console: reboot
70
console: / # reboot
71
console: / # Found console ttyS0
72
console: Stopping network: OK
73
console: hrtimer: interrupt took 21852064 ns
74
console: Saving random seed... random: dd: uninitialized urandom read (512 bytes read)
75
console: done.
76
console: Stopping logging: OK
77
console: umount: devtmpfs busy - remounted read-only
78
console: umount: can't unmount /: Invalid argument
79
console: The system is going down NOW!
80
console: Sent SIGTERM to all processes
81
console: Sent SIGKILL to all processes
82
console: Requesting system reboot
83
console: reboot: Restarting system
84
PASS (48.32 s)
85
JOB TIME : 49.16 s
86
87
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
88
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
89
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
90
Tested-by: Alex Bennée <alex.bennee@linaro.org>
91
Message-id: 20200311221854.30370-15-nieklinnenbank@gmail.com
92
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
93
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
94
---
95
tests/acceptance/boot_linux_console.py | 40 ++++++++++++++++++++++++++
96
1 file changed, 40 insertions(+)
97
98
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
99
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
100
--- a/tests/acceptance/boot_linux_console.py
15
--- a/target/arm/helper-mve.h
101
+++ b/tests/acceptance/boot_linux_console.py
16
+++ b/target/arm/helper-mve.h
102
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
103
console_pattern = 'Kernel command line: %s' % kernel_command_line
18
DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
104
self.wait_for_console_pattern(console_pattern)
19
DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
105
20
106
+ def test_arm_orangepi_initrd(self):
21
+DEF_HELPER_FLAGS_4(mve_vshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
107
+ """
22
+DEF_HELPER_FLAGS_4(mve_vshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
108
+ :avocado: tags=arch:arm
23
+DEF_HELPER_FLAGS_4(mve_vshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
109
+ :avocado: tags=machine:orangepi-pc
110
+ """
111
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
112
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
113
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
114
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
115
+ kernel_path = self.extract_from_deb(deb_path,
116
+ '/boot/vmlinuz-4.20.7-sunxi')
117
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
118
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
119
+ initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
120
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
121
+ 'arm/rootfs-armv7a.cpio.gz')
122
+ initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c'
123
+ initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
124
+ initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
125
+ archive.gzip_uncompress(initrd_path_gz, initrd_path)
126
+
24
+
127
+ self.vm.set_console()
25
+DEF_HELPER_FLAGS_4(mve_vshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
128
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
26
+DEF_HELPER_FLAGS_4(mve_vshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
129
+ 'console=ttyS0,115200 '
27
+DEF_HELPER_FLAGS_4(mve_vshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
130
+ 'panic=-1 noreboot')
131
+ self.vm.add_args('-kernel', kernel_path,
132
+ '-dtb', dtb_path,
133
+ '-initrd', initrd_path,
134
+ '-append', kernel_command_line,
135
+ '-no-reboot')
136
+ self.vm.launch()
137
+ self.wait_for_console_pattern('Boot successful.')
138
+
28
+
139
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
29
DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
140
+ 'Allwinner sun8i Family')
30
DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
141
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
31
DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
142
+ 'system-control@1c00000')
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
143
+ exec_command_and_wait_for_pattern(self, 'reboot',
33
index XXXXXXX..XXXXXXX 100644
144
+ 'reboot: Restarting system')
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
37
VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
38
VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
39
40
+VSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
41
+VSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
145
+
42
+
146
def test_s390x_s390_ccw_virtio(self):
43
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
147
"""
44
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
148
:avocado: tags=arch:s390x
45
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhaddu, do_vhadd_u)
51
DO_2OP_S(vhsubs, do_vhsub_s)
52
DO_2OP_U(vhsubu, do_vhsub_u)
53
54
+#define DO_VSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
55
+#define DO_VSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
56
+
57
+DO_2OP_S(vshls, DO_VSHLS)
58
+DO_2OP_U(vshlu, DO_VSHLU)
59
+
60
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
61
{
62
if (val > max) {
63
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-mve.c
66
+++ b/target/arm/translate-mve.c
67
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQADD_S, vqadds)
68
DO_2OP(VQADD_U, vqaddu)
69
DO_2OP(VQSUB_S, vqsubs)
70
DO_2OP(VQSUB_U, vqsubu)
71
+DO_2OP(VSHL_S, vshls)
72
+DO_2OP(VSHL_U, vshlu)
73
DO_2OP(VQSHL_S, vqshls)
74
DO_2OP(VQSHL_U, vqshlu)
75
DO_2OP(VQRSHL_S, vqrshls)
149
--
76
--
150
2.20.1
77
2.20.1
151
78
152
79
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Implement the MVE VRSHL insn (vector form).
2
2
3
This test boots a Linux kernel on a OrangePi PC board and verify
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the serial output is working.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-36-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 8 ++++++++
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 4 ++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 17 insertions(+)
5
12
6
The kernel image and DeviceTree blob are built by the Armbian
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
7
project (based on Debian):
8
https://www.armbian.com/orange-pi-pc/
9
10
If ARM is a target being built, "make check-acceptance" will
11
automatically include this test by the use of the "arch:arm" tags.
12
13
Alternatively, this test can be run using:
14
15
$ make check-venv
16
$ ./tests/venv/bin/avocado --show=console,app run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
17
JOB ID : 2e4d15eceb13c33672af406f08171e6e9de1414a
18
JOB LOG : ~/job-results/job-2019-12-17T05.46-2e4d15e/job.log
19
(1/1) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
20
console: Uncompressing Linux... done, booting the kernel.
21
console: Booting Linux on physical CPU 0x0
22
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
23
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
24
console: CPU: div instructions available: patching division code
25
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
26
console: OF: fdt: Machine model: Xunlong Orange Pi PC
27
console: Memory policy: Data cache writealloc
28
console: OF: reserved mem: failed to allocate memory for node 'cma@4a000000'
29
console: cma: Failed to reserve 128 MiB
30
console: psci: probing for conduit method from DT.
31
console: psci: PSCIv0.2 detected in firmware.
32
console: psci: Using standard PSCI v0.2 function IDs
33
console: psci: Trusted OS migration not required
34
console: random: get_random_bytes called from start_kernel+0x8d/0x3c2 with crng_init=0
35
console: percpu: Embedded 18 pages/cpu @(ptrval) s41228 r8192 d24308 u73728
36
console: Built 1 zonelists, mobility grouping on. Total pages: 32480
37
console: Kernel command line: printk.time=0 console=ttyS0,115200
38
PASS (8.59 s)
39
JOB TIME : 8.81 s
40
41
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
42
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
43
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
44
Tested-by: Alex Bennée <alex.bennee@linaro.org>
45
Message-id: 20200311221854.30370-14-nieklinnenbank@gmail.com
46
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
47
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
48
---
49
tests/acceptance/boot_linux_console.py | 25 +++++++++++++++++++++++++
50
1 file changed, 25 insertions(+)
51
52
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
53
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
54
--- a/tests/acceptance/boot_linux_console.py
15
--- a/target/arm/helper-mve.h
55
+++ b/tests/acceptance/boot_linux_console.py
16
+++ b/target/arm/helper-mve.h
56
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
57
exec_command_and_wait_for_pattern(self, 'reboot',
18
DEF_HELPER_FLAGS_4(mve_vshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
58
'reboot: Restarting system')
19
DEF_HELPER_FLAGS_4(mve_vshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
59
20
60
+ def test_arm_orangepi(self):
21
+DEF_HELPER_FLAGS_4(mve_vrshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
61
+ """
22
+DEF_HELPER_FLAGS_4(mve_vrshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
62
+ :avocado: tags=arch:arm
23
+DEF_HELPER_FLAGS_4(mve_vrshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
63
+ :avocado: tags=machine:orangepi-pc
64
+ """
65
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
66
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
67
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
68
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
69
+ kernel_path = self.extract_from_deb(deb_path,
70
+ '/boot/vmlinuz-4.20.7-sunxi')
71
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
72
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
73
+
24
+
74
+ self.vm.set_console()
25
+DEF_HELPER_FLAGS_4(mve_vrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
75
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
26
+DEF_HELPER_FLAGS_4(mve_vrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
76
+ 'console=ttyS0,115200n8 '
27
+DEF_HELPER_FLAGS_4(mve_vrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
77
+ 'earlycon=uart,mmio32,0x1c28000')
78
+ self.vm.add_args('-kernel', kernel_path,
79
+ '-dtb', dtb_path,
80
+ '-append', kernel_command_line)
81
+ self.vm.launch()
82
+ console_pattern = 'Kernel command line: %s' % kernel_command_line
83
+ self.wait_for_console_pattern(console_pattern)
84
+
28
+
85
def test_s390x_s390_ccw_virtio(self):
29
DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
86
"""
30
DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
87
:avocado: tags=arch:s390x
31
DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
37
VSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
38
VSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
39
40
+VRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 0 ... 0 @2op_rev
41
+VRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 0 ... 0 @2op_rev
42
+
43
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
44
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
45
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
51
52
#define DO_VSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
53
#define DO_VSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
54
+#define DO_VRSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, true, NULL)
55
+#define DO_VRSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, true, NULL)
56
57
DO_2OP_S(vshls, DO_VSHLS)
58
DO_2OP_U(vshlu, DO_VSHLU)
59
+DO_2OP_S(vrshls, DO_VRSHLS)
60
+DO_2OP_U(vrshlu, DO_VRSHLU)
61
62
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
63
{
64
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate-mve.c
67
+++ b/target/arm/translate-mve.c
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSUB_S, vqsubs)
69
DO_2OP(VQSUB_U, vqsubu)
70
DO_2OP(VSHL_S, vshls)
71
DO_2OP(VSHL_U, vshlu)
72
+DO_2OP(VRSHL_S, vrshls)
73
+DO_2OP(VRSHL_U, vrshlu)
74
DO_2OP(VQSHL_S, vqshls)
75
DO_2OP(VQSHL_U, vqshlu)
76
DO_2OP(VQRSHL_S, vqrshls)
88
--
77
--
89
2.20.1
78
2.20.1
90
79
91
80
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement the MVE VQDMLADH and VQRDMLADH insns. These multiply
2
elements, and then add pairs of products, double, possibly round,
3
saturate and return the high half of the result.
2
4
3
The Allwinner H3 System on Chip has an System Control
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
module that provides system wide generic controls and
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
device information. This commit adds support for the
7
Message-id: 20210617121628.20116-37-peter.maydell@linaro.org
6
Allwinner H3 System Control module.
8
---
9
target/arm/helper-mve.h | 16 +++++++
10
target/arm/mve.decode | 5 +++
11
target/arm/mve_helper.c | 89 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-mve.c | 4 ++
13
4 files changed, 114 insertions(+)
7
14
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Message-id: 20200311221854.30370-6-nieklinnenbank@gmail.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/misc/Makefile.objs | 1 +
16
include/hw/arm/allwinner-h3.h | 3 +
17
include/hw/misc/allwinner-h3-sysctrl.h | 67 ++++++++++++
18
hw/arm/allwinner-h3.c | 9 +-
19
hw/misc/allwinner-h3-sysctrl.c | 140 +++++++++++++++++++++++++
20
5 files changed, 219 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/misc/allwinner-h3-sysctrl.h
22
create mode 100644 hw/misc/allwinner-h3-sysctrl.c
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/Makefile.objs
17
--- a/target/arm/helper-mve.h
27
+++ b/hw/misc/Makefile.objs
18
+++ b/target/arm/helper-mve.h
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
20
DEF_HELPER_FLAGS_4(mve_vqrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
21
DEF_HELPER_FLAGS_4(mve_vqrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
22
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
23
+DEF_HELPER_FLAGS_4(mve_vqdmladhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
24
+DEF_HELPER_FLAGS_4(mve_vqdmladhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
common-obj-$(CONFIG_NSERIES) += cbus.o
25
+DEF_HELPER_FLAGS_4(mve_vqdmladhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
26
+
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
27
+DEF_HELPER_FLAGS_4(mve_vqdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vqdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+DEF_HELPER_FLAGS_4(mve_vqdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+
31
+DEF_HELPER_FLAGS_4(mve_vqrdmladhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vqrdmladhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vqrdmladhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+
35
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
38
+
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
44
--- a/target/arm/mve.decode
39
+++ b/include/hw/arm/allwinner-h3.h
45
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
41
#include "hw/timer/allwinner-a10-pit.h"
47
VQRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
42
#include "hw/intc/arm_gic.h"
48
VQRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
43
#include "hw/misc/allwinner-h3-ccu.h"
49
44
+#include "hw/misc/allwinner-h3-sysctrl.h"
50
+VQDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
45
#include "target/arm/cpu.h"
51
+VQDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
46
52
+VQRDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
47
/**
53
+VQRDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
48
@@ -XXX,XX +XXX,XX @@ enum {
54
+
49
AW_H3_SRAM_A1,
55
# Vector miscellaneous
50
AW_H3_SRAM_A2,
56
51
AW_H3_SRAM_C,
57
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
+ AW_H3_SYSCTRL,
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
AW_H3_EHCI0,
59
index XXXXXXX..XXXXXXX 100644
54
AW_H3_OHCI0,
60
--- a/target/arm/mve_helper.c
55
AW_H3_EHCI1,
61
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
62
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
57
const hwaddr *memmap;
63
DO_2OP_SAT_S(vqrshls, DO_SQRSHL_OP)
58
AwA10PITState timer;
64
DO_2OP_SAT_U(vqrshlu, DO_UQRSHL_OP)
59
AwH3ClockCtlState ccu;
65
60
+ AwH3SysCtrlState sysctrl;
61
GICState gic;
62
MemoryRegion sram_a1;
63
MemoryRegion sram_a2;
64
diff --git a/include/hw/misc/allwinner-h3-sysctrl.h b/include/hw/misc/allwinner-h3-sysctrl.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/allwinner-h3-sysctrl.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
66
+/*
71
+ * Allwinner H3 System Control emulation
67
+ * Multiply add dual returning high half
72
+ *
68
+ * The 'FN' here takes four inputs A, B, C, D, a 0/1 indicator of
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
69
+ * whether to add the rounding constant, and the pointer to the
74
+ *
70
+ * saturation flag, and should do "(A * B + C * D) * 2 + rounding constant",
75
+ * This program is free software: you can redistribute it and/or modify
71
+ * saturate to twice the input size and return the high half; or
76
+ * it under the terms of the GNU General Public License as published by
72
+ * (A * B - C * D) etc for VQDMLSDH.
77
+ * the Free Software Foundation, either version 2 of the License, or
78
+ * (at your option) any later version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful,
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
+ * GNU General Public License for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
73
+ */
88
+
74
+#define DO_VQDMLADH_OP(OP, ESIZE, TYPE, XCHG, ROUND, FN) \
89
+#ifndef HW_MISC_ALLWINNER_H3_SYSCTRL_H
75
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
90
+#define HW_MISC_ALLWINNER_H3_SYSCTRL_H
76
+ void *vm) \
91
+
77
+ { \
92
+#include "qom/object.h"
78
+ TYPE *d = vd, *n = vn, *m = vm; \
93
+#include "hw/sysbus.h"
79
+ uint16_t mask = mve_element_mask(env); \
94
+
80
+ unsigned e; \
95
+/**
81
+ bool qc = false; \
96
+ * @name Constants
82
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
97
+ * @{
83
+ bool sat = false; \
98
+ */
84
+ if ((e & 1) == XCHG) { \
99
+
85
+ TYPE r = FN(n[H##ESIZE(e)], \
100
+/** Highest register address used by System Control device */
86
+ m[H##ESIZE(e - XCHG)], \
101
+#define AW_H3_SYSCTRL_REGS_MAXADDR (0x30)
87
+ n[H##ESIZE(e + (1 - 2 * XCHG))], \
102
+
88
+ m[H##ESIZE(e + (1 - XCHG))], \
103
+/** Total number of known registers */
89
+ ROUND, &sat); \
104
+#define AW_H3_SYSCTRL_REGS_NUM ((AW_H3_SYSCTRL_REGS_MAXADDR / \
90
+ mergemask(&d[H##ESIZE(e)], r, mask); \
105
+ sizeof(uint32_t)) + 1)
91
+ qc |= sat & mask & 1; \
106
+
92
+ } \
107
+/** @} */
93
+ } \
108
+
94
+ if (qc) { \
109
+/**
95
+ env->vfp.qc[0] = qc; \
110
+ * @name Object model
96
+ } \
111
+ * @{
97
+ mve_advance_vpt(env); \
112
+ */
113
+
114
+#define TYPE_AW_H3_SYSCTRL "allwinner-h3-sysctrl"
115
+#define AW_H3_SYSCTRL(obj) \
116
+ OBJECT_CHECK(AwH3SysCtrlState, (obj), TYPE_AW_H3_SYSCTRL)
117
+
118
+/** @} */
119
+
120
+/**
121
+ * Allwinner H3 System Control object instance state
122
+ */
123
+typedef struct AwH3SysCtrlState {
124
+ /*< private >*/
125
+ SysBusDevice parent_obj;
126
+ /*< public >*/
127
+
128
+ /** Maps I/O registers in physical memory */
129
+ MemoryRegion iomem;
130
+
131
+ /** Array of hardware registers */
132
+ uint32_t regs[AW_H3_SYSCTRL_REGS_NUM];
133
+
134
+} AwH3SysCtrlState;
135
+
136
+#endif /* HW_MISC_ALLWINNER_H3_SYSCTRL_H */
137
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/hw/arm/allwinner-h3.c
140
+++ b/hw/arm/allwinner-h3.c
141
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
142
[AW_H3_SRAM_A1] = 0x00000000,
143
[AW_H3_SRAM_A2] = 0x00044000,
144
[AW_H3_SRAM_C] = 0x00010000,
145
+ [AW_H3_SYSCTRL] = 0x01c00000,
146
[AW_H3_EHCI0] = 0x01c1a000,
147
[AW_H3_OHCI0] = 0x01c1a400,
148
[AW_H3_EHCI1] = 0x01c1b000,
149
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
150
} unimplemented[] = {
151
{ "d-engine", 0x01000000, 4 * MiB },
152
{ "d-inter", 0x01400000, 128 * KiB },
153
- { "syscon", 0x01c00000, 4 * KiB },
154
{ "dma", 0x01c02000, 4 * KiB },
155
{ "nfdc", 0x01c03000, 4 * KiB },
156
{ "ts", 0x01c06000, 4 * KiB },
157
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
158
159
sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu),
160
TYPE_AW_H3_CCU);
161
+
162
+ sysbus_init_child_obj(obj, "sysctrl", &s->sysctrl, sizeof(s->sysctrl),
163
+ TYPE_AW_H3_SYSCTRL);
164
}
165
166
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
167
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
168
qdev_init_nofail(DEVICE(&s->ccu));
169
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
170
171
+ /* System Control */
172
+ qdev_init_nofail(DEVICE(&s->sysctrl));
173
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, s->memmap[AW_H3_SYSCTRL]);
174
+
175
/* Universal Serial Bus */
176
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
177
qdev_get_gpio_in(DEVICE(&s->gic),
178
diff --git a/hw/misc/allwinner-h3-sysctrl.c b/hw/misc/allwinner-h3-sysctrl.c
179
new file mode 100644
180
index XXXXXXX..XXXXXXX
181
--- /dev/null
182
+++ b/hw/misc/allwinner-h3-sysctrl.c
183
@@ -XXX,XX +XXX,XX @@
184
+/*
185
+ * Allwinner H3 System Control emulation
186
+ *
187
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
188
+ *
189
+ * This program is free software: you can redistribute it and/or modify
190
+ * it under the terms of the GNU General Public License as published by
191
+ * the Free Software Foundation, either version 2 of the License, or
192
+ * (at your option) any later version.
193
+ *
194
+ * This program is distributed in the hope that it will be useful,
195
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
196
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
197
+ * GNU General Public License for more details.
198
+ *
199
+ * You should have received a copy of the GNU General Public License
200
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
201
+ */
202
+
203
+#include "qemu/osdep.h"
204
+#include "qemu/units.h"
205
+#include "hw/sysbus.h"
206
+#include "migration/vmstate.h"
207
+#include "qemu/log.h"
208
+#include "qemu/module.h"
209
+#include "hw/misc/allwinner-h3-sysctrl.h"
210
+
211
+/* System Control register offsets */
212
+enum {
213
+ REG_VER = 0x24, /* Version */
214
+ REG_EMAC_PHY_CLK = 0x30, /* EMAC PHY Clock */
215
+};
216
+
217
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
218
+
219
+/* System Control register reset values */
220
+enum {
221
+ REG_VER_RST = 0x0,
222
+ REG_EMAC_PHY_CLK_RST = 0x58000,
223
+};
224
+
225
+static uint64_t allwinner_h3_sysctrl_read(void *opaque, hwaddr offset,
226
+ unsigned size)
227
+{
228
+ const AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
229
+ const uint32_t idx = REG_INDEX(offset);
230
+
231
+ if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
232
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
233
+ __func__, (uint32_t)offset);
234
+ return 0;
235
+ }
98
+ }
236
+
99
+
237
+ return s->regs[idx];
100
+static int8_t do_vqdmladh_b(int8_t a, int8_t b, int8_t c, int8_t d,
101
+ int round, bool *sat)
102
+{
103
+ int64_t r = ((int64_t)a * b + (int64_t)c * d) * 2 + (round << 7);
104
+ return do_sat_bhw(r, INT16_MIN, INT16_MAX, sat) >> 8;
238
+}
105
+}
239
+
106
+
240
+static void allwinner_h3_sysctrl_write(void *opaque, hwaddr offset,
107
+static int16_t do_vqdmladh_h(int16_t a, int16_t b, int16_t c, int16_t d,
241
+ uint64_t val, unsigned size)
108
+ int round, bool *sat)
242
+{
109
+{
243
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
110
+ int64_t r = ((int64_t)a * b + (int64_t)c * d) * 2 + (round << 15);
244
+ const uint32_t idx = REG_INDEX(offset);
111
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat) >> 16;
245
+
246
+ if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
247
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
248
+ __func__, (uint32_t)offset);
249
+ return;
250
+ }
251
+
252
+ switch (offset) {
253
+ case REG_VER: /* Version */
254
+ break;
255
+ default:
256
+ s->regs[idx] = (uint32_t) val;
257
+ break;
258
+ }
259
+}
112
+}
260
+
113
+
261
+static const MemoryRegionOps allwinner_h3_sysctrl_ops = {
114
+static int32_t do_vqdmladh_w(int32_t a, int32_t b, int32_t c, int32_t d,
262
+ .read = allwinner_h3_sysctrl_read,
115
+ int round, bool *sat)
263
+ .write = allwinner_h3_sysctrl_write,
264
+ .endianness = DEVICE_NATIVE_ENDIAN,
265
+ .valid = {
266
+ .min_access_size = 4,
267
+ .max_access_size = 4,
268
+ },
269
+ .impl.min_access_size = 4,
270
+};
271
+
272
+static void allwinner_h3_sysctrl_reset(DeviceState *dev)
273
+{
116
+{
274
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(dev);
117
+ int64_t m1 = (int64_t)a * b;
275
+
118
+ int64_t m2 = (int64_t)c * d;
276
+ /* Set default values for registers */
119
+ int64_t r;
277
+ s->regs[REG_INDEX(REG_VER)] = REG_VER_RST;
120
+ /*
278
+ s->regs[REG_INDEX(REG_EMAC_PHY_CLK)] = REG_EMAC_PHY_CLK_RST;
121
+ * Architecturally we should do the entire add, double, round
122
+ * and then check for saturation. We do three saturating adds,
123
+ * but we need to be careful about the order. If the first
124
+ * m1 + m2 saturates then it's impossible for the *2+rc to
125
+ * bring it back into the non-saturated range. However, if
126
+ * m1 + m2 is negative then it's possible that doing the doubling
127
+ * would take the intermediate result below INT64_MAX and the
128
+ * addition of the rounding constant then brings it back in range.
129
+ * So we add half the rounding constant before doubling rather
130
+ * than adding the rounding constant after the doubling.
131
+ */
132
+ if (sadd64_overflow(m1, m2, &r) ||
133
+ sadd64_overflow(r, (round << 30), &r) ||
134
+ sadd64_overflow(r, r, &r)) {
135
+ *sat = true;
136
+ return r < 0 ? INT32_MAX : INT32_MIN;
137
+ }
138
+ return r >> 32;
279
+}
139
+}
280
+
140
+
281
+static void allwinner_h3_sysctrl_init(Object *obj)
141
+DO_VQDMLADH_OP(vqdmladhb, 1, int8_t, 0, 0, do_vqdmladh_b)
282
+{
142
+DO_VQDMLADH_OP(vqdmladhh, 2, int16_t, 0, 0, do_vqdmladh_h)
283
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
143
+DO_VQDMLADH_OP(vqdmladhw, 4, int32_t, 0, 0, do_vqdmladh_w)
284
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(obj);
144
+DO_VQDMLADH_OP(vqdmladhxb, 1, int8_t, 1, 0, do_vqdmladh_b)
145
+DO_VQDMLADH_OP(vqdmladhxh, 2, int16_t, 1, 0, do_vqdmladh_h)
146
+DO_VQDMLADH_OP(vqdmladhxw, 4, int32_t, 1, 0, do_vqdmladh_w)
285
+
147
+
286
+ /* Memory mapping */
148
+DO_VQDMLADH_OP(vqrdmladhb, 1, int8_t, 0, 1, do_vqdmladh_b)
287
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_h3_sysctrl_ops, s,
149
+DO_VQDMLADH_OP(vqrdmladhh, 2, int16_t, 0, 1, do_vqdmladh_h)
288
+ TYPE_AW_H3_SYSCTRL, 4 * KiB);
150
+DO_VQDMLADH_OP(vqrdmladhw, 4, int32_t, 0, 1, do_vqdmladh_w)
289
+ sysbus_init_mmio(sbd, &s->iomem);
151
+DO_VQDMLADH_OP(vqrdmladhxb, 1, int8_t, 1, 1, do_vqdmladh_b)
290
+}
152
+DO_VQDMLADH_OP(vqrdmladhxh, 2, int16_t, 1, 1, do_vqdmladh_h)
153
+DO_VQDMLADH_OP(vqrdmladhxw, 4, int32_t, 1, 1, do_vqdmladh_w)
291
+
154
+
292
+static const VMStateDescription allwinner_h3_sysctrl_vmstate = {
155
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
293
+ .name = "allwinner-h3-sysctrl",
156
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
294
+ .version_id = 1,
157
uint32_t rm) \
295
+ .minimum_version_id = 1,
158
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
296
+ .fields = (VMStateField[]) {
159
index XXXXXXX..XXXXXXX 100644
297
+ VMSTATE_UINT32_ARRAY(regs, AwH3SysCtrlState, AW_H3_SYSCTRL_REGS_NUM),
160
--- a/target/arm/translate-mve.c
298
+ VMSTATE_END_OF_LIST()
161
+++ b/target/arm/translate-mve.c
299
+ }
162
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSHL_S, vqshls)
300
+};
163
DO_2OP(VQSHL_U, vqshlu)
301
+
164
DO_2OP(VQRSHL_S, vqrshls)
302
+static void allwinner_h3_sysctrl_class_init(ObjectClass *klass, void *data)
165
DO_2OP(VQRSHL_U, vqrshlu)
303
+{
166
+DO_2OP(VQDMLADH, vqdmladh)
304
+ DeviceClass *dc = DEVICE_CLASS(klass);
167
+DO_2OP(VQDMLADHX, vqdmladhx)
305
+
168
+DO_2OP(VQRDMLADH, vqrdmladh)
306
+ dc->reset = allwinner_h3_sysctrl_reset;
169
+DO_2OP(VQRDMLADHX, vqrdmladhx)
307
+ dc->vmsd = &allwinner_h3_sysctrl_vmstate;
170
308
+}
171
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
309
+
172
MVEGenTwoOpScalarFn fn)
310
+static const TypeInfo allwinner_h3_sysctrl_info = {
311
+ .name = TYPE_AW_H3_SYSCTRL,
312
+ .parent = TYPE_SYS_BUS_DEVICE,
313
+ .instance_init = allwinner_h3_sysctrl_init,
314
+ .instance_size = sizeof(AwH3SysCtrlState),
315
+ .class_init = allwinner_h3_sysctrl_class_init,
316
+};
317
+
318
+static void allwinner_h3_sysctrl_register(void)
319
+{
320
+ type_register_static(&allwinner_h3_sysctrl_info);
321
+}
322
+
323
+type_init(allwinner_h3_sysctrl_register)
324
--
173
--
325
2.20.1
174
2.20.1
326
175
327
176
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the MVE VQDMLSDH and VQRDMLSDH insns, which are
2
like VQDMLADH and VQRDMLADH except that products are subtracted
3
rather than added.
2
4
3
We must include the tag in the FAR_ELx register when raising
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
an addressing exception. Which means that we should not clear
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
out the tag during translation.
7
Message-id: 20210617121628.20116-38-peter.maydell@linaro.org
8
---
9
target/arm/helper-mve.h | 16 ++++++++++++++
10
target/arm/mve.decode | 5 +++++
11
target/arm/mve_helper.c | 44 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-mve.c | 4 ++++
13
4 files changed, 69 insertions(+)
6
14
7
We cannot at present comply with this for user mode, so we
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
8
retain the clean_data_tbi function for the moment, though it
9
no longer does what it says on the tin for system mode. This
10
function is to be replaced with MTE, so don't worry about the
11
slight misnaming.
12
13
Buglink: https://bugs.launchpad.net/qemu/+bug/1867072
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200308012946.16303-3-richard.henderson@linaro.org
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
target/arm/translate-a64.c | 11 +++++++++++
20
1 file changed, 11 insertions(+)
21
22
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
23
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/translate-a64.c
17
--- a/target/arm/helper-mve.h
25
+++ b/target/arm/translate-a64.c
18
+++ b/target/arm/helper-mve.h
26
@@ -XXX,XX +XXX,XX @@ static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr)
20
DEF_HELPER_FLAGS_4(mve_vqrdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
{
21
DEF_HELPER_FLAGS_4(mve_vqrdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
TCGv_i64 clean = new_tmp_a64(s);
22
30
+ /*
23
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+ * In order to get the correct value in the FAR_ELx register,
24
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+ * we must present the memory subsystem with the "dirty" address
25
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+ * including the TBI. In system mode we can make this work via
26
+
34
+ * the TLB, dropping the TBI during translation. But for user-only
27
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+ * mode we don't have that option, and must remove the top byte now.
28
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+ */
29
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
+#ifdef CONFIG_USER_ONLY
30
+
38
gen_top_byte_ignore(s, clean, addr, s->tbid);
31
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
39
+#else
32
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
40
+ tcg_gen_mov_i64(clean, addr);
33
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
41
+#endif
34
+
42
return clean;
35
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
38
+
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve.decode
45
+++ b/target/arm/mve.decode
46
@@ -XXX,XX +XXX,XX @@ VQDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
47
VQRDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
48
VQRDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
49
50
+VQDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
51
+VQDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
52
+VQRDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
53
+VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
54
+
55
# Vector miscellaneous
56
57
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/mve_helper.c
61
+++ b/target/arm/mve_helper.c
62
@@ -XXX,XX +XXX,XX @@ static int32_t do_vqdmladh_w(int32_t a, int32_t b, int32_t c, int32_t d,
63
return r >> 32;
43
}
64
}
44
65
66
+static int8_t do_vqdmlsdh_b(int8_t a, int8_t b, int8_t c, int8_t d,
67
+ int round, bool *sat)
68
+{
69
+ int64_t r = ((int64_t)a * b - (int64_t)c * d) * 2 + (round << 7);
70
+ return do_sat_bhw(r, INT16_MIN, INT16_MAX, sat) >> 8;
71
+}
72
+
73
+static int16_t do_vqdmlsdh_h(int16_t a, int16_t b, int16_t c, int16_t d,
74
+ int round, bool *sat)
75
+{
76
+ int64_t r = ((int64_t)a * b - (int64_t)c * d) * 2 + (round << 15);
77
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat) >> 16;
78
+}
79
+
80
+static int32_t do_vqdmlsdh_w(int32_t a, int32_t b, int32_t c, int32_t d,
81
+ int round, bool *sat)
82
+{
83
+ int64_t m1 = (int64_t)a * b;
84
+ int64_t m2 = (int64_t)c * d;
85
+ int64_t r;
86
+ /* The same ordering issue as in do_vqdmladh_w applies here too */
87
+ if (ssub64_overflow(m1, m2, &r) ||
88
+ sadd64_overflow(r, (round << 30), &r) ||
89
+ sadd64_overflow(r, r, &r)) {
90
+ *sat = true;
91
+ return r < 0 ? INT32_MAX : INT32_MIN;
92
+ }
93
+ return r >> 32;
94
+}
95
+
96
DO_VQDMLADH_OP(vqdmladhb, 1, int8_t, 0, 0, do_vqdmladh_b)
97
DO_VQDMLADH_OP(vqdmladhh, 2, int16_t, 0, 0, do_vqdmladh_h)
98
DO_VQDMLADH_OP(vqdmladhw, 4, int32_t, 0, 0, do_vqdmladh_w)
99
@@ -XXX,XX +XXX,XX @@ DO_VQDMLADH_OP(vqrdmladhxb, 1, int8_t, 1, 1, do_vqdmladh_b)
100
DO_VQDMLADH_OP(vqrdmladhxh, 2, int16_t, 1, 1, do_vqdmladh_h)
101
DO_VQDMLADH_OP(vqrdmladhxw, 4, int32_t, 1, 1, do_vqdmladh_w)
102
103
+DO_VQDMLADH_OP(vqdmlsdhb, 1, int8_t, 0, 0, do_vqdmlsdh_b)
104
+DO_VQDMLADH_OP(vqdmlsdhh, 2, int16_t, 0, 0, do_vqdmlsdh_h)
105
+DO_VQDMLADH_OP(vqdmlsdhw, 4, int32_t, 0, 0, do_vqdmlsdh_w)
106
+DO_VQDMLADH_OP(vqdmlsdhxb, 1, int8_t, 1, 0, do_vqdmlsdh_b)
107
+DO_VQDMLADH_OP(vqdmlsdhxh, 2, int16_t, 1, 0, do_vqdmlsdh_h)
108
+DO_VQDMLADH_OP(vqdmlsdhxw, 4, int32_t, 1, 0, do_vqdmlsdh_w)
109
+
110
+DO_VQDMLADH_OP(vqrdmlsdhb, 1, int8_t, 0, 1, do_vqdmlsdh_b)
111
+DO_VQDMLADH_OP(vqrdmlsdhh, 2, int16_t, 0, 1, do_vqdmlsdh_h)
112
+DO_VQDMLADH_OP(vqrdmlsdhw, 4, int32_t, 0, 1, do_vqdmlsdh_w)
113
+DO_VQDMLADH_OP(vqrdmlsdhxb, 1, int8_t, 1, 1, do_vqdmlsdh_b)
114
+DO_VQDMLADH_OP(vqrdmlsdhxh, 2, int16_t, 1, 1, do_vqdmlsdh_h)
115
+DO_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
116
+
117
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
118
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
119
uint32_t rm) \
120
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/arm/translate-mve.c
123
+++ b/target/arm/translate-mve.c
124
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLADH, vqdmladh)
125
DO_2OP(VQDMLADHX, vqdmladhx)
126
DO_2OP(VQRDMLADH, vqrdmladh)
127
DO_2OP(VQRDMLADHX, vqrdmladhx)
128
+DO_2OP(VQDMLSDH, vqdmlsdh)
129
+DO_2OP(VQDMLSDHX, vqdmlsdhx)
130
+DO_2OP(VQRDMLSDH, vqrdmlsdh)
131
+DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
132
133
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
134
MVEGenTwoOpScalarFn fn)
45
--
135
--
46
2.20.1
136
2.20.1
47
137
48
138
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement the vector form of the MVE VQDMULL insn.
2
2
3
The Allwinner H3 System on Chip contains multiple USB 2.0 bus
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
connections which provide software access using the Enhanced
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Host Controller Interface (EHCI) and Open Host Controller
5
Message-id: 20210617121628.20116-39-peter.maydell@linaro.org
6
Interface (OHCI) interfaces. This commit adds support for
6
---
7
both interfaces in the Allwinner H3 System on Chip.
7
target/arm/helper-mve.h | 5 +++++
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 30 ++++++++++++++++++++++++++++++
10
target/arm/translate-mve.c | 30 ++++++++++++++++++++++++++++++
11
4 files changed, 70 insertions(+)
8
12
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
10
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Message-id: 20200311221854.30370-5-nieklinnenbank@gmail.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/usb/hcd-ehci.h | 1 +
18
include/hw/arm/allwinner-h3.h | 8 +++++++
19
hw/arm/allwinner-h3.c | 44 +++++++++++++++++++++++++++++++++++
20
hw/usb/hcd-ehci-sysbus.c | 17 ++++++++++++++
21
hw/arm/Kconfig | 2 ++
22
5 files changed, 72 insertions(+)
23
24
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/usb/hcd-ehci.h
15
--- a/target/arm/helper-mve.h
27
+++ b/hw/usb/hcd-ehci.h
16
+++ b/target/arm/helper-mve.h
28
@@ -XXX,XX +XXX,XX @@ typedef struct EHCIPCIState {
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
#define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
18
DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
#define TYPE_PLATFORM_EHCI "platform-ehci-usb"
19
DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
20
32
+#define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
21
+DEF_HELPER_FLAGS_4(mve_vqdmullbh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
22
+DEF_HELPER_FLAGS_4(mve_vqdmullbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
23
+DEF_HELPER_FLAGS_4(mve_vqdmullth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
24
+DEF_HELPER_FLAGS_4(mve_vqdmulltw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
25
+
26
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
31
--- a/target/arm/mve.decode
39
+++ b/include/hw/arm/allwinner-h3.h
32
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@ enum {
33
@@ -XXX,XX +XXX,XX @@
41
AW_H3_SRAM_A1,
34
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
42
AW_H3_SRAM_A2,
35
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
43
AW_H3_SRAM_C,
36
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
44
+ AW_H3_EHCI0,
37
+@2op_sz28 .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn \
45
+ AW_H3_OHCI0,
38
+ size=%size_28
46
+ AW_H3_EHCI1,
39
47
+ AW_H3_OHCI1,
40
# The _rev suffix indicates that Vn and Vm are reversed. This is
48
+ AW_H3_EHCI2,
41
# the case for shifts. In the Arm ARM these insns are documented
49
+ AW_H3_OHCI2,
42
@@ -XXX,XX +XXX,XX @@ VQDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
50
+ AW_H3_EHCI3,
43
VQRDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
51
+ AW_H3_OHCI3,
44
VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
52
AW_H3_CCU,
45
53
AW_H3_PIT,
46
+VQDMULLB 111 . 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 1 @2op_sz28
54
AW_H3_UART0,
47
+VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
55
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
48
+
49
# Vector miscellaneous
50
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
56
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/allwinner-h3.c
54
--- a/target/arm/mve_helper.c
58
+++ b/hw/arm/allwinner-h3.c
55
+++ b/target/arm/mve_helper.c
59
@@ -XXX,XX +XXX,XX @@
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR_L(vqdmullt_scalarh, 1, 2, int16_t, 4, int32_t, \
60
#include "hw/sysbus.h"
57
DO_2OP_SAT_SCALAR_L(vqdmullt_scalarw, 1, 4, int32_t, 8, int64_t, \
61
#include "hw/char/serial.h"
58
do_qdmullw, SATMASK32)
62
#include "hw/misc/unimp.h"
59
63
+#include "hw/usb/hcd-ehci.h"
60
+/*
64
#include "sysemu/sysemu.h"
61
+ * Long saturating ops
65
#include "hw/arm/allwinner-h3.h"
62
+ */
66
63
+#define DO_2OP_SAT_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN, SATMASK) \
67
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
64
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
68
[AW_H3_SRAM_A1] = 0x00000000,
65
+ void *vm) \
69
[AW_H3_SRAM_A2] = 0x00044000,
66
+ { \
70
[AW_H3_SRAM_C] = 0x00010000,
67
+ LTYPE *d = vd; \
71
+ [AW_H3_EHCI0] = 0x01c1a000,
68
+ TYPE *n = vn, *m = vm; \
72
+ [AW_H3_OHCI0] = 0x01c1a400,
69
+ uint16_t mask = mve_element_mask(env); \
73
+ [AW_H3_EHCI1] = 0x01c1b000,
70
+ unsigned le; \
74
+ [AW_H3_OHCI1] = 0x01c1b400,
71
+ bool qc = false; \
75
+ [AW_H3_EHCI2] = 0x01c1c000,
72
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
76
+ [AW_H3_OHCI2] = 0x01c1c400,
73
+ bool sat = false; \
77
+ [AW_H3_EHCI3] = 0x01c1d000,
74
+ LTYPE op1 = n[H##ESIZE(le * 2 + TOP)]; \
78
+ [AW_H3_OHCI3] = 0x01c1d400,
75
+ LTYPE op2 = m[H##ESIZE(le * 2 + TOP)]; \
79
[AW_H3_CCU] = 0x01c20000,
76
+ mergemask(&d[H##LESIZE(le)], FN(op1, op2, &sat), mask); \
80
[AW_H3_PIT] = 0x01c20c00,
77
+ qc |= sat && (mask & SATMASK); \
81
[AW_H3_UART0] = 0x01c28000,
78
+ } \
82
@@ -XXX,XX +XXX,XX @@ enum {
79
+ if (qc) { \
83
AW_H3_GIC_SPI_UART3 = 3,
80
+ env->vfp.qc[0] = qc; \
84
AW_H3_GIC_SPI_TIMER0 = 18,
81
+ } \
85
AW_H3_GIC_SPI_TIMER1 = 19,
82
+ mve_advance_vpt(env); \
86
+ AW_H3_GIC_SPI_EHCI0 = 72,
83
+ }
87
+ AW_H3_GIC_SPI_OHCI0 = 73,
88
+ AW_H3_GIC_SPI_EHCI1 = 74,
89
+ AW_H3_GIC_SPI_OHCI1 = 75,
90
+ AW_H3_GIC_SPI_EHCI2 = 76,
91
+ AW_H3_GIC_SPI_OHCI2 = 77,
92
+ AW_H3_GIC_SPI_EHCI3 = 78,
93
+ AW_H3_GIC_SPI_OHCI3 = 79,
94
};
95
96
/* Allwinner H3 general constants */
97
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
98
qdev_init_nofail(DEVICE(&s->ccu));
99
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
100
101
+ /* Universal Serial Bus */
102
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
103
+ qdev_get_gpio_in(DEVICE(&s->gic),
104
+ AW_H3_GIC_SPI_EHCI0));
105
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI1],
106
+ qdev_get_gpio_in(DEVICE(&s->gic),
107
+ AW_H3_GIC_SPI_EHCI1));
108
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI2],
109
+ qdev_get_gpio_in(DEVICE(&s->gic),
110
+ AW_H3_GIC_SPI_EHCI2));
111
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI3],
112
+ qdev_get_gpio_in(DEVICE(&s->gic),
113
+ AW_H3_GIC_SPI_EHCI3));
114
+
84
+
115
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI0],
85
+DO_2OP_SAT_L(vqdmullbh, 0, 2, int16_t, 4, int32_t, do_qdmullh, SATMASK16B)
116
+ qdev_get_gpio_in(DEVICE(&s->gic),
86
+DO_2OP_SAT_L(vqdmullbw, 0, 4, int32_t, 8, int64_t, do_qdmullw, SATMASK32)
117
+ AW_H3_GIC_SPI_OHCI0));
87
+DO_2OP_SAT_L(vqdmullth, 1, 2, int16_t, 4, int32_t, do_qdmullh, SATMASK16T)
118
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI1],
88
+DO_2OP_SAT_L(vqdmulltw, 1, 4, int32_t, 8, int64_t, do_qdmullw, SATMASK32)
119
+ qdev_get_gpio_in(DEVICE(&s->gic),
120
+ AW_H3_GIC_SPI_OHCI1));
121
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI2],
122
+ qdev_get_gpio_in(DEVICE(&s->gic),
123
+ AW_H3_GIC_SPI_OHCI2));
124
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI3],
125
+ qdev_get_gpio_in(DEVICE(&s->gic),
126
+ AW_H3_GIC_SPI_OHCI3));
127
+
89
+
128
/* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
90
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
129
serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
91
{
130
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
92
m &= 0xff;
131
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
93
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
132
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/usb/hcd-ehci-sysbus.c
95
--- a/target/arm/translate-mve.c
134
+++ b/hw/usb/hcd-ehci-sysbus.c
96
+++ b/target/arm/translate-mve.c
135
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ehci_exynos4210_type_info = {
97
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLSDHX, vqdmlsdhx)
136
.class_init = ehci_exynos4210_class_init,
98
DO_2OP(VQRDMLSDH, vqrdmlsdh)
137
};
99
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
138
100
139
+static void ehci_aw_h3_class_init(ObjectClass *oc, void *data)
101
+static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
140
+{
102
+{
141
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
103
+ static MVEGenTwoOpFn * const fns[] = {
142
+ DeviceClass *dc = DEVICE_CLASS(oc);
104
+ NULL,
143
+
105
+ gen_helper_mve_vqdmullbh,
144
+ sec->capsbase = 0x0;
106
+ gen_helper_mve_vqdmullbw,
145
+ sec->opregbase = 0x10;
107
+ NULL,
146
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
108
+ };
109
+ if (a->size == MO_32 && (a->qd == a->qm || a->qd == a->qn)) {
110
+ /* UNPREDICTABLE; we choose to undef */
111
+ return false;
112
+ }
113
+ return do_2op(s, a, fns[a->size]);
147
+}
114
+}
148
+
115
+
149
+static const TypeInfo ehci_aw_h3_type_info = {
116
+static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
150
+ .name = TYPE_AW_H3_EHCI,
117
+{
151
+ .parent = TYPE_SYS_BUS_EHCI,
118
+ static MVEGenTwoOpFn * const fns[] = {
152
+ .class_init = ehci_aw_h3_class_init,
119
+ NULL,
153
+};
120
+ gen_helper_mve_vqdmullth,
121
+ gen_helper_mve_vqdmulltw,
122
+ NULL,
123
+ };
124
+ if (a->size == MO_32 && (a->qd == a->qm || a->qd == a->qn)) {
125
+ /* UNPREDICTABLE; we choose to undef */
126
+ return false;
127
+ }
128
+ return do_2op(s, a, fns[a->size]);
129
+}
154
+
130
+
155
static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
131
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
132
MVEGenTwoOpScalarFn fn)
156
{
133
{
157
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
158
@@ -XXX,XX +XXX,XX @@ static void ehci_sysbus_register_types(void)
159
type_register_static(&ehci_type_info);
160
type_register_static(&ehci_platform_type_info);
161
type_register_static(&ehci_exynos4210_type_info);
162
+ type_register_static(&ehci_aw_h3_type_info);
163
type_register_static(&ehci_tegra2_type_info);
164
type_register_static(&ehci_ppc4xx_type_info);
165
type_register_static(&ehci_fusbh200_type_info);
166
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/arm/Kconfig
169
+++ b/hw/arm/Kconfig
170
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
171
select ARM_TIMER
172
select ARM_GIC
173
select UNIMP
174
+ select USB_OHCI
175
+ select USB_EHCI_SYSBUS
176
177
config RASPI
178
bool
179
--
134
--
180
2.20.1
135
2.20.1
181
136
182
137
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the MVE VRHADD insn, which performs a rounded halving
2
addition.
2
3
3
We fail to validate the upper bits of a virtual address on a
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
translation disabled regime, as per AArch64.TranslateAddressS1Off.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-40-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 8 ++++++++
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 6 ++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 19 insertions(+)
5
13
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
7
Message-id: 20200308012946.16303-2-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 35 ++++++++++++++++++++++++++++++++++-
12
1 file changed, 34 insertions(+), 1 deletion(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
16
--- a/target/arm/helper-mve.h
17
+++ b/target/arm/helper.c
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqdmullbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
/* Definitely a real MMU, not an MPU */
19
DEF_HELPER_FLAGS_4(mve_vqdmullth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
20
DEF_HELPER_FLAGS_4(mve_vqdmulltw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
if (regime_translation_disabled(env, mmu_idx)) {
21
22
- /* MMU disabled. */
22
+DEF_HELPER_FLAGS_4(mve_vrhaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+ /*
23
+DEF_HELPER_FLAGS_4(mve_vrhaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+ * MMU disabled. S1 addresses within aa64 translation regimes are
24
+DEF_HELPER_FLAGS_4(mve_vrhaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+ * still checked for bounds -- see AArch64.TranslateAddressS1Off.
26
+ */
27
+ if (mmu_idx != ARMMMUIdx_Stage2) {
28
+ int r_el = regime_el(env, mmu_idx);
29
+ if (arm_el_is_aa64(env, r_el)) {
30
+ int pamax = arm_pamax(env_archcpu(env));
31
+ uint64_t tcr = env->cp15.tcr_el[r_el].raw_tcr;
32
+ int addrtop, tbi;
33
+
25
+
34
+ tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
26
+DEF_HELPER_FLAGS_4(mve_vrhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+ if (access_type == MMU_INST_FETCH) {
27
+DEF_HELPER_FLAGS_4(mve_vrhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+ tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
28
+DEF_HELPER_FLAGS_4(mve_vrhadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
+ }
38
+ tbi = (tbi >> extract64(address, 55, 1)) & 1;
39
+ addrtop = (tbi ? 55 : 63);
40
+
29
+
41
+ if (extract64(address, pamax, addrtop - pamax + 1) != 0) {
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
+ fi->type = ARMFault_AddressSize;
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
43
+ fi->level = 0;
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
44
+ fi->stage2 = false;
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
45
+ return 1;
34
index XXXXXXX..XXXXXXX 100644
46
+ }
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
38
VQDMULLB 111 . 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 1 @2op_sz28
39
VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
40
41
+VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
42
+VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
47
+
43
+
48
+ /*
44
# Vector miscellaneous
49
+ * When TBI is disabled, we've just validated that all of the
45
50
+ * bits above PAMax are zero, so logically we only need to
46
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
51
+ * clear the top byte for TBI. But it's clearer to follow
47
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
52
+ * the pseudocode set of addrdesc.paddress.
48
index XXXXXXX..XXXXXXX 100644
53
+ */
49
--- a/target/arm/mve_helper.c
54
+ address = extract64(address, 0, 52);
50
+++ b/target/arm/mve_helper.c
55
+ }
51
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vshlu, DO_VSHLU)
56
+ }
52
DO_2OP_S(vrshls, DO_VRSHLS)
57
*phys_ptr = address;
53
DO_2OP_U(vrshlu, DO_VRSHLU)
58
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
54
59
*page_size = TARGET_PAGE_SIZE;
55
+#define DO_RHADD_S(N, M) (((int64_t)(N) + (M) + 1) >> 1)
56
+#define DO_RHADD_U(N, M) (((uint64_t)(N) + (M) + 1) >> 1)
57
+
58
+DO_2OP_S(vrhadds, DO_RHADD_S)
59
+DO_2OP_U(vrhaddu, DO_RHADD_U)
60
+
61
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
62
{
63
if (val > max) {
64
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate-mve.c
67
+++ b/target/arm/translate-mve.c
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLSDH, vqdmlsdh)
69
DO_2OP(VQDMLSDHX, vqdmlsdhx)
70
DO_2OP(VQRDMLSDH, vqrdmlsdh)
71
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
72
+DO_2OP(VRHADD_S, vrhadds)
73
+DO_2OP(VRHADD_U, vrhaddu)
74
75
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
76
{
60
--
77
--
61
2.20.1
78
2.20.1
62
79
63
80
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
Implement the MVE VADC and VSBC insns. These perform an
2
add-with-carry or subtract-with-carry of the 32-bit elements in each
3
lane of the input vectors, where the carry-out of each add is the
4
carry-in of the next. The initial carry input is either 1 or is from
5
FPSCR.C; the carry out at the end is written back to FPSCR.C.
2
6
3
In the Allwinner H3 SoC the SDRAM controller is responsible
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
for interfacing with the external Synchronous Dynamic Random
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Access Memory (SDRAM). Types of memory that the SDRAM controller
9
Message-id: 20210617121628.20116-41-peter.maydell@linaro.org
6
supports are DDR2/DDR3 and capacities of up to 2GiB. This commit
10
---
7
adds emulation support of the Allwinner H3 SDRAM controller.
11
target/arm/helper-mve.h | 5 ++++
12
target/arm/mve.decode | 5 ++++
13
target/arm/mve_helper.c | 52 ++++++++++++++++++++++++++++++++++++++
14
target/arm/translate-mve.c | 37 +++++++++++++++++++++++++++
15
4 files changed, 99 insertions(+)
8
16
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20200311221854.30370-12-nieklinnenbank@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/misc/Makefile.objs | 1 +
15
include/hw/arm/allwinner-h3.h | 5 +
16
include/hw/misc/allwinner-h3-dramc.h | 106 ++++++++
17
hw/arm/allwinner-h3.c | 19 +-
18
hw/arm/orangepi.c | 6 +
19
hw/misc/allwinner-h3-dramc.c | 358 +++++++++++++++++++++++++++
20
hw/misc/trace-events | 10 +
21
7 files changed, 502 insertions(+), 3 deletions(-)
22
create mode 100644 include/hw/misc/allwinner-h3-dramc.h
23
create mode 100644 hw/misc/allwinner-h3-dramc.c
24
25
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/misc/Makefile.objs
19
--- a/target/arm/helper-mve.h
28
+++ b/hw/misc/Makefile.objs
20
+++ b/target/arm/helper-mve.h
29
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
22
DEF_HELPER_FLAGS_4(mve_vrhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
23
DEF_HELPER_FLAGS_4(mve_vrhadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
24
33
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-dramc.o
25
+DEF_HELPER_FLAGS_4(mve_vadc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
26
+DEF_HELPER_FLAGS_4(mve_vadci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sid.o
27
+DEF_HELPER_FLAGS_4(mve_vsbc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
28
+DEF_HELPER_FLAGS_4(mve_vsbci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
29
+
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
38
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
39
--- a/include/hw/arm/allwinner-h3.h
35
--- a/target/arm/mve.decode
40
+++ b/include/hw/arm/allwinner-h3.h
36
+++ b/target/arm/mve.decode
41
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
42
#include "hw/intc/arm_gic.h"
38
VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
43
#include "hw/misc/allwinner-h3-ccu.h"
39
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
44
#include "hw/misc/allwinner-cpucfg.h"
40
45
+#include "hw/misc/allwinner-h3-dramc.h"
41
+VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
46
#include "hw/misc/allwinner-h3-sysctrl.h"
42
+VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
47
#include "hw/misc/allwinner-sid.h"
43
+VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
48
#include "hw/sd/allwinner-sdhost.h"
44
+VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
49
@@ -XXX,XX +XXX,XX @@ enum {
50
AW_H3_UART2,
51
AW_H3_UART3,
52
AW_H3_EMAC,
53
+ AW_H3_DRAMCOM,
54
+ AW_H3_DRAMCTL,
55
+ AW_H3_DRAMPHY,
56
AW_H3_GIC_DIST,
57
AW_H3_GIC_CPU,
58
AW_H3_GIC_HYP,
59
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
60
AwA10PITState timer;
61
AwH3ClockCtlState ccu;
62
AwCpuCfgState cpucfg;
63
+ AwH3DramCtlState dramc;
64
AwH3SysCtrlState sysctrl;
65
AwSidState sid;
66
AwSdHostState mmc0;
67
diff --git a/include/hw/misc/allwinner-h3-dramc.h b/include/hw/misc/allwinner-h3-dramc.h
68
new file mode 100644
69
index XXXXXXX..XXXXXXX
70
--- /dev/null
71
+++ b/include/hw/misc/allwinner-h3-dramc.h
72
@@ -XXX,XX +XXX,XX @@
73
+/*
74
+ * Allwinner H3 SDRAM Controller emulation
75
+ *
76
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
77
+ *
78
+ * This program is free software: you can redistribute it and/or modify
79
+ * it under the terms of the GNU General Public License as published by
80
+ * the Free Software Foundation, either version 2 of the License, or
81
+ * (at your option) any later version.
82
+ *
83
+ * This program is distributed in the hope that it will be useful,
84
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
85
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86
+ * GNU General Public License for more details.
87
+ *
88
+ * You should have received a copy of the GNU General Public License
89
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
90
+ */
91
+
45
+
92
+#ifndef HW_MISC_ALLWINNER_H3_DRAMC_H
46
# Vector miscellaneous
93
+#define HW_MISC_ALLWINNER_H3_DRAMC_H
47
48
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
49
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/mve_helper.c
52
+++ b/target/arm/mve_helper.c
53
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vrshlu, DO_VRSHLU)
54
DO_2OP_S(vrhadds, DO_RHADD_S)
55
DO_2OP_U(vrhaddu, DO_RHADD_U)
56
57
+static void do_vadc(CPUARMState *env, uint32_t *d, uint32_t *n, uint32_t *m,
58
+ uint32_t inv, uint32_t carry_in, bool update_flags)
59
+{
60
+ uint16_t mask = mve_element_mask(env);
61
+ unsigned e;
94
+
62
+
95
+#include "qom/object.h"
63
+ /* If any additions trigger, we will update flags. */
96
+#include "hw/sysbus.h"
64
+ if (mask & 0x1111) {
97
+#include "exec/hwaddr.h"
65
+ update_flags = true;
98
+
99
+/**
100
+ * Constants
101
+ * @{
102
+ */
103
+
104
+/** Highest register address used by DRAMCOM module */
105
+#define AW_H3_DRAMCOM_REGS_MAXADDR (0x804)
106
+
107
+/** Total number of known DRAMCOM registers */
108
+#define AW_H3_DRAMCOM_REGS_NUM (AW_H3_DRAMCOM_REGS_MAXADDR / \
109
+ sizeof(uint32_t))
110
+
111
+/** Highest register address used by DRAMCTL module */
112
+#define AW_H3_DRAMCTL_REGS_MAXADDR (0x88c)
113
+
114
+/** Total number of known DRAMCTL registers */
115
+#define AW_H3_DRAMCTL_REGS_NUM (AW_H3_DRAMCTL_REGS_MAXADDR / \
116
+ sizeof(uint32_t))
117
+
118
+/** Highest register address used by DRAMPHY module */
119
+#define AW_H3_DRAMPHY_REGS_MAXADDR (0x4)
120
+
121
+/** Total number of known DRAMPHY registers */
122
+#define AW_H3_DRAMPHY_REGS_NUM (AW_H3_DRAMPHY_REGS_MAXADDR / \
123
+ sizeof(uint32_t))
124
+
125
+/** @} */
126
+
127
+/**
128
+ * Object model
129
+ * @{
130
+ */
131
+
132
+#define TYPE_AW_H3_DRAMC "allwinner-h3-dramc"
133
+#define AW_H3_DRAMC(obj) \
134
+ OBJECT_CHECK(AwH3DramCtlState, (obj), TYPE_AW_H3_DRAMC)
135
+
136
+/** @} */
137
+
138
+/**
139
+ * Allwinner H3 SDRAM Controller object instance state.
140
+ */
141
+typedef struct AwH3DramCtlState {
142
+ /*< private >*/
143
+ SysBusDevice parent_obj;
144
+ /*< public >*/
145
+
146
+ /** Physical base address for start of RAM */
147
+ hwaddr ram_addr;
148
+
149
+ /** Total RAM size in megabytes */
150
+ uint32_t ram_size;
151
+
152
+ /**
153
+ * @name Memory Regions
154
+ * @{
155
+ */
156
+
157
+ MemoryRegion row_mirror; /**< Simulates rows for RAM size detection */
158
+ MemoryRegion row_mirror_alias; /**< Alias of the row which is mirrored */
159
+ MemoryRegion dramcom_iomem; /**< DRAMCOM module I/O registers */
160
+ MemoryRegion dramctl_iomem; /**< DRAMCTL module I/O registers */
161
+ MemoryRegion dramphy_iomem; /**< DRAMPHY module I/O registers */
162
+
163
+ /** @} */
164
+
165
+ /**
166
+ * @name Hardware Registers
167
+ * @{
168
+ */
169
+
170
+ uint32_t dramcom[AW_H3_DRAMCOM_REGS_NUM]; /**< Array of DRAMCOM registers */
171
+ uint32_t dramctl[AW_H3_DRAMCTL_REGS_NUM]; /**< Array of DRAMCTL registers */
172
+ uint32_t dramphy[AW_H3_DRAMPHY_REGS_NUM] ;/**< Array of DRAMPHY registers */
173
+
174
+ /** @} */
175
+
176
+} AwH3DramCtlState;
177
+
178
+#endif /* HW_MISC_ALLWINNER_H3_DRAMC_H */
179
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/arm/allwinner-h3.c
182
+++ b/hw/arm/allwinner-h3.c
183
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
184
[AW_H3_UART2] = 0x01c28800,
185
[AW_H3_UART3] = 0x01c28c00,
186
[AW_H3_EMAC] = 0x01c30000,
187
+ [AW_H3_DRAMCOM] = 0x01c62000,
188
+ [AW_H3_DRAMCTL] = 0x01c63000,
189
+ [AW_H3_DRAMPHY] = 0x01c65000,
190
[AW_H3_GIC_DIST] = 0x01c81000,
191
[AW_H3_GIC_CPU] = 0x01c82000,
192
[AW_H3_GIC_HYP] = 0x01c84000,
193
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
194
{ "scr", 0x01c2c400, 1 * KiB },
195
{ "gpu", 0x01c40000, 64 * KiB },
196
{ "hstmr", 0x01c60000, 4 * KiB },
197
- { "dramcom", 0x01c62000, 4 * KiB },
198
- { "dramctl0", 0x01c63000, 4 * KiB },
199
- { "dramphy0", 0x01c65000, 4 * KiB },
200
{ "spi0", 0x01c68000, 4 * KiB },
201
{ "spi1", 0x01c69000, 4 * KiB },
202
{ "csi", 0x01cb0000, 320 * KiB },
203
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
204
205
sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac),
206
TYPE_AW_SUN8I_EMAC);
207
+
208
+ sysbus_init_child_obj(obj, "dramc", &s->dramc, sizeof(s->dramc),
209
+ TYPE_AW_H3_DRAMC);
210
+ object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc),
211
+ "ram-addr", &error_abort);
212
+ object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
213
+ "ram-size", &error_abort);
214
}
215
216
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
217
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
218
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART3),
219
115200, serial_hd(3), DEVICE_NATIVE_ENDIAN);
220
221
+ /* DRAMC */
222
+ qdev_init_nofail(DEVICE(&s->dramc));
223
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0, s->memmap[AW_H3_DRAMCOM]);
224
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1, s->memmap[AW_H3_DRAMCTL]);
225
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2, s->memmap[AW_H3_DRAMPHY]);
226
+
227
/* Unimplemented devices */
228
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
229
create_unimplemented_device(unimplemented[i].device_name,
230
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/hw/arm/orangepi.c
233
+++ b/hw/arm/orangepi.c
234
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
235
/* Setup EMAC properties */
236
object_property_set_int(OBJECT(&h3->emac), 1, "phy-addr", &error_abort);
237
238
+ /* DRAMC */
239
+ object_property_set_uint(OBJECT(h3), h3->memmap[AW_H3_SDRAM],
240
+ "ram-addr", &error_abort);
241
+ object_property_set_int(OBJECT(h3), machine->ram_size / MiB, "ram-size",
242
+ &error_abort);
243
+
244
/* Mark H3 object realized */
245
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
246
247
diff --git a/hw/misc/allwinner-h3-dramc.c b/hw/misc/allwinner-h3-dramc.c
248
new file mode 100644
249
index XXXXXXX..XXXXXXX
250
--- /dev/null
251
+++ b/hw/misc/allwinner-h3-dramc.c
252
@@ -XXX,XX +XXX,XX @@
253
+/*
254
+ * Allwinner H3 SDRAM Controller emulation
255
+ *
256
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
257
+ *
258
+ * This program is free software: you can redistribute it and/or modify
259
+ * it under the terms of the GNU General Public License as published by
260
+ * the Free Software Foundation, either version 2 of the License, or
261
+ * (at your option) any later version.
262
+ *
263
+ * This program is distributed in the hope that it will be useful,
264
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
265
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
266
+ * GNU General Public License for more details.
267
+ *
268
+ * You should have received a copy of the GNU General Public License
269
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
270
+ */
271
+
272
+#include "qemu/osdep.h"
273
+#include "qemu/units.h"
274
+#include "qemu/error-report.h"
275
+#include "hw/sysbus.h"
276
+#include "migration/vmstate.h"
277
+#include "qemu/log.h"
278
+#include "qemu/module.h"
279
+#include "exec/address-spaces.h"
280
+#include "hw/qdev-properties.h"
281
+#include "qapi/error.h"
282
+#include "hw/misc/allwinner-h3-dramc.h"
283
+#include "trace.h"
284
+
285
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
286
+
287
+/* DRAMCOM register offsets */
288
+enum {
289
+ REG_DRAMCOM_CR = 0x0000, /* Control Register */
290
+};
291
+
292
+/* DRAMCTL register offsets */
293
+enum {
294
+ REG_DRAMCTL_PIR = 0x0000, /* PHY Initialization Register */
295
+ REG_DRAMCTL_PGSR = 0x0010, /* PHY General Status Register */
296
+ REG_DRAMCTL_STATR = 0x0018, /* Status Register */
297
+};
298
+
299
+/* DRAMCTL register flags */
300
+enum {
301
+ REG_DRAMCTL_PGSR_INITDONE = (1 << 0),
302
+};
303
+
304
+enum {
305
+ REG_DRAMCTL_STATR_ACTIVE = (1 << 0),
306
+};
307
+
308
+static void allwinner_h3_dramc_map_rows(AwH3DramCtlState *s, uint8_t row_bits,
309
+ uint8_t bank_bits, uint16_t page_size)
310
+{
311
+ /*
312
+ * This function simulates row addressing behavior when bootloader
313
+ * software attempts to detect the amount of available SDRAM. In U-Boot
314
+ * the controller is configured with the widest row addressing available.
315
+ * Then a pattern is written to RAM at an offset on the row boundary size.
316
+ * If the value read back equals the value read back from the
317
+ * start of RAM, the bootloader knows the amount of row bits.
318
+ *
319
+ * This function inserts a mirrored memory region when the configured row
320
+ * bits are not matching the actual emulated memory, to simulate the
321
+ * same behavior on hardware as expected by the bootloader.
322
+ */
323
+ uint8_t row_bits_actual = 0;
324
+
325
+ /* Calculate the actual row bits using the ram_size property */
326
+ for (uint8_t i = 8; i < 12; i++) {
327
+ if (1 << i == s->ram_size) {
328
+ row_bits_actual = i + 3;
329
+ break;
330
+ }
331
+ }
66
+ }
332
+
67
+
333
+ if (s->ram_size == (1 << (row_bits - 3))) {
68
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) {
334
+ /* When row bits is the expected value, remove the mirror */
69
+ uint64_t r = carry_in;
335
+ memory_region_set_enabled(&s->row_mirror_alias, false);
70
+ r += n[H4(e)];
336
+ trace_allwinner_h3_dramc_rowmirror_disable();
71
+ r += m[H4(e)] ^ inv;
72
+ if (mask & 1) {
73
+ carry_in = r >> 32;
74
+ }
75
+ mergemask(&d[H4(e)], r, mask);
76
+ }
337
+
77
+
338
+ } else if (row_bits_actual) {
78
+ if (update_flags) {
339
+ /* Row bits not matching ram_size, install the rows mirror */
79
+ /* Store C, clear NZV. */
340
+ hwaddr row_mirror = s->ram_addr + ((1 << (row_bits_actual +
80
+ env->vfp.xregs[ARM_VFP_FPSCR] &= ~FPCR_NZCV_MASK;
341
+ bank_bits)) * page_size);
81
+ env->vfp.xregs[ARM_VFP_FPSCR] |= carry_in * FPCR_C;
342
+
343
+ memory_region_set_enabled(&s->row_mirror_alias, true);
344
+ memory_region_set_address(&s->row_mirror_alias, row_mirror);
345
+
346
+ trace_allwinner_h3_dramc_rowmirror_enable(row_mirror);
347
+ }
82
+ }
83
+ mve_advance_vpt(env);
348
+}
84
+}
349
+
85
+
350
+static uint64_t allwinner_h3_dramcom_read(void *opaque, hwaddr offset,
86
+void HELPER(mve_vadc)(CPUARMState *env, void *vd, void *vn, void *vm)
351
+ unsigned size)
352
+{
87
+{
353
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
88
+ bool carry_in = env->vfp.xregs[ARM_VFP_FPSCR] & FPCR_C;
354
+ const uint32_t idx = REG_INDEX(offset);
89
+ do_vadc(env, vd, vn, vm, 0, carry_in, false);
355
+
356
+ if (idx >= AW_H3_DRAMCOM_REGS_NUM) {
357
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
358
+ __func__, (uint32_t)offset);
359
+ return 0;
360
+ }
361
+
362
+ trace_allwinner_h3_dramcom_read(offset, s->dramcom[idx], size);
363
+
364
+ return s->dramcom[idx];
365
+}
90
+}
366
+
91
+
367
+static void allwinner_h3_dramcom_write(void *opaque, hwaddr offset,
92
+void HELPER(mve_vsbc)(CPUARMState *env, void *vd, void *vn, void *vm)
368
+ uint64_t val, unsigned size)
369
+{
93
+{
370
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
94
+ bool carry_in = env->vfp.xregs[ARM_VFP_FPSCR] & FPCR_C;
371
+ const uint32_t idx = REG_INDEX(offset);
95
+ do_vadc(env, vd, vn, vm, -1, carry_in, false);
372
+
373
+ trace_allwinner_h3_dramcom_write(offset, val, size);
374
+
375
+ if (idx >= AW_H3_DRAMCOM_REGS_NUM) {
376
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
377
+ __func__, (uint32_t)offset);
378
+ return;
379
+ }
380
+
381
+ switch (offset) {
382
+ case REG_DRAMCOM_CR: /* Control Register */
383
+ allwinner_h3_dramc_map_rows(s, ((val >> 4) & 0xf) + 1,
384
+ ((val >> 2) & 0x1) + 2,
385
+ 1 << (((val >> 8) & 0xf) + 3));
386
+ break;
387
+ default:
388
+ break;
389
+ };
390
+
391
+ s->dramcom[idx] = (uint32_t) val;
392
+}
96
+}
393
+
97
+
394
+static uint64_t allwinner_h3_dramctl_read(void *opaque, hwaddr offset,
98
+
395
+ unsigned size)
99
+void HELPER(mve_vadci)(CPUARMState *env, void *vd, void *vn, void *vm)
396
+{
100
+{
397
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
101
+ do_vadc(env, vd, vn, vm, 0, 0, true);
398
+ const uint32_t idx = REG_INDEX(offset);
399
+
400
+ if (idx >= AW_H3_DRAMCTL_REGS_NUM) {
401
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
402
+ __func__, (uint32_t)offset);
403
+ return 0;
404
+ }
405
+
406
+ trace_allwinner_h3_dramctl_read(offset, s->dramctl[idx], size);
407
+
408
+ return s->dramctl[idx];
409
+}
102
+}
410
+
103
+
411
+static void allwinner_h3_dramctl_write(void *opaque, hwaddr offset,
104
+void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
412
+ uint64_t val, unsigned size)
413
+{
105
+{
414
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
106
+ do_vadc(env, vd, vn, vm, -1, 1, true);
415
+ const uint32_t idx = REG_INDEX(offset);
416
+
417
+ trace_allwinner_h3_dramctl_write(offset, val, size);
418
+
419
+ if (idx >= AW_H3_DRAMCTL_REGS_NUM) {
420
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
421
+ __func__, (uint32_t)offset);
422
+ return;
423
+ }
424
+
425
+ switch (offset) {
426
+ case REG_DRAMCTL_PIR: /* PHY Initialization Register */
427
+ s->dramctl[REG_INDEX(REG_DRAMCTL_PGSR)] |= REG_DRAMCTL_PGSR_INITDONE;
428
+ s->dramctl[REG_INDEX(REG_DRAMCTL_STATR)] |= REG_DRAMCTL_STATR_ACTIVE;
429
+ break;
430
+ default:
431
+ break;
432
+ }
433
+
434
+ s->dramctl[idx] = (uint32_t) val;
435
+}
107
+}
436
+
108
+
437
+static uint64_t allwinner_h3_dramphy_read(void *opaque, hwaddr offset,
109
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
438
+ unsigned size)
110
{
111
if (val > max) {
112
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/translate-mve.c
115
+++ b/target/arm/translate-mve.c
116
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
117
return do_2op(s, a, fns[a->size]);
118
}
119
120
+/*
121
+ * VADC and VSBC: these perform an add-with-carry or subtract-with-carry
122
+ * of the 32-bit elements in each lane of the input vectors, where the
123
+ * carry-out of each add is the carry-in of the next. The initial carry
124
+ * input is either fixed (0 for VADCI, 1 for VSBCI) or is from FPSCR.C
125
+ * (for VADC and VSBC); the carry out at the end is written back to FPSCR.C.
126
+ * These insns are subject to beat-wise execution. Partial execution
127
+ * of an I=1 (initial carry input fixed) insn which does not
128
+ * execute the first beat must start with the current FPSCR.NZCV
129
+ * value, not the fixed constant input.
130
+ */
131
+static bool trans_VADC(DisasContext *s, arg_2op *a)
439
+{
132
+{
440
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
133
+ return do_2op(s, a, gen_helper_mve_vadc);
441
+ const uint32_t idx = REG_INDEX(offset);
442
+
443
+ if (idx >= AW_H3_DRAMPHY_REGS_NUM) {
444
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
445
+ __func__, (uint32_t)offset);
446
+ return 0;
447
+ }
448
+
449
+ trace_allwinner_h3_dramphy_read(offset, s->dramphy[idx], size);
450
+
451
+ return s->dramphy[idx];
452
+}
134
+}
453
+
135
+
454
+static void allwinner_h3_dramphy_write(void *opaque, hwaddr offset,
136
+static bool trans_VADCI(DisasContext *s, arg_2op *a)
455
+ uint64_t val, unsigned size)
456
+{
137
+{
457
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
138
+ if (mve_skip_first_beat(s)) {
458
+ const uint32_t idx = REG_INDEX(offset);
139
+ return trans_VADC(s, a);
459
+
460
+ trace_allwinner_h3_dramphy_write(offset, val, size);
461
+
462
+ if (idx >= AW_H3_DRAMPHY_REGS_NUM) {
463
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
464
+ __func__, (uint32_t)offset);
465
+ return;
466
+ }
140
+ }
467
+
141
+ return do_2op(s, a, gen_helper_mve_vadci);
468
+ s->dramphy[idx] = (uint32_t) val;
469
+}
142
+}
470
+
143
+
471
+static const MemoryRegionOps allwinner_h3_dramcom_ops = {
144
+static bool trans_VSBC(DisasContext *s, arg_2op *a)
472
+ .read = allwinner_h3_dramcom_read,
473
+ .write = allwinner_h3_dramcom_write,
474
+ .endianness = DEVICE_NATIVE_ENDIAN,
475
+ .valid = {
476
+ .min_access_size = 4,
477
+ .max_access_size = 4,
478
+ },
479
+ .impl.min_access_size = 4,
480
+};
481
+
482
+static const MemoryRegionOps allwinner_h3_dramctl_ops = {
483
+ .read = allwinner_h3_dramctl_read,
484
+ .write = allwinner_h3_dramctl_write,
485
+ .endianness = DEVICE_NATIVE_ENDIAN,
486
+ .valid = {
487
+ .min_access_size = 4,
488
+ .max_access_size = 4,
489
+ },
490
+ .impl.min_access_size = 4,
491
+};
492
+
493
+static const MemoryRegionOps allwinner_h3_dramphy_ops = {
494
+ .read = allwinner_h3_dramphy_read,
495
+ .write = allwinner_h3_dramphy_write,
496
+ .endianness = DEVICE_NATIVE_ENDIAN,
497
+ .valid = {
498
+ .min_access_size = 4,
499
+ .max_access_size = 4,
500
+ },
501
+ .impl.min_access_size = 4,
502
+};
503
+
504
+static void allwinner_h3_dramc_reset(DeviceState *dev)
505
+{
145
+{
506
+ AwH3DramCtlState *s = AW_H3_DRAMC(dev);
146
+ return do_2op(s, a, gen_helper_mve_vsbc);
507
+
508
+ /* Set default values for registers */
509
+ memset(&s->dramcom, 0, sizeof(s->dramcom));
510
+ memset(&s->dramctl, 0, sizeof(s->dramctl));
511
+ memset(&s->dramphy, 0, sizeof(s->dramphy));
512
+}
147
+}
513
+
148
+
514
+static void allwinner_h3_dramc_realize(DeviceState *dev, Error **errp)
149
+static bool trans_VSBCI(DisasContext *s, arg_2op *a)
515
+{
150
+{
516
+ AwH3DramCtlState *s = AW_H3_DRAMC(dev);
151
+ if (mve_skip_first_beat(s)) {
517
+
152
+ return trans_VSBC(s, a);
518
+ /* Only power of 2 RAM sizes from 256MiB up to 2048MiB are supported */
519
+ for (uint8_t i = 8; i < 13; i++) {
520
+ if (1 << i == s->ram_size) {
521
+ break;
522
+ } else if (i == 12) {
523
+ error_report("%s: ram-size %u MiB is not supported",
524
+ __func__, s->ram_size);
525
+ exit(1);
526
+ }
527
+ }
153
+ }
528
+
154
+ return do_2op(s, a, gen_helper_mve_vsbci);
529
+ /* Setup row mirror mappings */
530
+ memory_region_init_ram(&s->row_mirror, OBJECT(s),
531
+ "allwinner-h3-dramc.row-mirror",
532
+ 4 * KiB, &error_abort);
533
+ memory_region_add_subregion_overlap(get_system_memory(), s->ram_addr,
534
+ &s->row_mirror, 10);
535
+
536
+ memory_region_init_alias(&s->row_mirror_alias, OBJECT(s),
537
+ "allwinner-h3-dramc.row-mirror-alias",
538
+ &s->row_mirror, 0, 4 * KiB);
539
+ memory_region_add_subregion_overlap(get_system_memory(),
540
+ s->ram_addr + 1 * MiB,
541
+ &s->row_mirror_alias, 10);
542
+ memory_region_set_enabled(&s->row_mirror_alias, false);
543
+}
155
+}
544
+
156
+
545
+static void allwinner_h3_dramc_init(Object *obj)
157
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
546
+{
158
MVEGenTwoOpScalarFn fn)
547
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
159
{
548
+ AwH3DramCtlState *s = AW_H3_DRAMC(obj);
549
+
550
+ /* DRAMCOM registers */
551
+ memory_region_init_io(&s->dramcom_iomem, OBJECT(s),
552
+ &allwinner_h3_dramcom_ops, s,
553
+ TYPE_AW_H3_DRAMC, 4 * KiB);
554
+ sysbus_init_mmio(sbd, &s->dramcom_iomem);
555
+
556
+ /* DRAMCTL registers */
557
+ memory_region_init_io(&s->dramctl_iomem, OBJECT(s),
558
+ &allwinner_h3_dramctl_ops, s,
559
+ TYPE_AW_H3_DRAMC, 4 * KiB);
560
+ sysbus_init_mmio(sbd, &s->dramctl_iomem);
561
+
562
+ /* DRAMPHY registers */
563
+ memory_region_init_io(&s->dramphy_iomem, OBJECT(s),
564
+ &allwinner_h3_dramphy_ops, s,
565
+ TYPE_AW_H3_DRAMC, 4 * KiB);
566
+ sysbus_init_mmio(sbd, &s->dramphy_iomem);
567
+}
568
+
569
+static Property allwinner_h3_dramc_properties[] = {
570
+ DEFINE_PROP_UINT64("ram-addr", AwH3DramCtlState, ram_addr, 0x0),
571
+ DEFINE_PROP_UINT32("ram-size", AwH3DramCtlState, ram_size, 256 * MiB),
572
+ DEFINE_PROP_END_OF_LIST()
573
+};
574
+
575
+static const VMStateDescription allwinner_h3_dramc_vmstate = {
576
+ .name = "allwinner-h3-dramc",
577
+ .version_id = 1,
578
+ .minimum_version_id = 1,
579
+ .fields = (VMStateField[]) {
580
+ VMSTATE_UINT32_ARRAY(dramcom, AwH3DramCtlState, AW_H3_DRAMCOM_REGS_NUM),
581
+ VMSTATE_UINT32_ARRAY(dramctl, AwH3DramCtlState, AW_H3_DRAMCTL_REGS_NUM),
582
+ VMSTATE_UINT32_ARRAY(dramphy, AwH3DramCtlState, AW_H3_DRAMPHY_REGS_NUM),
583
+ VMSTATE_END_OF_LIST()
584
+ }
585
+};
586
+
587
+static void allwinner_h3_dramc_class_init(ObjectClass *klass, void *data)
588
+{
589
+ DeviceClass *dc = DEVICE_CLASS(klass);
590
+
591
+ dc->reset = allwinner_h3_dramc_reset;
592
+ dc->vmsd = &allwinner_h3_dramc_vmstate;
593
+ dc->realize = allwinner_h3_dramc_realize;
594
+ device_class_set_props(dc, allwinner_h3_dramc_properties);
595
+}
596
+
597
+static const TypeInfo allwinner_h3_dramc_info = {
598
+ .name = TYPE_AW_H3_DRAMC,
599
+ .parent = TYPE_SYS_BUS_DEVICE,
600
+ .instance_init = allwinner_h3_dramc_init,
601
+ .instance_size = sizeof(AwH3DramCtlState),
602
+ .class_init = allwinner_h3_dramc_class_init,
603
+};
604
+
605
+static void allwinner_h3_dramc_register(void)
606
+{
607
+ type_register_static(&allwinner_h3_dramc_info);
608
+}
609
+
610
+type_init(allwinner_h3_dramc_register)
611
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
612
index XXXXXXX..XXXXXXX 100644
613
--- a/hw/misc/trace-events
614
+++ b/hw/misc/trace-events
615
@@ -XXX,XX +XXX,XX @@ allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_ad
616
allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
617
allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
618
619
+# allwinner-h3-dramc.c
620
+allwinner_h3_dramc_rowmirror_disable(void) "Disable row mirror"
621
+allwinner_h3_dramc_rowmirror_enable(uint64_t addr) "Enable row mirror: addr 0x%" PRIx64
622
+allwinner_h3_dramcom_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
623
+allwinner_h3_dramcom_write(uint64_t offset, uint64_t data, unsigned size) "Write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
624
+allwinner_h3_dramctl_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
625
+allwinner_h3_dramctl_write(uint64_t offset, uint64_t data, unsigned size) "Write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
626
+allwinner_h3_dramphy_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
627
+allwinner_h3_dramphy_write(uint64_t offset, uint64_t data, unsigned size) "write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
628
+
629
# allwinner-sid.c
630
allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
631
allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
632
--
160
--
633
2.20.1
161
2.20.1
634
162
635
163
diff view generated by jsdifflib
1
Some of an M-profile CPU's cached hflags state depends on state that's
1
Implement the MVE VCADD insn, which performs a complex add with
2
in our NVIC object. We already do an hflags rebuild when the NVIC
2
rotate. Note that the size=0b11 encoding is VSBC.
3
registers are written, but we also need to do this on NVIC reset,
4
because there's no guarantee that this will happen before the
5
CPU reset.
6
3
7
This fixes an assertion due to mismatched hflags which happens if
4
The architecture grants some leeway for the "destination and Vm
8
the CPU is reset from inside a HardFault handler.
5
source overlap" case for the size MO_32 case, but we choose not to
6
make use of it, instead always calculating all 16 bytes worth of
7
results before setting the destination register.
9
8
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200303174950.3298-2-peter.maydell@linaro.org
11
Message-id: 20210617121628.20116-42-peter.maydell@linaro.org
13
---
12
---
14
hw/intc/armv7m_nvic.c | 6 ++++++
13
target/arm/helper-mve.h | 8 ++++++++
15
1 file changed, 6 insertions(+)
14
target/arm/mve.decode | 9 +++++++--
15
target/arm/mve_helper.c | 29 +++++++++++++++++++++++++++++
16
target/arm/translate-mve.c | 7 +++++++
17
4 files changed, 51 insertions(+), 2 deletions(-)
16
18
17
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/armv7m_nvic.c
21
--- a/target/arm/helper-mve.h
20
+++ b/hw/intc/armv7m_nvic.c
22
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vadci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
s->itns[i] = true;
24
DEF_HELPER_FLAGS_4(mve_vsbc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
}
25
DEF_HELPER_FLAGS_4(mve_vsbci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
}
26
27
+DEF_HELPER_FLAGS_4(mve_vcadd90b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+DEF_HELPER_FLAGS_4(mve_vcadd90w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+
30
+
26
+ /*
31
+DEF_HELPER_FLAGS_4(mve_vcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+ * We updated state that affects the CPU's MMUidx and thus its hflags;
32
+DEF_HELPER_FLAGS_4(mve_vcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+ * and we can't guarantee that we run before the CPU reset function.
33
+DEF_HELPER_FLAGS_4(mve_vcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+ */
34
+
30
+ arm_rebuild_hflags(&s->cpu->env);
35
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve.decode
41
+++ b/target/arm/mve.decode
42
@@ -XXX,XX +XXX,XX @@ VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
43
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
44
45
VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
46
-VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
47
VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
48
-VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
49
+
50
+{
51
+ VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
52
+ VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
53
+ VCADD90 1111 1110 0 . .. ... 0 ... 0 1111 . 0 . 0 ... 0 @2op
54
+ VCADD270 1111 1110 0 . .. ... 0 ... 1 1111 . 0 . 0 ... 0 @2op
55
+}
56
57
# Vector miscellaneous
58
59
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/mve_helper.c
62
+++ b/target/arm/mve_helper.c
63
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
64
do_vadc(env, vd, vn, vm, -1, 1, true);
31
}
65
}
32
66
33
static void nvic_systick_trigger(void *opaque, int n, int level)
67
+#define DO_VCADD(OP, ESIZE, TYPE, FN0, FN1) \
68
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
69
+ { \
70
+ TYPE *d = vd, *n = vn, *m = vm; \
71
+ uint16_t mask = mve_element_mask(env); \
72
+ unsigned e; \
73
+ TYPE r[16 / ESIZE]; \
74
+ /* Calculate all results first to avoid overwriting inputs */ \
75
+ for (e = 0; e < 16 / ESIZE; e++) { \
76
+ if (!(e & 1)) { \
77
+ r[e] = FN0(n[H##ESIZE(e)], m[H##ESIZE(e + 1)]); \
78
+ } else { \
79
+ r[e] = FN1(n[H##ESIZE(e)], m[H##ESIZE(e - 1)]); \
80
+ } \
81
+ } \
82
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
83
+ mergemask(&d[H##ESIZE(e)], r[e], mask); \
84
+ } \
85
+ mve_advance_vpt(env); \
86
+ }
87
+
88
+#define DO_VCADD_ALL(OP, FN0, FN1) \
89
+ DO_VCADD(OP##b, 1, int8_t, FN0, FN1) \
90
+ DO_VCADD(OP##h, 2, int16_t, FN0, FN1) \
91
+ DO_VCADD(OP##w, 4, int32_t, FN0, FN1)
92
+
93
+DO_VCADD_ALL(vcadd90, DO_SUB, DO_ADD)
94
+DO_VCADD_ALL(vcadd270, DO_ADD, DO_SUB)
95
+
96
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
97
{
98
if (val > max) {
99
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/translate-mve.c
102
+++ b/target/arm/translate-mve.c
103
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQRDMLSDH, vqrdmlsdh)
104
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
105
DO_2OP(VRHADD_S, vrhadds)
106
DO_2OP(VRHADD_U, vrhaddu)
107
+/*
108
+ * VCADD Qd == Qm at size MO_32 is UNPREDICTABLE; we choose not to diagnose
109
+ * so we can reuse the DO_2OP macro. (Our implementation calculates the
110
+ * "expected" results in this case.)
111
+ */
112
+DO_2OP(VCADD90, vcadd90)
113
+DO_2OP(VCADD270, vcadd270)
114
115
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
116
{
34
--
117
--
35
2.20.1
118
2.20.1
36
119
37
120
diff view generated by jsdifflib
1
For M-profile CPUs, the FAULTMASK value affects the CPU's MMU index
1
Implement the MVE VHCADD insn, which is similar to VCADD
2
(it changes the NegPri bit). We update the hflags after calls
2
but performs a halving step. This one overlaps with VADC.
3
to the v7m_msr helper in trans_MSR_v7m() but forgot to do so
4
in trans_CPS_v7m().
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200303174950.3298-3-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-43-peter.maydell@linaro.org
9
---
7
---
10
target/arm/translate.c | 5 ++++-
8
target/arm/helper-mve.h | 8 ++++++++
11
1 file changed, 4 insertions(+), 1 deletion(-)
9
target/arm/mve.decode | 8 ++++++--
10
target/arm/mve_helper.c | 2 ++
11
target/arm/translate-mve.c | 4 +++-
12
4 files changed, 19 insertions(+), 3 deletions(-)
12
13
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
16
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/translate.c
17
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS(DisasContext *s, arg_CPS *a)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
19
DEF_HELPER_FLAGS_4(mve_vcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
20
DEF_HELPER_FLAGS_4(mve_vcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
22
+DEF_HELPER_FLAGS_4(mve_vhcadd90b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vhcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vhcadd90w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+
26
+DEF_HELPER_FLAGS_4(mve_vhcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vhcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vhcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
38
VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
39
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
40
41
-VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
42
-VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
43
+{
44
+ VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
45
+ VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
46
+ VHCADD90 1110 1110 0 . .. ... 0 ... 0 1111 . 0 . 0 ... 0 @2op
47
+ VHCADD270 1110 1110 0 . .. ... 0 ... 1 1111 . 0 . 0 ... 0 @2op
48
+}
49
20
{
50
{
21
- TCGv_i32 tmp, addr;
51
VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
22
+ TCGv_i32 tmp, addr, el;
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
23
53
index XXXXXXX..XXXXXXX 100644
24
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
54
--- a/target/arm/mve_helper.c
25
return false;
55
+++ b/target/arm/mve_helper.c
26
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
56
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
27
gen_helper_v7m_msr(cpu_env, addr, tmp);
57
28
tcg_temp_free_i32(addr);
58
DO_VCADD_ALL(vcadd90, DO_SUB, DO_ADD)
29
}
59
DO_VCADD_ALL(vcadd270, DO_ADD, DO_SUB)
30
+ el = tcg_const_i32(s->current_el);
60
+DO_VCADD_ALL(vhcadd90, do_vhsub_s, do_vhadd_s)
31
+ gen_helper_rebuild_hflags_m32(cpu_env, el);
61
+DO_VCADD_ALL(vhcadd270, do_vhadd_s, do_vhsub_s)
32
+ tcg_temp_free_i32(el);
62
33
tcg_temp_free_i32(tmp);
63
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
34
gen_lookup_tb(s);
64
{
35
return true;
65
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/translate-mve.c
68
+++ b/target/arm/translate-mve.c
69
@@ -XXX,XX +XXX,XX @@ DO_2OP(VRHADD_U, vrhaddu)
70
/*
71
* VCADD Qd == Qm at size MO_32 is UNPREDICTABLE; we choose not to diagnose
72
* so we can reuse the DO_2OP macro. (Our implementation calculates the
73
- * "expected" results in this case.)
74
+ * "expected" results in this case.) Similarly for VHCADD.
75
*/
76
DO_2OP(VCADD90, vcadd90)
77
DO_2OP(VCADD270, vcadd270)
78
+DO_2OP(VHCADD90, vhcadd90)
79
+DO_2OP(VHCADD270, vhcadd270)
80
81
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
82
{
36
--
83
--
37
2.20.1
84
2.20.1
38
85
39
86
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
Implement the MVE VADDV insn, which performs an addition
2
across vector lanes.
2
3
3
i.MX25 supports two USB controllers. Let's wire them up.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-44-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 7 +++++++
9
target/arm/mve.decode | 2 ++
10
target/arm/mve_helper.c | 24 +++++++++++++++++++++
11
target/arm/translate-mve.c | 43 ++++++++++++++++++++++++++++++++++++++
12
4 files changed, 76 insertions(+)
4
13
5
With this patch, imx25-pdk can boot from both USB ports.
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
6
7
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20200310215146.19688-3-linux@roeck-us.net
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/fsl-imx25.h | 9 +++++++++
13
hw/arm/fsl-imx25.c | 24 ++++++++++++++++++++++++
14
2 files changed, 33 insertions(+)
15
16
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/fsl-imx25.h
16
--- a/target/arm/helper-mve.h
19
+++ b/include/hw/arm/fsl-imx25.h
17
+++ b/target/arm/helper-mve.h
20
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrmlaldavhuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
21
#include "hw/i2c/imx_i2c.h"
19
22
#include "hw/gpio/imx_gpio.h"
20
DEF_HELPER_FLAGS_4(mve_vrmlsldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
23
#include "hw/sd/sdhci.h"
21
DEF_HELPER_FLAGS_4(mve_vrmlsldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
24
+#include "hw/usb/chipidea.h"
22
+
25
#include "exec/memory.h"
23
+DEF_HELPER_FLAGS_3(mve_vaddvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
26
#include "target/arm/cpu.h"
24
+DEF_HELPER_FLAGS_3(mve_vaddvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
27
25
+DEF_HELPER_FLAGS_3(mve_vaddvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
28
@@ -XXX,XX +XXX,XX @@
26
+DEF_HELPER_FLAGS_3(mve_vaddvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
29
#define FSL_IMX25_NUM_I2CS 3
27
+DEF_HELPER_FLAGS_3(mve_vaddvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
30
#define FSL_IMX25_NUM_GPIOS 4
28
+DEF_HELPER_FLAGS_3(mve_vaddvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
31
#define FSL_IMX25_NUM_ESDHCS 2
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
32
+#define FSL_IMX25_NUM_USBS 2
33
34
typedef struct FslIMX25State {
35
/*< private >*/
36
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
37
IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
38
IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
39
SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
40
+ ChipideaState usb[FSL_IMX25_NUM_USBS];
41
MemoryRegion rom[2];
42
MemoryRegion iram;
43
MemoryRegion iram_alias;
44
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
45
#define FSL_IMX25_GPIO1_SIZE 0x4000
46
#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
47
#define FSL_IMX25_GPIO2_SIZE 0x4000
48
+#define FSL_IMX25_USB1_ADDR 0x53FF4000
49
+#define FSL_IMX25_USB1_SIZE 0x0200
50
+#define FSL_IMX25_USB2_ADDR 0x53FF4400
51
+#define FSL_IMX25_USB2_SIZE 0x0200
52
#define FSL_IMX25_AVIC_ADDR 0x68000000
53
#define FSL_IMX25_AVIC_SIZE 0x4000
54
#define FSL_IMX25_IRAM_ADDR 0x78000000
55
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
56
#define FSL_IMX25_GPIO4_IRQ 23
57
#define FSL_IMX25_ESDHC1_IRQ 9
58
#define FSL_IMX25_ESDHC2_IRQ 8
59
+#define FSL_IMX25_USB1_IRQ 37
60
+#define FSL_IMX25_USB2_IRQ 35
61
62
#endif /* FSL_IMX25_H */
63
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
64
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/fsl-imx25.c
31
--- a/target/arm/mve.decode
66
+++ b/hw/arm/fsl-imx25.c
32
+++ b/target/arm/mve.decode
67
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_init(Object *obj)
33
@@ -XXX,XX +XXX,XX @@ VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
68
sysbus_init_child_obj(obj, "sdhc[*]", &s->esdhc[i], sizeof(s->esdhc[i]),
34
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
69
TYPE_IMX_USDHC);
35
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
70
}
36
37
+# Vector add across vector
38
+VADDV 111 u:1 1110 1111 size:2 01 ... 0 1111 0 0 a:1 0 qm:3 0 rda=%rdalo
39
40
# Predicate operations
41
%mask_22_13 22:1 13:3
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_LDAVH(vrmlaldavhuw, 4, uint32_t, false, int128_add, int128_add, int128_make64
47
48
DO_LDAVH(vrmlsldavhsw, 4, int32_t, false, int128_add, int128_sub, int128_makes64)
49
DO_LDAVH(vrmlsldavhxsw, 4, int32_t, true, int128_add, int128_sub, int128_makes64)
71
+
50
+
72
+ for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
51
+/* Vector add across vector */
73
+ sysbus_init_child_obj(obj, "usb[*]", &s->usb[i], sizeof(s->usb[i]),
52
+#define DO_VADDV(OP, ESIZE, TYPE) \
74
+ TYPE_CHIPIDEA);
53
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
54
+ uint32_t ra) \
55
+ { \
56
+ uint16_t mask = mve_element_mask(env); \
57
+ unsigned e; \
58
+ TYPE *m = vm; \
59
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
60
+ if (mask & 1) { \
61
+ ra += m[H##ESIZE(e)]; \
62
+ } \
63
+ } \
64
+ mve_advance_vpt(env); \
65
+ return ra; \
66
+ } \
67
+
68
+DO_VADDV(vaddvsb, 1, uint8_t)
69
+DO_VADDV(vaddvsh, 2, uint16_t)
70
+DO_VADDV(vaddvsw, 4, uint32_t)
71
+DO_VADDV(vaddvub, 1, uint8_t)
72
+DO_VADDV(vaddvuh, 2, uint16_t)
73
+DO_VADDV(vaddvuw, 4, uint32_t)
74
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/translate-mve.c
77
+++ b/target/arm/translate-mve.c
78
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
79
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
80
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
81
typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
82
+typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
83
84
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
85
static inline long mve_qreg_offset(unsigned reg)
86
@@ -XXX,XX +XXX,XX @@ static bool trans_VPST(DisasContext *s, arg_VPST *a)
87
mve_update_and_store_eci(s);
88
return true;
89
}
90
+
91
+static bool trans_VADDV(DisasContext *s, arg_VADDV *a)
92
+{
93
+ /* VADDV: vector add across vector */
94
+ static MVEGenVADDVFn * const fns[4][2] = {
95
+ { gen_helper_mve_vaddvsb, gen_helper_mve_vaddvub },
96
+ { gen_helper_mve_vaddvsh, gen_helper_mve_vaddvuh },
97
+ { gen_helper_mve_vaddvsw, gen_helper_mve_vaddvuw },
98
+ { NULL, NULL }
99
+ };
100
+ TCGv_ptr qm;
101
+ TCGv_i32 rda;
102
+
103
+ if (!dc_isar_feature(aa32_mve, s) ||
104
+ a->size == 3) {
105
+ return false;
106
+ }
107
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
108
+ return true;
75
+ }
109
+ }
76
+
110
+
77
}
111
+ /*
78
112
+ * This insn is subject to beat-wise execution. Partial execution
79
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
113
+ * of an A=0 (no-accumulate) insn which does not execute the first
80
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
114
+ * beat must start with the current value of Rda, not zero.
81
esdhc_table[i].irq));
115
+ */
82
}
116
+ if (a->a || mve_skip_first_beat(s)) {
83
117
+ /* Accumulate input from Rda */
84
+ /* USB */
118
+ rda = load_reg(s, a->rda);
85
+ for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
119
+ } else {
86
+ static const struct {
120
+ /* Accumulate starting at zero */
87
+ hwaddr addr;
121
+ rda = tcg_const_i32(0);
88
+ unsigned int irq;
89
+ } usb_table[FSL_IMX25_NUM_USBS] = {
90
+ { FSL_IMX25_USB1_ADDR, FSL_IMX25_USB1_IRQ },
91
+ { FSL_IMX25_USB2_ADDR, FSL_IMX25_USB2_IRQ },
92
+ };
93
+
94
+ object_property_set_bool(OBJECT(&s->usb[i]), true, "realized",
95
+ &error_abort);
96
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
97
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
98
+ qdev_get_gpio_in(DEVICE(&s->avic),
99
+ usb_table[i].irq));
100
+ }
122
+ }
101
+
123
+
102
/* initialize 2 x 16 KB ROM */
124
+ qm = mve_qreg_ptr(a->qm);
103
memory_region_init_rom(&s->rom[0], NULL,
125
+ fns[a->size][a->u](rda, cpu_env, qm, rda);
104
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
126
+ store_reg(s, a->rda, rda);
127
+ tcg_temp_free_ptr(qm);
128
+
129
+ mve_update_eci(s);
130
+ return true;
131
+}
105
--
132
--
106
2.20.1
133
2.20.1
107
134
108
135
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
In a CPU with MVE, the VMOV (vector lane to general-purpose register)
2
and VMOV (general-purpose register to vector lane) insns are not
3
predicated, but they are subject to beatwise execution if they
4
are not in an IT block.
2
5
3
The Allwinner System on Chip families sun4i and above contain
6
Since our implementation always executes all 4 beats in one tick,
4
an integrated storage controller for Secure Digital (SD) and
7
this means only that we need to handle PSR.ECI:
5
Multi Media Card (MMC) interfaces. This commit adds support
8
* we must do the usual check for bad ECI state
6
for the Allwinner SD/MMC storage controller with the following
9
* we must advance ECI state if the insn succeeds
7
emulated features:
10
* if ECI says we should not be executing the beat corresponding
11
to the lane of the vector register being accessed then we
12
should skip performing the move
8
13
9
* DMA transfers
14
Note that if PSR.ECI is non-zero then we cannot be in an IT block.
10
* Direct FIFO I/O
11
* Short/Long format command responses
12
* Auto-Stop command (CMD12)
13
* Insert & remove card detection
14
15
15
The following boards are extended with the SD host controller:
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20210617121628.20116-45-peter.maydell@linaro.org
19
---
20
target/arm/translate-a32.h | 2 +
21
target/arm/translate-mve.c | 4 +-
22
target/arm/translate-vfp.c | 77 +++++++++++++++++++++++++++++++++++---
23
3 files changed, 75 insertions(+), 8 deletions(-)
16
24
17
* Cubieboard (hw/arm/cubieboard.c)
25
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
18
* Orange Pi PC (hw/arm/orangepi.c)
19
20
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
21
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
22
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Message-id: 20200311221854.30370-9-nieklinnenbank@gmail.com
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
26
hw/sd/Makefile.objs | 1 +
27
include/hw/arm/allwinner-a10.h | 2 +
28
include/hw/arm/allwinner-h3.h | 3 +
29
include/hw/sd/allwinner-sdhost.h | 135 +++++
30
hw/arm/allwinner-a10.c | 11 +
31
hw/arm/allwinner-h3.c | 15 +-
32
hw/arm/cubieboard.c | 15 +
33
hw/arm/orangepi.c | 16 +
34
hw/sd/allwinner-sdhost.c | 854 +++++++++++++++++++++++++++++++
35
hw/arm/Kconfig | 1 +
36
hw/sd/trace-events | 7 +
37
11 files changed, 1059 insertions(+), 1 deletion(-)
38
create mode 100644 include/hw/sd/allwinner-sdhost.h
39
create mode 100644 hw/sd/allwinner-sdhost.c
40
41
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
42
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/sd/Makefile.objs
27
--- a/target/arm/translate-a32.h
44
+++ b/hw/sd/Makefile.objs
28
+++ b/target/arm/translate-a32.h
45
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SD) += sd.o core.o sdmmc-internal.o
29
@@ -XXX,XX +XXX,XX @@ long neon_full_reg_offset(unsigned reg);
46
common-obj-$(CONFIG_SDHCI) += sdhci.o
30
long neon_element_offset(int reg, int element, MemOp memop);
47
common-obj-$(CONFIG_SDHCI_PCI) += sdhci-pci.o
31
void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
48
32
void clear_eci_state(DisasContext *s);
49
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sdhost.o
33
+bool mve_eci_check(DisasContext *s);
50
common-obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
34
+void mve_update_and_store_eci(DisasContext *s);
51
common-obj-$(CONFIG_OMAP) += omap_mmc.o
35
52
common-obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
36
static inline TCGv_i32 load_cpu_offset(int offset)
53
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
37
{
38
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
54
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
55
--- a/include/hw/arm/allwinner-a10.h
40
--- a/target/arm/translate-mve.c
56
+++ b/include/hw/arm/allwinner-a10.h
41
+++ b/target/arm/translate-mve.c
57
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@ static bool mve_check_qreg_bank(DisasContext *s, int qmask)
58
#include "hw/timer/allwinner-a10-pit.h"
43
return qmask < 8;
59
#include "hw/intc/allwinner-a10-pic.h"
44
}
60
#include "hw/net/allwinner_emac.h"
45
61
+#include "hw/sd/allwinner-sdhost.h"
46
-static bool mve_eci_check(DisasContext *s)
62
#include "hw/ide/ahci.h"
47
+bool mve_eci_check(DisasContext *s)
63
#include "hw/usb/hcd-ohci.h"
48
{
64
#include "hw/usb/hcd-ehci.h"
49
/*
65
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
50
* This is a beatwise insn: check that ECI is valid (not a
66
AwA10PICState intc;
51
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
67
AwEmacState emac;
52
}
68
AllwinnerAHCIState sata;
53
}
69
+ AwSdHostState mmc0;
54
70
MemoryRegion sram_a;
55
-static void mve_update_and_store_eci(DisasContext *s)
71
EHCISysBusState ehci[AW_A10_NUM_USB];
56
+void mve_update_and_store_eci(DisasContext *s)
72
OHCISysBusState ohci[AW_A10_NUM_USB];
57
{
73
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
58
/*
59
* For insns which don't call a helper function that will call
60
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
74
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
75
--- a/include/hw/arm/allwinner-h3.h
62
--- a/target/arm/translate-vfp.c
76
+++ b/include/hw/arm/allwinner-h3.h
63
+++ b/target/arm/translate-vfp.c
77
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
78
#include "hw/misc/allwinner-cpucfg.h"
65
return true;
79
#include "hw/misc/allwinner-h3-sysctrl.h"
66
}
80
#include "hw/misc/allwinner-sid.h"
67
81
+#include "hw/sd/allwinner-sdhost.h"
68
+static bool mve_skip_vmov(DisasContext *s, int vn, int index, int size)
82
#include "target/arm/cpu.h"
69
+{
83
70
+ /*
84
/**
71
+ * In a CPU with MVE, the VMOV (vector lane to general-purpose register)
85
@@ -XXX,XX +XXX,XX @@ enum {
72
+ * and VMOV (general-purpose register to vector lane) insns are not
86
AW_H3_SRAM_A2,
73
+ * predicated, but they are subject to beatwise execution if they are
87
AW_H3_SRAM_C,
74
+ * not in an IT block.
88
AW_H3_SYSCTRL,
75
+ *
89
+ AW_H3_MMC0,
76
+ * Since our implementation always executes all 4 beats in one tick,
90
AW_H3_SID,
77
+ * this means only that if PSR.ECI says we should not be executing
91
AW_H3_EHCI0,
78
+ * the beat corresponding to the lane of the vector register being
92
AW_H3_OHCI0,
79
+ * accessed then we should skip performing the move, and that we need
93
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
80
+ * to do the usual check for bad ECI state and advance of ECI state.
94
AwCpuCfgState cpucfg;
81
+ *
95
AwH3SysCtrlState sysctrl;
82
+ * Note that if PSR.ECI is non-zero then we cannot be in an IT block.
96
AwSidState sid;
83
+ *
97
+ AwSdHostState mmc0;
84
+ * Return true if this VMOV scalar <-> gpreg should be skipped because
98
GICState gic;
85
+ * the MVE PSR.ECI state says we skip the beat where the store happens.
99
MemoryRegion sram_a1;
100
MemoryRegion sram_a2;
101
diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
102
new file mode 100644
103
index XXXXXXX..XXXXXXX
104
--- /dev/null
105
+++ b/include/hw/sd/allwinner-sdhost.h
106
@@ -XXX,XX +XXX,XX @@
107
+/*
108
+ * Allwinner (sun4i and above) SD Host Controller emulation
109
+ *
110
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
111
+ *
112
+ * This program is free software: you can redistribute it and/or modify
113
+ * it under the terms of the GNU General Public License as published by
114
+ * the Free Software Foundation, either version 2 of the License, or
115
+ * (at your option) any later version.
116
+ *
117
+ * This program is distributed in the hope that it will be useful,
118
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
119
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
120
+ * GNU General Public License for more details.
121
+ *
122
+ * You should have received a copy of the GNU General Public License
123
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
124
+ */
125
+
126
+#ifndef HW_SD_ALLWINNER_SDHOST_H
127
+#define HW_SD_ALLWINNER_SDHOST_H
128
+
129
+#include "qom/object.h"
130
+#include "hw/sysbus.h"
131
+#include "hw/sd/sd.h"
132
+
133
+/**
134
+ * Object model types
135
+ * @{
136
+ */
137
+
138
+/** Generic Allwinner SD Host Controller (abstract) */
139
+#define TYPE_AW_SDHOST "allwinner-sdhost"
140
+
141
+/** Allwinner sun4i family (A10, A12) */
142
+#define TYPE_AW_SDHOST_SUN4I TYPE_AW_SDHOST "-sun4i"
143
+
144
+/** Allwinner sun5i family and newer (A13, H2+, H3, etc) */
145
+#define TYPE_AW_SDHOST_SUN5I TYPE_AW_SDHOST "-sun5i"
146
+
147
+/** @} */
148
+
149
+/**
150
+ * Object model macros
151
+ * @{
152
+ */
153
+
154
+#define AW_SDHOST(obj) \
155
+ OBJECT_CHECK(AwSdHostState, (obj), TYPE_AW_SDHOST)
156
+#define AW_SDHOST_CLASS(klass) \
157
+ OBJECT_CLASS_CHECK(AwSdHostClass, (klass), TYPE_AW_SDHOST)
158
+#define AW_SDHOST_GET_CLASS(obj) \
159
+ OBJECT_GET_CLASS(AwSdHostClass, (obj), TYPE_AW_SDHOST)
160
+
161
+/** @} */
162
+
163
+/**
164
+ * Allwinner SD Host Controller object instance state.
165
+ */
166
+typedef struct AwSdHostState {
167
+ /*< private >*/
168
+ SysBusDevice busdev;
169
+ /*< public >*/
170
+
171
+ /** Secure Digital (SD) bus, which connects to SD card (if present) */
172
+ SDBus sdbus;
173
+
174
+ /** Maps I/O registers in physical memory */
175
+ MemoryRegion iomem;
176
+
177
+ /** Interrupt output signal to notify CPU */
178
+ qemu_irq irq;
179
+
180
+ /** Number of bytes left in current DMA transfer */
181
+ uint32_t transfer_cnt;
182
+
183
+ /**
184
+ * @name Hardware Registers
185
+ * @{
186
+ */
86
+ */
187
+
87
+
188
+ uint32_t global_ctl; /**< Global Control */
88
+ /* Calculate the byte offset into Qn which we're going to access */
189
+ uint32_t clock_ctl; /**< Clock Control */
89
+ int ofs = (index << size) + ((vn & 1) * 8);
190
+ uint32_t timeout; /**< Timeout */
191
+ uint32_t bus_width; /**< Bus Width */
192
+ uint32_t block_size; /**< Block Size */
193
+ uint32_t byte_count; /**< Byte Count */
194
+
90
+
195
+ uint32_t command; /**< Command */
91
+ if (!dc_isar_feature(aa32_mve, s)) {
196
+ uint32_t command_arg; /**< Command Argument */
92
+ return false;
197
+ uint32_t response[4]; /**< Command Response */
198
+
199
+ uint32_t irq_mask; /**< Interrupt Mask */
200
+ uint32_t irq_status; /**< Raw Interrupt Status */
201
+ uint32_t status; /**< Status */
202
+
203
+ uint32_t fifo_wlevel; /**< FIFO Water Level */
204
+ uint32_t fifo_func_sel; /**< FIFO Function Select */
205
+ uint32_t debug_enable; /**< Debug Enable */
206
+ uint32_t auto12_arg; /**< Auto Command 12 Argument */
207
+ uint32_t newtiming_set; /**< SD New Timing Set */
208
+ uint32_t newtiming_debug; /**< SD New Timing Debug */
209
+ uint32_t hardware_rst; /**< Hardware Reset */
210
+ uint32_t dmac; /**< Internal DMA Controller Control */
211
+ uint32_t desc_base; /**< Descriptor List Base Address */
212
+ uint32_t dmac_status; /**< Internal DMA Controller Status */
213
+ uint32_t dmac_irq; /**< Internal DMA Controller IRQ Enable */
214
+ uint32_t card_threshold; /**< Card Threshold Control */
215
+ uint32_t startbit_detect; /**< eMMC DDR Start Bit Detection Control */
216
+ uint32_t response_crc; /**< Response CRC */
217
+ uint32_t data_crc[8]; /**< Data CRC */
218
+ uint32_t status_crc; /**< Status CRC */
219
+
220
+ /** @} */
221
+
222
+} AwSdHostState;
223
+
224
+/**
225
+ * Allwinner SD Host Controller class-level struct.
226
+ *
227
+ * This struct is filled by each sunxi device specific code
228
+ * such that the generic code can use this struct to support
229
+ * all devices.
230
+ */
231
+typedef struct AwSdHostClass {
232
+ /*< private >*/
233
+ SysBusDeviceClass parent_class;
234
+ /*< public >*/
235
+
236
+ /** Maximum buffer size in bytes per DMA descriptor */
237
+ size_t max_desc_size;
238
+
239
+} AwSdHostClass;
240
+
241
+#endif /* HW_SD_ALLWINNER_SDHOST_H */
242
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
243
index XXXXXXX..XXXXXXX 100644
244
--- a/hw/arm/allwinner-a10.c
245
+++ b/hw/arm/allwinner-a10.c
246
@@ -XXX,XX +XXX,XX @@
247
#include "hw/boards.h"
248
#include "hw/usb/hcd-ohci.h"
249
250
+#define AW_A10_MMC0_BASE 0x01c0f000
251
#define AW_A10_PIC_REG_BASE 0x01c20400
252
#define AW_A10_PIT_REG_BASE 0x01c20c00
253
#define AW_A10_UART0_REG_BASE 0x01c28000
254
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
255
sizeof(s->ohci[i]), TYPE_SYSBUS_OHCI);
256
}
257
}
258
+
259
+ sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
260
+ TYPE_AW_SDHOST_SUN4I);
261
}
262
263
static void aw_a10_realize(DeviceState *dev, Error **errp)
264
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
265
qdev_get_gpio_in(dev, 64 + i));
266
}
267
}
268
+
269
+ /* SD/MMC */
270
+ qdev_init_nofail(DEVICE(&s->mmc0));
271
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, AW_A10_MMC0_BASE);
272
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32));
273
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
274
+ "sd-bus", &error_abort);
275
}
276
277
static void aw_a10_class_init(ObjectClass *oc, void *data)
278
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
279
index XXXXXXX..XXXXXXX 100644
280
--- a/hw/arm/allwinner-h3.c
281
+++ b/hw/arm/allwinner-h3.c
282
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
283
[AW_H3_SRAM_A2] = 0x00044000,
284
[AW_H3_SRAM_C] = 0x00010000,
285
[AW_H3_SYSCTRL] = 0x01c00000,
286
+ [AW_H3_MMC0] = 0x01c0f000,
287
[AW_H3_SID] = 0x01c14000,
288
[AW_H3_EHCI0] = 0x01c1a000,
289
[AW_H3_OHCI0] = 0x01c1a400,
290
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
291
{ "lcd0", 0x01c0c000, 4 * KiB },
292
{ "lcd1", 0x01c0d000, 4 * KiB },
293
{ "ve", 0x01c0e000, 4 * KiB },
294
- { "mmc0", 0x01c0f000, 4 * KiB },
295
{ "mmc1", 0x01c10000, 4 * KiB },
296
{ "mmc2", 0x01c11000, 4 * KiB },
297
{ "crypto", 0x01c15000, 4 * KiB },
298
@@ -XXX,XX +XXX,XX @@ enum {
299
AW_H3_GIC_SPI_UART3 = 3,
300
AW_H3_GIC_SPI_TIMER0 = 18,
301
AW_H3_GIC_SPI_TIMER1 = 19,
302
+ AW_H3_GIC_SPI_MMC0 = 60,
303
AW_H3_GIC_SPI_EHCI0 = 72,
304
AW_H3_GIC_SPI_OHCI0 = 73,
305
AW_H3_GIC_SPI_EHCI1 = 74,
306
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
307
TYPE_AW_SID);
308
object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
309
"identifier", &error_abort);
310
+
311
+ sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
312
+ TYPE_AW_SDHOST_SUN5I);
313
}
314
315
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
316
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
317
qdev_init_nofail(DEVICE(&s->sid));
318
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H3_SID]);
319
320
+ /* SD/MMC */
321
+ qdev_init_nofail(DEVICE(&s->mmc0));
322
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, s->memmap[AW_H3_MMC0]);
323
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0,
324
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_MMC0));
325
+
326
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
327
+ "sd-bus", &error_abort);
328
+
329
/* Universal Serial Bus */
330
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
331
qdev_get_gpio_in(DEVICE(&s->gic),
332
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
333
index XXXXXXX..XXXXXXX 100644
334
--- a/hw/arm/cubieboard.c
335
+++ b/hw/arm/cubieboard.c
336
@@ -XXX,XX +XXX,XX @@
337
#include "sysemu/sysemu.h"
338
#include "hw/sysbus.h"
339
#include "hw/boards.h"
340
+#include "hw/qdev-properties.h"
341
#include "hw/arm/allwinner-a10.h"
342
343
static struct arm_boot_info cubieboard_binfo = {
344
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
345
{
346
AwA10State *a10;
347
Error *err = NULL;
348
+ DriveInfo *di;
349
+ BlockBackend *blk;
350
+ BusState *bus;
351
+ DeviceState *carddev;
352
353
/* BIOS is not supported by this board */
354
if (bios_name) {
355
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
356
exit(1);
357
}
358
359
+ /* Retrieve SD bus */
360
+ di = drive_get_next(IF_SD);
361
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
362
+ bus = qdev_get_child_bus(DEVICE(a10), "sd-bus");
363
+
364
+ /* Plug in SD card */
365
+ carddev = qdev_create(bus, TYPE_SD_CARD);
366
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
367
+ object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
368
+
369
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
370
machine->ram);
371
372
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
373
index XXXXXXX..XXXXXXX 100644
374
--- a/hw/arm/orangepi.c
375
+++ b/hw/arm/orangepi.c
376
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info orangepi_binfo = {
377
static void orangepi_init(MachineState *machine)
378
{
379
AwH3State *h3;
380
+ DriveInfo *di;
381
+ BlockBackend *blk;
382
+ BusState *bus;
383
+ DeviceState *carddev;
384
385
/* BIOS is not supported by this board */
386
if (bios_name) {
387
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
388
/* Mark H3 object realized */
389
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
390
391
+ /* Retrieve SD bus */
392
+ di = drive_get_next(IF_SD);
393
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
394
+ bus = qdev_get_child_bus(DEVICE(h3), "sd-bus");
395
+
396
+ /* Plug in SD card */
397
+ carddev = qdev_create(bus, TYPE_SD_CARD);
398
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
399
+ object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
400
+
401
/* SDRAM */
402
memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
403
machine->ram);
404
@@ -XXX,XX +XXX,XX @@ static void orangepi_machine_init(MachineClass *mc)
405
{
406
mc->desc = "Orange Pi PC";
407
mc->init = orangepi_init;
408
+ mc->block_default_type = IF_SD;
409
+ mc->units_per_default_bus = 1;
410
mc->min_cpus = AW_H3_NUM_CPUS;
411
mc->max_cpus = AW_H3_NUM_CPUS;
412
mc->default_cpus = AW_H3_NUM_CPUS;
413
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
414
new file mode 100644
415
index XXXXXXX..XXXXXXX
416
--- /dev/null
417
+++ b/hw/sd/allwinner-sdhost.c
418
@@ -XXX,XX +XXX,XX @@
419
+/*
420
+ * Allwinner (sun4i and above) SD Host Controller emulation
421
+ *
422
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
423
+ *
424
+ * This program is free software: you can redistribute it and/or modify
425
+ * it under the terms of the GNU General Public License as published by
426
+ * the Free Software Foundation, either version 2 of the License, or
427
+ * (at your option) any later version.
428
+ *
429
+ * This program is distributed in the hope that it will be useful,
430
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
431
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
432
+ * GNU General Public License for more details.
433
+ *
434
+ * You should have received a copy of the GNU General Public License
435
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
436
+ */
437
+
438
+#include "qemu/osdep.h"
439
+#include "qemu/log.h"
440
+#include "qemu/module.h"
441
+#include "qemu/units.h"
442
+#include "sysemu/blockdev.h"
443
+#include "hw/irq.h"
444
+#include "hw/sd/allwinner-sdhost.h"
445
+#include "migration/vmstate.h"
446
+#include "trace.h"
447
+
448
+#define TYPE_AW_SDHOST_BUS "allwinner-sdhost-bus"
449
+#define AW_SDHOST_BUS(obj) \
450
+ OBJECT_CHECK(SDBus, (obj), TYPE_AW_SDHOST_BUS)
451
+
452
+/* SD Host register offsets */
453
+enum {
454
+ REG_SD_GCTL = 0x00, /* Global Control */
455
+ REG_SD_CKCR = 0x04, /* Clock Control */
456
+ REG_SD_TMOR = 0x08, /* Timeout */
457
+ REG_SD_BWDR = 0x0C, /* Bus Width */
458
+ REG_SD_BKSR = 0x10, /* Block Size */
459
+ REG_SD_BYCR = 0x14, /* Byte Count */
460
+ REG_SD_CMDR = 0x18, /* Command */
461
+ REG_SD_CAGR = 0x1C, /* Command Argument */
462
+ REG_SD_RESP0 = 0x20, /* Response Zero */
463
+ REG_SD_RESP1 = 0x24, /* Response One */
464
+ REG_SD_RESP2 = 0x28, /* Response Two */
465
+ REG_SD_RESP3 = 0x2C, /* Response Three */
466
+ REG_SD_IMKR = 0x30, /* Interrupt Mask */
467
+ REG_SD_MISR = 0x34, /* Masked Interrupt Status */
468
+ REG_SD_RISR = 0x38, /* Raw Interrupt Status */
469
+ REG_SD_STAR = 0x3C, /* Status */
470
+ REG_SD_FWLR = 0x40, /* FIFO Water Level */
471
+ REG_SD_FUNS = 0x44, /* FIFO Function Select */
472
+ REG_SD_DBGC = 0x50, /* Debug Enable */
473
+ REG_SD_A12A = 0x58, /* Auto command 12 argument */
474
+ REG_SD_NTSR = 0x5C, /* SD NewTiming Set */
475
+ REG_SD_SDBG = 0x60, /* SD newTiming Set Debug */
476
+ REG_SD_HWRST = 0x78, /* Hardware Reset Register */
477
+ REG_SD_DMAC = 0x80, /* Internal DMA Controller Control */
478
+ REG_SD_DLBA = 0x84, /* Descriptor List Base Address */
479
+ REG_SD_IDST = 0x88, /* Internal DMA Controller Status */
480
+ REG_SD_IDIE = 0x8C, /* Internal DMA Controller IRQ Enable */
481
+ REG_SD_THLDC = 0x100, /* Card Threshold Control */
482
+ REG_SD_DSBD = 0x10C, /* eMMC DDR Start Bit Detection Control */
483
+ REG_SD_RES_CRC = 0x110, /* Response CRC from card/eMMC */
484
+ REG_SD_DATA7_CRC = 0x114, /* CRC Data 7 from card/eMMC */
485
+ REG_SD_DATA6_CRC = 0x118, /* CRC Data 6 from card/eMMC */
486
+ REG_SD_DATA5_CRC = 0x11C, /* CRC Data 5 from card/eMMC */
487
+ REG_SD_DATA4_CRC = 0x120, /* CRC Data 4 from card/eMMC */
488
+ REG_SD_DATA3_CRC = 0x124, /* CRC Data 3 from card/eMMC */
489
+ REG_SD_DATA2_CRC = 0x128, /* CRC Data 2 from card/eMMC */
490
+ REG_SD_DATA1_CRC = 0x12C, /* CRC Data 1 from card/eMMC */
491
+ REG_SD_DATA0_CRC = 0x130, /* CRC Data 0 from card/eMMC */
492
+ REG_SD_CRC_STA = 0x134, /* CRC status from card/eMMC during write */
493
+ REG_SD_FIFO = 0x200, /* Read/Write FIFO */
494
+};
495
+
496
+/* SD Host register flags */
497
+enum {
498
+ SD_GCTL_FIFO_AC_MOD = (1 << 31),
499
+ SD_GCTL_DDR_MOD_SEL = (1 << 10),
500
+ SD_GCTL_CD_DBC_ENB = (1 << 8),
501
+ SD_GCTL_DMA_ENB = (1 << 5),
502
+ SD_GCTL_INT_ENB = (1 << 4),
503
+ SD_GCTL_DMA_RST = (1 << 2),
504
+ SD_GCTL_FIFO_RST = (1 << 1),
505
+ SD_GCTL_SOFT_RST = (1 << 0),
506
+};
507
+
508
+enum {
509
+ SD_CMDR_LOAD = (1 << 31),
510
+ SD_CMDR_CLKCHANGE = (1 << 21),
511
+ SD_CMDR_WRITE = (1 << 10),
512
+ SD_CMDR_AUTOSTOP = (1 << 12),
513
+ SD_CMDR_DATA = (1 << 9),
514
+ SD_CMDR_RESPONSE_LONG = (1 << 7),
515
+ SD_CMDR_RESPONSE = (1 << 6),
516
+ SD_CMDR_CMDID_MASK = (0x3f),
517
+};
518
+
519
+enum {
520
+ SD_RISR_CARD_REMOVE = (1 << 31),
521
+ SD_RISR_CARD_INSERT = (1 << 30),
522
+ SD_RISR_SDIO_INTR = (1 << 16),
523
+ SD_RISR_AUTOCMD_DONE = (1 << 14),
524
+ SD_RISR_DATA_COMPLETE = (1 << 3),
525
+ SD_RISR_CMD_COMPLETE = (1 << 2),
526
+ SD_RISR_NO_RESPONSE = (1 << 1),
527
+};
528
+
529
+enum {
530
+ SD_STAR_CARD_PRESENT = (1 << 8),
531
+};
532
+
533
+enum {
534
+ SD_IDST_INT_SUMMARY = (1 << 8),
535
+ SD_IDST_RECEIVE_IRQ = (1 << 1),
536
+ SD_IDST_TRANSMIT_IRQ = (1 << 0),
537
+ SD_IDST_IRQ_MASK = (1 << 1) | (1 << 0) | (1 << 8),
538
+ SD_IDST_WR_MASK = (0x3ff),
539
+};
540
+
541
+/* SD Host register reset values */
542
+enum {
543
+ REG_SD_GCTL_RST = 0x00000300,
544
+ REG_SD_CKCR_RST = 0x0,
545
+ REG_SD_TMOR_RST = 0xFFFFFF40,
546
+ REG_SD_BWDR_RST = 0x0,
547
+ REG_SD_BKSR_RST = 0x00000200,
548
+ REG_SD_BYCR_RST = 0x00000200,
549
+ REG_SD_CMDR_RST = 0x0,
550
+ REG_SD_CAGR_RST = 0x0,
551
+ REG_SD_RESP_RST = 0x0,
552
+ REG_SD_IMKR_RST = 0x0,
553
+ REG_SD_MISR_RST = 0x0,
554
+ REG_SD_RISR_RST = 0x0,
555
+ REG_SD_STAR_RST = 0x00000100,
556
+ REG_SD_FWLR_RST = 0x000F0000,
557
+ REG_SD_FUNS_RST = 0x0,
558
+ REG_SD_DBGC_RST = 0x0,
559
+ REG_SD_A12A_RST = 0x0000FFFF,
560
+ REG_SD_NTSR_RST = 0x00000001,
561
+ REG_SD_SDBG_RST = 0x0,
562
+ REG_SD_HWRST_RST = 0x00000001,
563
+ REG_SD_DMAC_RST = 0x0,
564
+ REG_SD_DLBA_RST = 0x0,
565
+ REG_SD_IDST_RST = 0x0,
566
+ REG_SD_IDIE_RST = 0x0,
567
+ REG_SD_THLDC_RST = 0x0,
568
+ REG_SD_DSBD_RST = 0x0,
569
+ REG_SD_RES_CRC_RST = 0x0,
570
+ REG_SD_DATA_CRC_RST = 0x0,
571
+ REG_SD_CRC_STA_RST = 0x0,
572
+ REG_SD_FIFO_RST = 0x0,
573
+};
574
+
575
+/* Data transfer descriptor for DMA */
576
+typedef struct TransferDescriptor {
577
+ uint32_t status; /* Status flags */
578
+ uint32_t size; /* Data buffer size */
579
+ uint32_t addr; /* Data buffer address */
580
+ uint32_t next; /* Physical address of next descriptor */
581
+} TransferDescriptor;
582
+
583
+/* Data transfer descriptor flags */
584
+enum {
585
+ DESC_STATUS_HOLD = (1 << 31), /* Set when descriptor is in use by DMA */
586
+ DESC_STATUS_ERROR = (1 << 30), /* Set when DMA transfer error occurred */
587
+ DESC_STATUS_CHAIN = (1 << 4), /* Indicates chained descriptor. */
588
+ DESC_STATUS_FIRST = (1 << 3), /* Set on the first descriptor */
589
+ DESC_STATUS_LAST = (1 << 2), /* Set on the last descriptor */
590
+ DESC_STATUS_NOIRQ = (1 << 1), /* Skip raising interrupt after transfer */
591
+ DESC_SIZE_MASK = (0xfffffffc)
592
+};
593
+
594
+static void allwinner_sdhost_update_irq(AwSdHostState *s)
595
+{
596
+ uint32_t irq;
597
+
598
+ if (s->global_ctl & SD_GCTL_INT_ENB) {
599
+ irq = s->irq_status & s->irq_mask;
600
+ } else {
601
+ irq = 0;
602
+ }
93
+ }
603
+
94
+
604
+ trace_allwinner_sdhost_update_irq(irq);
95
+ switch (s->eci) {
605
+ qemu_set_irq(s->irq, irq);
96
+ case ECI_NONE:
606
+}
97
+ return false;
607
+
98
+ case ECI_A0:
608
+static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
99
+ return ofs < 4;
609
+ uint32_t bytes)
100
+ case ECI_A0A1:
610
+{
101
+ return ofs < 8;
611
+ if (s->transfer_cnt > bytes) {
102
+ case ECI_A0A1A2:
612
+ s->transfer_cnt -= bytes;
103
+ case ECI_A0A1A2B0:
613
+ } else {
104
+ return ofs < 12;
614
+ s->transfer_cnt = 0;
105
+ default:
615
+ }
106
+ g_assert_not_reached();
616
+
617
+ if (!s->transfer_cnt) {
618
+ s->irq_status |= SD_RISR_DATA_COMPLETE;
619
+ }
107
+ }
620
+}
108
+}
621
+
109
+
622
+static void allwinner_sdhost_set_inserted(DeviceState *dev, bool inserted)
110
static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
623
+{
111
{
624
+ AwSdHostState *s = AW_SDHOST(dev);
112
/* VMOV scalar to general purpose register */
625
+
113
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
626
+ trace_allwinner_sdhost_set_inserted(inserted);
114
return false;
627
+
115
}
628
+ if (inserted) {
116
629
+ s->irq_status |= SD_RISR_CARD_INSERT;
117
+ if (dc_isar_feature(aa32_mve, s)) {
630
+ s->irq_status &= ~SD_RISR_CARD_REMOVE;
118
+ if (!mve_eci_check(s)) {
631
+ s->status |= SD_STAR_CARD_PRESENT;
119
+ return true;
632
+ } else {
633
+ s->irq_status &= ~SD_RISR_CARD_INSERT;
634
+ s->irq_status |= SD_RISR_CARD_REMOVE;
635
+ s->status &= ~SD_STAR_CARD_PRESENT;
636
+ }
637
+
638
+ allwinner_sdhost_update_irq(s);
639
+}
640
+
641
+static void allwinner_sdhost_send_command(AwSdHostState *s)
642
+{
643
+ SDRequest request;
644
+ uint8_t resp[16];
645
+ int rlen;
646
+
647
+ /* Auto clear load flag */
648
+ s->command &= ~SD_CMDR_LOAD;
649
+
650
+ /* Clock change does not actually interact with the SD bus */
651
+ if (!(s->command & SD_CMDR_CLKCHANGE)) {
652
+
653
+ /* Prepare request */
654
+ request.cmd = s->command & SD_CMDR_CMDID_MASK;
655
+ request.arg = s->command_arg;
656
+
657
+ /* Send request to SD bus */
658
+ rlen = sdbus_do_command(&s->sdbus, &request, resp);
659
+ if (rlen < 0) {
660
+ goto error;
661
+ }
662
+
663
+ /* If the command has a response, store it in the response registers */
664
+ if ((s->command & SD_CMDR_RESPONSE)) {
665
+ if (rlen == 4 && !(s->command & SD_CMDR_RESPONSE_LONG)) {
666
+ s->response[0] = ldl_be_p(&resp[0]);
667
+ s->response[1] = s->response[2] = s->response[3] = 0;
668
+
669
+ } else if (rlen == 16 && (s->command & SD_CMDR_RESPONSE_LONG)) {
670
+ s->response[0] = ldl_be_p(&resp[12]);
671
+ s->response[1] = ldl_be_p(&resp[8]);
672
+ s->response[2] = ldl_be_p(&resp[4]);
673
+ s->response[3] = ldl_be_p(&resp[0]);
674
+ } else {
675
+ goto error;
676
+ }
677
+ }
120
+ }
678
+ }
121
+ }
679
+
122
+
680
+ /* Set interrupt status bits */
123
if (!vfp_access_check(s)) {
681
+ s->irq_status |= SD_RISR_CMD_COMPLETE;
124
return true;
682
+ return;
125
}
683
+
126
684
+error:
127
- tmp = tcg_temp_new_i32();
685
+ s->irq_status |= SD_RISR_NO_RESPONSE;
128
- read_neon_element32(tmp, a->vn, a->index, a->size | (a->u ? 0 : MO_SIGN));
686
+}
129
- store_reg(s, a->rt, tmp);
687
+
130
+ if (!mve_skip_vmov(s, a->vn, a->index, a->size)) {
688
+static void allwinner_sdhost_auto_stop(AwSdHostState *s)
131
+ tmp = tcg_temp_new_i32();
689
+{
132
+ read_neon_element32(tmp, a->vn, a->index,
690
+ /*
133
+ a->size | (a->u ? 0 : MO_SIGN));
691
+ * The stop command (CMD12) ensures the SD bus
134
+ store_reg(s, a->rt, tmp);
692
+ * returns to the transfer state.
693
+ */
694
+ if ((s->command & SD_CMDR_AUTOSTOP) && (s->transfer_cnt == 0)) {
695
+ /* First save current command registers */
696
+ uint32_t saved_cmd = s->command;
697
+ uint32_t saved_arg = s->command_arg;
698
+
699
+ /* Prepare stop command (CMD12) */
700
+ s->command &= ~SD_CMDR_CMDID_MASK;
701
+ s->command |= 12; /* CMD12 */
702
+ s->command_arg = 0;
703
+
704
+ /* Put the command on SD bus */
705
+ allwinner_sdhost_send_command(s);
706
+
707
+ /* Restore command values */
708
+ s->command = saved_cmd;
709
+ s->command_arg = saved_arg;
710
+
711
+ /* Set IRQ status bit for automatic stop done */
712
+ s->irq_status |= SD_RISR_AUTOCMD_DONE;
713
+ }
135
+ }
714
+}
136
715
+
137
+ if (dc_isar_feature(aa32_mve, s)) {
716
+static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
138
+ mve_update_and_store_eci(s);
717
+ hwaddr desc_addr,
718
+ TransferDescriptor *desc,
719
+ bool is_write, uint32_t max_bytes)
720
+{
721
+ AwSdHostClass *klass = AW_SDHOST_GET_CLASS(s);
722
+ uint32_t num_done = 0;
723
+ uint32_t num_bytes = max_bytes;
724
+ uint8_t buf[1024];
725
+
726
+ /* Read descriptor */
727
+ cpu_physical_memory_read(desc_addr, desc, sizeof(*desc));
728
+ if (desc->size == 0) {
729
+ desc->size = klass->max_desc_size;
730
+ } else if (desc->size > klass->max_desc_size) {
731
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA descriptor buffer size "
732
+ " is out-of-bounds: %" PRIu32 " > %zu",
733
+ __func__, desc->size, klass->max_desc_size);
734
+ desc->size = klass->max_desc_size;
735
+ }
139
+ }
736
+ if (desc->size < num_bytes) {
140
return true;
737
+ num_bytes = desc->size;
141
}
738
+ }
142
739
+
143
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
740
+ trace_allwinner_sdhost_process_desc(desc_addr, desc->size,
144
return false;
741
+ is_write, max_bytes);
145
}
742
+
146
743
+ while (num_done < num_bytes) {
147
+ if (dc_isar_feature(aa32_mve, s)) {
744
+ /* Try to completely fill the local buffer */
148
+ if (!mve_eci_check(s)) {
745
+ uint32_t buf_bytes = num_bytes - num_done;
149
+ return true;
746
+ if (buf_bytes > sizeof(buf)) {
747
+ buf_bytes = sizeof(buf);
748
+ }
749
+
750
+ /* Write to SD bus */
751
+ if (is_write) {
752
+ cpu_physical_memory_read((desc->addr & DESC_SIZE_MASK) + num_done,
753
+ buf, buf_bytes);
754
+
755
+ for (uint32_t i = 0; i < buf_bytes; i++) {
756
+ sdbus_write_data(&s->sdbus, buf[i]);
757
+ }
758
+
759
+ /* Read from SD bus */
760
+ } else {
761
+ for (uint32_t i = 0; i < buf_bytes; i++) {
762
+ buf[i] = sdbus_read_data(&s->sdbus);
763
+ }
764
+ cpu_physical_memory_write((desc->addr & DESC_SIZE_MASK) + num_done,
765
+ buf, buf_bytes);
766
+ }
767
+ num_done += buf_bytes;
768
+ }
769
+
770
+ /* Clear hold flag and flush descriptor */
771
+ desc->status &= ~DESC_STATUS_HOLD;
772
+ cpu_physical_memory_write(desc_addr, desc, sizeof(*desc));
773
+
774
+ return num_done;
775
+}
776
+
777
+static void allwinner_sdhost_dma(AwSdHostState *s)
778
+{
779
+ TransferDescriptor desc;
780
+ hwaddr desc_addr = s->desc_base;
781
+ bool is_write = (s->command & SD_CMDR_WRITE);
782
+ uint32_t bytes_done = 0;
783
+
784
+ /* Check if DMA can be performed */
785
+ if (s->byte_count == 0 || s->block_size == 0 ||
786
+ !(s->global_ctl & SD_GCTL_DMA_ENB)) {
787
+ return;
788
+ }
789
+
790
+ /*
791
+ * For read operations, data must be available on the SD bus
792
+ * If not, it is an error and we should not act at all
793
+ */
794
+ if (!is_write && !sdbus_data_ready(&s->sdbus)) {
795
+ return;
796
+ }
797
+
798
+ /* Process the DMA descriptors until all data is copied */
799
+ while (s->byte_count > 0) {
800
+ bytes_done = allwinner_sdhost_process_desc(s, desc_addr, &desc,
801
+ is_write, s->byte_count);
802
+ allwinner_sdhost_update_transfer_cnt(s, bytes_done);
803
+
804
+ if (bytes_done <= s->byte_count) {
805
+ s->byte_count -= bytes_done;
806
+ } else {
807
+ s->byte_count = 0;
808
+ }
809
+
810
+ if (desc.status & DESC_STATUS_LAST) {
811
+ break;
812
+ } else {
813
+ desc_addr = desc.next;
814
+ }
150
+ }
815
+ }
151
+ }
816
+
152
+
817
+ /* Raise IRQ to signal DMA is completed */
153
if (!vfp_access_check(s)) {
818
+ s->irq_status |= SD_RISR_DATA_COMPLETE | SD_RISR_SDIO_INTR;
154
return true;
819
+
155
}
820
+ /* Update DMAC bits */
156
821
+ s->dmac_status |= SD_IDST_INT_SUMMARY;
157
- tmp = load_reg(s, a->rt);
822
+
158
- write_neon_element32(tmp, a->vn, a->index, a->size);
823
+ if (is_write) {
159
- tcg_temp_free_i32(tmp);
824
+ s->dmac_status |= SD_IDST_TRANSMIT_IRQ;
160
+ if (!mve_skip_vmov(s, a->vn, a->index, a->size)) {
825
+ } else {
161
+ tmp = load_reg(s, a->rt);
826
+ s->dmac_status |= SD_IDST_RECEIVE_IRQ;
162
+ write_neon_element32(tmp, a->vn, a->index, a->size);
163
+ tcg_temp_free_i32(tmp);
827
+ }
164
+ }
828
+}
165
829
+
166
+ if (dc_isar_feature(aa32_mve, s)) {
830
+static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
167
+ mve_update_and_store_eci(s);
831
+ unsigned size)
832
+{
833
+ AwSdHostState *s = AW_SDHOST(opaque);
834
+ uint32_t res = 0;
835
+
836
+ switch (offset) {
837
+ case REG_SD_GCTL: /* Global Control */
838
+ res = s->global_ctl;
839
+ break;
840
+ case REG_SD_CKCR: /* Clock Control */
841
+ res = s->clock_ctl;
842
+ break;
843
+ case REG_SD_TMOR: /* Timeout */
844
+ res = s->timeout;
845
+ break;
846
+ case REG_SD_BWDR: /* Bus Width */
847
+ res = s->bus_width;
848
+ break;
849
+ case REG_SD_BKSR: /* Block Size */
850
+ res = s->block_size;
851
+ break;
852
+ case REG_SD_BYCR: /* Byte Count */
853
+ res = s->byte_count;
854
+ break;
855
+ case REG_SD_CMDR: /* Command */
856
+ res = s->command;
857
+ break;
858
+ case REG_SD_CAGR: /* Command Argument */
859
+ res = s->command_arg;
860
+ break;
861
+ case REG_SD_RESP0: /* Response Zero */
862
+ res = s->response[0];
863
+ break;
864
+ case REG_SD_RESP1: /* Response One */
865
+ res = s->response[1];
866
+ break;
867
+ case REG_SD_RESP2: /* Response Two */
868
+ res = s->response[2];
869
+ break;
870
+ case REG_SD_RESP3: /* Response Three */
871
+ res = s->response[3];
872
+ break;
873
+ case REG_SD_IMKR: /* Interrupt Mask */
874
+ res = s->irq_mask;
875
+ break;
876
+ case REG_SD_MISR: /* Masked Interrupt Status */
877
+ res = s->irq_status & s->irq_mask;
878
+ break;
879
+ case REG_SD_RISR: /* Raw Interrupt Status */
880
+ res = s->irq_status;
881
+ break;
882
+ case REG_SD_STAR: /* Status */
883
+ res = s->status;
884
+ break;
885
+ case REG_SD_FWLR: /* FIFO Water Level */
886
+ res = s->fifo_wlevel;
887
+ break;
888
+ case REG_SD_FUNS: /* FIFO Function Select */
889
+ res = s->fifo_func_sel;
890
+ break;
891
+ case REG_SD_DBGC: /* Debug Enable */
892
+ res = s->debug_enable;
893
+ break;
894
+ case REG_SD_A12A: /* Auto command 12 argument */
895
+ res = s->auto12_arg;
896
+ break;
897
+ case REG_SD_NTSR: /* SD NewTiming Set */
898
+ res = s->newtiming_set;
899
+ break;
900
+ case REG_SD_SDBG: /* SD newTiming Set Debug */
901
+ res = s->newtiming_debug;
902
+ break;
903
+ case REG_SD_HWRST: /* Hardware Reset Register */
904
+ res = s->hardware_rst;
905
+ break;
906
+ case REG_SD_DMAC: /* Internal DMA Controller Control */
907
+ res = s->dmac;
908
+ break;
909
+ case REG_SD_DLBA: /* Descriptor List Base Address */
910
+ res = s->desc_base;
911
+ break;
912
+ case REG_SD_IDST: /* Internal DMA Controller Status */
913
+ res = s->dmac_status;
914
+ break;
915
+ case REG_SD_IDIE: /* Internal DMA Controller Interrupt Enable */
916
+ res = s->dmac_irq;
917
+ break;
918
+ case REG_SD_THLDC: /* Card Threshold Control */
919
+ res = s->card_threshold;
920
+ break;
921
+ case REG_SD_DSBD: /* eMMC DDR Start Bit Detection Control */
922
+ res = s->startbit_detect;
923
+ break;
924
+ case REG_SD_RES_CRC: /* Response CRC from card/eMMC */
925
+ res = s->response_crc;
926
+ break;
927
+ case REG_SD_DATA7_CRC: /* CRC Data 7 from card/eMMC */
928
+ case REG_SD_DATA6_CRC: /* CRC Data 6 from card/eMMC */
929
+ case REG_SD_DATA5_CRC: /* CRC Data 5 from card/eMMC */
930
+ case REG_SD_DATA4_CRC: /* CRC Data 4 from card/eMMC */
931
+ case REG_SD_DATA3_CRC: /* CRC Data 3 from card/eMMC */
932
+ case REG_SD_DATA2_CRC: /* CRC Data 2 from card/eMMC */
933
+ case REG_SD_DATA1_CRC: /* CRC Data 1 from card/eMMC */
934
+ case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */
935
+ res = s->data_crc[((offset - REG_SD_DATA7_CRC) / sizeof(uint32_t))];
936
+ break;
937
+ case REG_SD_CRC_STA: /* CRC status from card/eMMC in write operation */
938
+ res = s->status_crc;
939
+ break;
940
+ case REG_SD_FIFO: /* Read/Write FIFO */
941
+ if (sdbus_data_ready(&s->sdbus)) {
942
+ res = sdbus_read_data(&s->sdbus);
943
+ res |= sdbus_read_data(&s->sdbus) << 8;
944
+ res |= sdbus_read_data(&s->sdbus) << 16;
945
+ res |= sdbus_read_data(&s->sdbus) << 24;
946
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
947
+ allwinner_sdhost_auto_stop(s);
948
+ allwinner_sdhost_update_irq(s);
949
+ } else {
950
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no data ready on SD bus\n",
951
+ __func__);
952
+ }
953
+ break;
954
+ default:
955
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
956
+ HWADDR_PRIx"\n", __func__, offset);
957
+ res = 0;
958
+ break;
959
+ }
168
+ }
960
+
169
return true;
961
+ trace_allwinner_sdhost_read(offset, res, size);
170
}
962
+ return res;
171
963
+}
964
+
965
+static void allwinner_sdhost_write(void *opaque, hwaddr offset,
966
+ uint64_t value, unsigned size)
967
+{
968
+ AwSdHostState *s = AW_SDHOST(opaque);
969
+
970
+ trace_allwinner_sdhost_write(offset, value, size);
971
+
972
+ switch (offset) {
973
+ case REG_SD_GCTL: /* Global Control */
974
+ s->global_ctl = value;
975
+ s->global_ctl &= ~(SD_GCTL_DMA_RST | SD_GCTL_FIFO_RST |
976
+ SD_GCTL_SOFT_RST);
977
+ allwinner_sdhost_update_irq(s);
978
+ break;
979
+ case REG_SD_CKCR: /* Clock Control */
980
+ s->clock_ctl = value;
981
+ break;
982
+ case REG_SD_TMOR: /* Timeout */
983
+ s->timeout = value;
984
+ break;
985
+ case REG_SD_BWDR: /* Bus Width */
986
+ s->bus_width = value;
987
+ break;
988
+ case REG_SD_BKSR: /* Block Size */
989
+ s->block_size = value;
990
+ break;
991
+ case REG_SD_BYCR: /* Byte Count */
992
+ s->byte_count = value;
993
+ s->transfer_cnt = value;
994
+ break;
995
+ case REG_SD_CMDR: /* Command */
996
+ s->command = value;
997
+ if (value & SD_CMDR_LOAD) {
998
+ allwinner_sdhost_send_command(s);
999
+ allwinner_sdhost_dma(s);
1000
+ allwinner_sdhost_auto_stop(s);
1001
+ }
1002
+ allwinner_sdhost_update_irq(s);
1003
+ break;
1004
+ case REG_SD_CAGR: /* Command Argument */
1005
+ s->command_arg = value;
1006
+ break;
1007
+ case REG_SD_RESP0: /* Response Zero */
1008
+ s->response[0] = value;
1009
+ break;
1010
+ case REG_SD_RESP1: /* Response One */
1011
+ s->response[1] = value;
1012
+ break;
1013
+ case REG_SD_RESP2: /* Response Two */
1014
+ s->response[2] = value;
1015
+ break;
1016
+ case REG_SD_RESP3: /* Response Three */
1017
+ s->response[3] = value;
1018
+ break;
1019
+ case REG_SD_IMKR: /* Interrupt Mask */
1020
+ s->irq_mask = value;
1021
+ allwinner_sdhost_update_irq(s);
1022
+ break;
1023
+ case REG_SD_MISR: /* Masked Interrupt Status */
1024
+ case REG_SD_RISR: /* Raw Interrupt Status */
1025
+ s->irq_status &= ~value;
1026
+ allwinner_sdhost_update_irq(s);
1027
+ break;
1028
+ case REG_SD_STAR: /* Status */
1029
+ s->status &= ~value;
1030
+ allwinner_sdhost_update_irq(s);
1031
+ break;
1032
+ case REG_SD_FWLR: /* FIFO Water Level */
1033
+ s->fifo_wlevel = value;
1034
+ break;
1035
+ case REG_SD_FUNS: /* FIFO Function Select */
1036
+ s->fifo_func_sel = value;
1037
+ break;
1038
+ case REG_SD_DBGC: /* Debug Enable */
1039
+ s->debug_enable = value;
1040
+ break;
1041
+ case REG_SD_A12A: /* Auto command 12 argument */
1042
+ s->auto12_arg = value;
1043
+ break;
1044
+ case REG_SD_NTSR: /* SD NewTiming Set */
1045
+ s->newtiming_set = value;
1046
+ break;
1047
+ case REG_SD_SDBG: /* SD newTiming Set Debug */
1048
+ s->newtiming_debug = value;
1049
+ break;
1050
+ case REG_SD_HWRST: /* Hardware Reset Register */
1051
+ s->hardware_rst = value;
1052
+ break;
1053
+ case REG_SD_DMAC: /* Internal DMA Controller Control */
1054
+ s->dmac = value;
1055
+ allwinner_sdhost_update_irq(s);
1056
+ break;
1057
+ case REG_SD_DLBA: /* Descriptor List Base Address */
1058
+ s->desc_base = value;
1059
+ break;
1060
+ case REG_SD_IDST: /* Internal DMA Controller Status */
1061
+ s->dmac_status &= (~SD_IDST_WR_MASK) | (~value & SD_IDST_WR_MASK);
1062
+ allwinner_sdhost_update_irq(s);
1063
+ break;
1064
+ case REG_SD_IDIE: /* Internal DMA Controller Interrupt Enable */
1065
+ s->dmac_irq = value;
1066
+ allwinner_sdhost_update_irq(s);
1067
+ break;
1068
+ case REG_SD_THLDC: /* Card Threshold Control */
1069
+ s->card_threshold = value;
1070
+ break;
1071
+ case REG_SD_DSBD: /* eMMC DDR Start Bit Detection Control */
1072
+ s->startbit_detect = value;
1073
+ break;
1074
+ case REG_SD_FIFO: /* Read/Write FIFO */
1075
+ sdbus_write_data(&s->sdbus, value & 0xff);
1076
+ sdbus_write_data(&s->sdbus, (value >> 8) & 0xff);
1077
+ sdbus_write_data(&s->sdbus, (value >> 16) & 0xff);
1078
+ sdbus_write_data(&s->sdbus, (value >> 24) & 0xff);
1079
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
1080
+ allwinner_sdhost_auto_stop(s);
1081
+ allwinner_sdhost_update_irq(s);
1082
+ break;
1083
+ case REG_SD_RES_CRC: /* Response CRC from card/eMMC */
1084
+ case REG_SD_DATA7_CRC: /* CRC Data 7 from card/eMMC */
1085
+ case REG_SD_DATA6_CRC: /* CRC Data 6 from card/eMMC */
1086
+ case REG_SD_DATA5_CRC: /* CRC Data 5 from card/eMMC */
1087
+ case REG_SD_DATA4_CRC: /* CRC Data 4 from card/eMMC */
1088
+ case REG_SD_DATA3_CRC: /* CRC Data 3 from card/eMMC */
1089
+ case REG_SD_DATA2_CRC: /* CRC Data 2 from card/eMMC */
1090
+ case REG_SD_DATA1_CRC: /* CRC Data 1 from card/eMMC */
1091
+ case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */
1092
+ case REG_SD_CRC_STA: /* CRC status from card/eMMC in write operation */
1093
+ break;
1094
+ default:
1095
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
1096
+ HWADDR_PRIx"\n", __func__, offset);
1097
+ break;
1098
+ }
1099
+}
1100
+
1101
+static const MemoryRegionOps allwinner_sdhost_ops = {
1102
+ .read = allwinner_sdhost_read,
1103
+ .write = allwinner_sdhost_write,
1104
+ .endianness = DEVICE_NATIVE_ENDIAN,
1105
+ .valid = {
1106
+ .min_access_size = 4,
1107
+ .max_access_size = 4,
1108
+ },
1109
+ .impl.min_access_size = 4,
1110
+};
1111
+
1112
+static const VMStateDescription vmstate_allwinner_sdhost = {
1113
+ .name = "allwinner-sdhost",
1114
+ .version_id = 1,
1115
+ .minimum_version_id = 1,
1116
+ .fields = (VMStateField[]) {
1117
+ VMSTATE_UINT32(global_ctl, AwSdHostState),
1118
+ VMSTATE_UINT32(clock_ctl, AwSdHostState),
1119
+ VMSTATE_UINT32(timeout, AwSdHostState),
1120
+ VMSTATE_UINT32(bus_width, AwSdHostState),
1121
+ VMSTATE_UINT32(block_size, AwSdHostState),
1122
+ VMSTATE_UINT32(byte_count, AwSdHostState),
1123
+ VMSTATE_UINT32(transfer_cnt, AwSdHostState),
1124
+ VMSTATE_UINT32(command, AwSdHostState),
1125
+ VMSTATE_UINT32(command_arg, AwSdHostState),
1126
+ VMSTATE_UINT32_ARRAY(response, AwSdHostState, 4),
1127
+ VMSTATE_UINT32(irq_mask, AwSdHostState),
1128
+ VMSTATE_UINT32(irq_status, AwSdHostState),
1129
+ VMSTATE_UINT32(status, AwSdHostState),
1130
+ VMSTATE_UINT32(fifo_wlevel, AwSdHostState),
1131
+ VMSTATE_UINT32(fifo_func_sel, AwSdHostState),
1132
+ VMSTATE_UINT32(debug_enable, AwSdHostState),
1133
+ VMSTATE_UINT32(auto12_arg, AwSdHostState),
1134
+ VMSTATE_UINT32(newtiming_set, AwSdHostState),
1135
+ VMSTATE_UINT32(newtiming_debug, AwSdHostState),
1136
+ VMSTATE_UINT32(hardware_rst, AwSdHostState),
1137
+ VMSTATE_UINT32(dmac, AwSdHostState),
1138
+ VMSTATE_UINT32(desc_base, AwSdHostState),
1139
+ VMSTATE_UINT32(dmac_status, AwSdHostState),
1140
+ VMSTATE_UINT32(dmac_irq, AwSdHostState),
1141
+ VMSTATE_UINT32(card_threshold, AwSdHostState),
1142
+ VMSTATE_UINT32(startbit_detect, AwSdHostState),
1143
+ VMSTATE_UINT32(response_crc, AwSdHostState),
1144
+ VMSTATE_UINT32_ARRAY(data_crc, AwSdHostState, 8),
1145
+ VMSTATE_UINT32(status_crc, AwSdHostState),
1146
+ VMSTATE_END_OF_LIST()
1147
+ }
1148
+};
1149
+
1150
+static void allwinner_sdhost_init(Object *obj)
1151
+{
1152
+ AwSdHostState *s = AW_SDHOST(obj);
1153
+
1154
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
1155
+ TYPE_AW_SDHOST_BUS, DEVICE(s), "sd-bus");
1156
+
1157
+ memory_region_init_io(&s->iomem, obj, &allwinner_sdhost_ops, s,
1158
+ TYPE_AW_SDHOST, 4 * KiB);
1159
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
1160
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
1161
+}
1162
+
1163
+static void allwinner_sdhost_reset(DeviceState *dev)
1164
+{
1165
+ AwSdHostState *s = AW_SDHOST(dev);
1166
+
1167
+ s->global_ctl = REG_SD_GCTL_RST;
1168
+ s->clock_ctl = REG_SD_CKCR_RST;
1169
+ s->timeout = REG_SD_TMOR_RST;
1170
+ s->bus_width = REG_SD_BWDR_RST;
1171
+ s->block_size = REG_SD_BKSR_RST;
1172
+ s->byte_count = REG_SD_BYCR_RST;
1173
+ s->transfer_cnt = 0;
1174
+
1175
+ s->command = REG_SD_CMDR_RST;
1176
+ s->command_arg = REG_SD_CAGR_RST;
1177
+
1178
+ for (int i = 0; i < ARRAY_SIZE(s->response); i++) {
1179
+ s->response[i] = REG_SD_RESP_RST;
1180
+ }
1181
+
1182
+ s->irq_mask = REG_SD_IMKR_RST;
1183
+ s->irq_status = REG_SD_RISR_RST;
1184
+ s->status = REG_SD_STAR_RST;
1185
+
1186
+ s->fifo_wlevel = REG_SD_FWLR_RST;
1187
+ s->fifo_func_sel = REG_SD_FUNS_RST;
1188
+ s->debug_enable = REG_SD_DBGC_RST;
1189
+ s->auto12_arg = REG_SD_A12A_RST;
1190
+ s->newtiming_set = REG_SD_NTSR_RST;
1191
+ s->newtiming_debug = REG_SD_SDBG_RST;
1192
+ s->hardware_rst = REG_SD_HWRST_RST;
1193
+ s->dmac = REG_SD_DMAC_RST;
1194
+ s->desc_base = REG_SD_DLBA_RST;
1195
+ s->dmac_status = REG_SD_IDST_RST;
1196
+ s->dmac_irq = REG_SD_IDIE_RST;
1197
+ s->card_threshold = REG_SD_THLDC_RST;
1198
+ s->startbit_detect = REG_SD_DSBD_RST;
1199
+ s->response_crc = REG_SD_RES_CRC_RST;
1200
+
1201
+ for (int i = 0; i < ARRAY_SIZE(s->data_crc); i++) {
1202
+ s->data_crc[i] = REG_SD_DATA_CRC_RST;
1203
+ }
1204
+
1205
+ s->status_crc = REG_SD_CRC_STA_RST;
1206
+}
1207
+
1208
+static void allwinner_sdhost_bus_class_init(ObjectClass *klass, void *data)
1209
+{
1210
+ SDBusClass *sbc = SD_BUS_CLASS(klass);
1211
+
1212
+ sbc->set_inserted = allwinner_sdhost_set_inserted;
1213
+}
1214
+
1215
+static void allwinner_sdhost_class_init(ObjectClass *klass, void *data)
1216
+{
1217
+ DeviceClass *dc = DEVICE_CLASS(klass);
1218
+
1219
+ dc->reset = allwinner_sdhost_reset;
1220
+ dc->vmsd = &vmstate_allwinner_sdhost;
1221
+}
1222
+
1223
+static void allwinner_sdhost_sun4i_class_init(ObjectClass *klass, void *data)
1224
+{
1225
+ AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
1226
+ sc->max_desc_size = 8 * KiB;
1227
+}
1228
+
1229
+static void allwinner_sdhost_sun5i_class_init(ObjectClass *klass, void *data)
1230
+{
1231
+ AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
1232
+ sc->max_desc_size = 64 * KiB;
1233
+}
1234
+
1235
+static TypeInfo allwinner_sdhost_info = {
1236
+ .name = TYPE_AW_SDHOST,
1237
+ .parent = TYPE_SYS_BUS_DEVICE,
1238
+ .instance_init = allwinner_sdhost_init,
1239
+ .instance_size = sizeof(AwSdHostState),
1240
+ .class_init = allwinner_sdhost_class_init,
1241
+ .class_size = sizeof(AwSdHostClass),
1242
+ .abstract = true,
1243
+};
1244
+
1245
+static const TypeInfo allwinner_sdhost_sun4i_info = {
1246
+ .name = TYPE_AW_SDHOST_SUN4I,
1247
+ .parent = TYPE_AW_SDHOST,
1248
+ .class_init = allwinner_sdhost_sun4i_class_init,
1249
+};
1250
+
1251
+static const TypeInfo allwinner_sdhost_sun5i_info = {
1252
+ .name = TYPE_AW_SDHOST_SUN5I,
1253
+ .parent = TYPE_AW_SDHOST,
1254
+ .class_init = allwinner_sdhost_sun5i_class_init,
1255
+};
1256
+
1257
+static const TypeInfo allwinner_sdhost_bus_info = {
1258
+ .name = TYPE_AW_SDHOST_BUS,
1259
+ .parent = TYPE_SD_BUS,
1260
+ .instance_size = sizeof(SDBus),
1261
+ .class_init = allwinner_sdhost_bus_class_init,
1262
+};
1263
+
1264
+static void allwinner_sdhost_register_types(void)
1265
+{
1266
+ type_register_static(&allwinner_sdhost_info);
1267
+ type_register_static(&allwinner_sdhost_sun4i_info);
1268
+ type_register_static(&allwinner_sdhost_sun5i_info);
1269
+ type_register_static(&allwinner_sdhost_bus_info);
1270
+}
1271
+
1272
+type_init(allwinner_sdhost_register_types)
1273
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
1274
index XXXXXXX..XXXXXXX 100644
1275
--- a/hw/arm/Kconfig
1276
+++ b/hw/arm/Kconfig
1277
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
1278
select UNIMP
1279
select USB_OHCI
1280
select USB_EHCI_SYSBUS
1281
+ select SD
1282
1283
config RASPI
1284
bool
1285
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
1286
index XXXXXXX..XXXXXXX 100644
1287
--- a/hw/sd/trace-events
1288
+++ b/hw/sd/trace-events
1289
@@ -XXX,XX +XXX,XX @@
1290
# See docs/devel/tracing.txt for syntax documentation.
1291
1292
+# allwinner-sdhost.c
1293
+allwinner_sdhost_set_inserted(bool inserted) "inserted %u"
1294
+allwinner_sdhost_process_desc(uint64_t desc_addr, uint32_t desc_size, bool is_write, uint32_t max_bytes) "desc_addr 0x%" PRIx64 " desc_size %" PRIu32 " is_write %u max_bytes %" PRIu32
1295
+allwinner_sdhost_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
1296
+allwinner_sdhost_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
1297
+allwinner_sdhost_update_irq(uint32_t irq) "IRQ bits 0x%" PRIx32
1298
+
1299
# bcm2835_sdhost.c
1300
bcm2835_sdhost_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
1301
bcm2835_sdhost_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
1302
--
172
--
1303
2.20.1
173
2.20.1
1304
174
1305
175
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Peter Collingbourne <pcc@google.com>
2
2
3
Restructure the finalize_gic_version with switch cases and
3
MTE3 introduces an asymmetric tag checking mode, in which loads are
4
clearly separate the following cases:
4
checked synchronously and stores are checked asynchronously. Add
5
support for it.
5
6
6
- KVM mode / in-kernel irqchip
7
Signed-off-by: Peter Collingbourne <pcc@google.com>
7
- KVM mode / userspace irqchip
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
- TCG mode
9
Message-id: 20210616195614.11785-1-pcc@google.com
9
10
[PMM: Add line to emulation.rst]
10
In KVM mode / in-kernel irqchip , we explictly check whether
11
the chosen version is supported by the host. If the end-user
12
explicitly sets v2/v3 and this is not supported by the host,
13
then the user gets an explicit error message. Note that for
14
old kernels where the CREATE_DEVICE ioctl doesn't exist then
15
we will now fail if the user specifically asked for gicv2,
16
where previously we (probably) would have succeeded.
17
18
In KVM mode / userspace irqchip we immediatly output an error
19
in case the end-user explicitly selected v3. Also we warn the
20
end-user about the unexpected usage of gic-version=host in
21
that case as only userspace GICv2 is supported.
22
23
Signed-off-by: Eric Auger <eric.auger@redhat.com>
24
Reviewed-by: Andrew Jones <drjones@redhat.com>
25
Message-id: 20200311131618.7187-6-eric.auger@redhat.com
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
12
---
28
hw/arm/virt.c | 88 +++++++++++++++++++++++++++++++++++++++------------
13
docs/system/arm/emulation.rst | 1 +
29
1 file changed, 67 insertions(+), 21 deletions(-)
14
target/arm/cpu64.c | 2 +-
15
target/arm/mte_helper.c | 82 ++++++++++++++++++++++-------------
16
3 files changed, 53 insertions(+), 32 deletions(-)
30
17
31
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
18
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
32
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/virt.c
20
--- a/docs/system/arm/emulation.rst
34
+++ b/hw/arm/virt.c
21
+++ b/docs/system/arm/emulation.rst
35
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
22
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
36
*/
23
- FEAT_LSE (Large System Extensions)
37
static void finalize_gic_version(VirtMachineState *vms)
24
- FEAT_MTE (Memory Tagging Extension)
38
{
25
- FEAT_MTE2 (Memory Tagging Extension)
39
- if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
26
+- FEAT_MTE3 (MTE Asymmetric Fault Handling)
40
- vms->gic_version == VIRT_GIC_VERSION_MAX) {
27
- FEAT_PAN (Privileged access never)
41
- if (!kvm_enabled()) {
28
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
42
- if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
29
- FEAT_PAuth (Pointer authentication)
43
- error_report("gic-version=host requires KVM");
30
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
44
- exit(1);
31
index XXXXXXX..XXXXXXX 100644
45
- } else {
32
--- a/target/arm/cpu64.c
46
- /* "max": currently means 3 for TCG */
33
+++ b/target/arm/cpu64.c
47
- vms->gic_version = VIRT_GIC_VERSION_3;
34
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
48
- }
35
* during realize if the board provides no tag memory, much like
49
- } else {
36
* we do for EL2 with the virtualization=on property.
50
- int probe_bitmap = kvm_arm_vgic_probe();
37
*/
51
+ if (kvm_enabled()) {
38
- t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2);
52
+ int probe_bitmap;
39
+ t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3);
53
40
cpu->isar.id_aa64pfr1 = t;
54
- if (!probe_bitmap) {
41
55
+ if (!kvm_irqchip_in_kernel()) {
42
t = cpu->isar.id_aa64mmfr0;
56
+ switch (vms->gic_version) {
43
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
57
+ case VIRT_GIC_VERSION_HOST:
44
index XXXXXXX..XXXXXXX 100644
58
+ warn_report(
45
--- a/target/arm/mte_helper.c
59
+ "gic-version=host not relevant with kernel-irqchip=off "
46
+++ b/target/arm/mte_helper.c
60
+ "as only userspace GICv2 is supported. Using v2 ...");
47
@@ -XXX,XX +XXX,XX @@ void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val)
61
+ return;
62
+ case VIRT_GIC_VERSION_MAX:
63
+ case VIRT_GIC_VERSION_NOSEL:
64
+ vms->gic_version = VIRT_GIC_VERSION_2;
65
+ return;
66
+ case VIRT_GIC_VERSION_2:
67
+ return;
68
+ case VIRT_GIC_VERSION_3:
69
error_report(
70
- "Unable to determine GIC version supported by host");
71
+ "gic-version=3 is not supported with kernel-irqchip=off");
72
exit(1);
73
- } else {
74
- if (probe_bitmap & KVM_ARM_VGIC_V3) {
75
- vms->gic_version = VIRT_GIC_VERSION_3;
76
- } else {
77
- vms->gic_version = VIRT_GIC_VERSION_2;
78
- }
79
}
80
}
81
- } else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
82
+
83
+ probe_bitmap = kvm_arm_vgic_probe();
84
+ if (!probe_bitmap) {
85
+ error_report("Unable to determine GIC version supported by host");
86
+ exit(1);
87
+ }
88
+
89
+ switch (vms->gic_version) {
90
+ case VIRT_GIC_VERSION_HOST:
91
+ case VIRT_GIC_VERSION_MAX:
92
+ if (probe_bitmap & KVM_ARM_VGIC_V3) {
93
+ vms->gic_version = VIRT_GIC_VERSION_3;
94
+ } else {
95
+ vms->gic_version = VIRT_GIC_VERSION_2;
96
+ }
97
+ return;
98
+ case VIRT_GIC_VERSION_NOSEL:
99
+ vms->gic_version = VIRT_GIC_VERSION_2;
100
+ break;
101
+ case VIRT_GIC_VERSION_2:
102
+ case VIRT_GIC_VERSION_3:
103
+ break;
104
+ }
105
+
106
+ /* Check chosen version is effectively supported by the host */
107
+ if (vms->gic_version == VIRT_GIC_VERSION_2 &&
108
+ !(probe_bitmap & KVM_ARM_VGIC_V2)) {
109
+ error_report("host does not support in-kernel GICv2 emulation");
110
+ exit(1);
111
+ } else if (vms->gic_version == VIRT_GIC_VERSION_3 &&
112
+ !(probe_bitmap & KVM_ARM_VGIC_V3)) {
113
+ error_report("host does not support in-kernel GICv3 emulation");
114
+ exit(1);
115
+ }
116
+ return;
117
+ }
118
+
119
+ /* TCG mode */
120
+ switch (vms->gic_version) {
121
+ case VIRT_GIC_VERSION_NOSEL:
122
vms->gic_version = VIRT_GIC_VERSION_2;
123
+ break;
124
+ case VIRT_GIC_VERSION_MAX:
125
+ vms->gic_version = VIRT_GIC_VERSION_3;
126
+ break;
127
+ case VIRT_GIC_VERSION_HOST:
128
+ error_report("gic-version=host requires KVM");
129
+ exit(1);
130
+ case VIRT_GIC_VERSION_2:
131
+ case VIRT_GIC_VERSION_3:
132
+ break;
133
}
48
}
134
}
49
}
135
50
51
+static void mte_sync_check_fail(CPUARMState *env, uint32_t desc,
52
+ uint64_t dirty_ptr, uintptr_t ra)
53
+{
54
+ int is_write, syn;
55
+
56
+ env->exception.vaddress = dirty_ptr;
57
+
58
+ is_write = FIELD_EX32(desc, MTEDESC, WRITE);
59
+ syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0, is_write,
60
+ 0x11);
61
+ raise_exception_ra(env, EXCP_DATA_ABORT, syn, exception_target_el(env), ra);
62
+ g_assert_not_reached();
63
+}
64
+
65
+static void mte_async_check_fail(CPUARMState *env, uint64_t dirty_ptr,
66
+ uintptr_t ra, ARMMMUIdx arm_mmu_idx, int el)
67
+{
68
+ int select;
69
+
70
+ if (regime_has_2_ranges(arm_mmu_idx)) {
71
+ select = extract64(dirty_ptr, 55, 1);
72
+ } else {
73
+ select = 0;
74
+ }
75
+ env->cp15.tfsr_el[el] |= 1 << select;
76
+#ifdef CONFIG_USER_ONLY
77
+ /*
78
+ * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
79
+ * which then sends a SIGSEGV when the thread is next scheduled.
80
+ * This cpu will return to the main loop at the end of the TB,
81
+ * which is rather sooner than "normal". But the alternative
82
+ * is waiting until the next syscall.
83
+ */
84
+ qemu_cpu_kick(env_cpu(env));
85
+#endif
86
+}
87
+
88
/* Record a tag check failure. */
89
static void mte_check_fail(CPUARMState *env, uint32_t desc,
90
uint64_t dirty_ptr, uintptr_t ra)
91
{
92
int mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
93
ARMMMUIdx arm_mmu_idx = core_to_aa64_mmu_idx(mmu_idx);
94
- int el, reg_el, tcf, select, is_write, syn;
95
+ int el, reg_el, tcf;
96
uint64_t sctlr;
97
98
reg_el = regime_el(env, arm_mmu_idx);
99
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
100
switch (tcf) {
101
case 1:
102
/* Tag check fail causes a synchronous exception. */
103
- env->exception.vaddress = dirty_ptr;
104
-
105
- is_write = FIELD_EX32(desc, MTEDESC, WRITE);
106
- syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0,
107
- is_write, 0x11);
108
- raise_exception_ra(env, EXCP_DATA_ABORT, syn,
109
- exception_target_el(env), ra);
110
- /* noreturn, but fall through to the assert anyway */
111
+ mte_sync_check_fail(env, desc, dirty_ptr, ra);
112
+ break;
113
114
case 0:
115
/*
116
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
117
118
case 2:
119
/* Tag check fail causes asynchronous flag set. */
120
- if (regime_has_2_ranges(arm_mmu_idx)) {
121
- select = extract64(dirty_ptr, 55, 1);
122
- } else {
123
- select = 0;
124
- }
125
- env->cp15.tfsr_el[el] |= 1 << select;
126
-#ifdef CONFIG_USER_ONLY
127
- /*
128
- * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
129
- * which then sends a SIGSEGV when the thread is next scheduled.
130
- * This cpu will return to the main loop at the end of the TB,
131
- * which is rather sooner than "normal". But the alternative
132
- * is waiting until the next syscall.
133
- */
134
- qemu_cpu_kick(env_cpu(env));
135
-#endif
136
+ mte_async_check_fail(env, dirty_ptr, ra, arm_mmu_idx, el);
137
break;
138
139
- default:
140
- /* Case 3: Reserved. */
141
- qemu_log_mask(LOG_GUEST_ERROR,
142
- "Tag check failure with SCTLR_EL%d.TCF%s "
143
- "set to reserved value %d\n",
144
- reg_el, el ? "" : "0", tcf);
145
+ case 3:
146
+ /*
147
+ * Tag check fail causes asynchronous flag set for stores, or
148
+ * a synchronous exception for loads.
149
+ */
150
+ if (FIELD_EX32(desc, MTEDESC, WRITE)) {
151
+ mte_async_check_fail(env, dirty_ptr, ra, arm_mmu_idx, el);
152
+ } else {
153
+ mte_sync_check_fail(env, desc, dirty_ptr, ra);
154
+ }
155
break;
156
}
157
}
136
--
158
--
137
2.20.1
159
2.20.1
138
160
139
161
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
From: Alexandre Iooss <erdnaxe@crans.org>
2
2
3
The Xunlong Orange Pi PC machine is a functional ARM machine
3
This adds the target guide for BBC Micro:bit.
4
based on the Allwinner H3 System-on-Chip. It supports mainline
5
Linux, U-Boot, NetBSD and is covered by acceptance tests.
6
4
7
This commit adds a documentation text file with a description
5
Information is taken from https://wiki.qemu.org/Features/MicroBit
8
of the machine and instructions for the user.
6
and from hw/arm/nrf51_soc.c.
9
7
10
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20200311221854.30370-19-nieklinnenbank@gmail.com
10
Reviewed-by: Joel Stanley <joel@jms.id.au>
13
[PMM: moved file into docs/system/arm to match the reorg
11
Message-id: 20210621075625.540471-1-erdnaxe@crans.org
14
of the arm target part of the docs; tweaked heading to
15
match other boards]
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
13
---
18
MAINTAINERS | 1 +
14
docs/system/arm/nrf.rst | 51 ++++++++++++++++++++++++++++++++++++++
19
docs/system/arm/orangepi.rst | 253 +++++++++++++++++++++++++++++++++++
15
docs/system/target-arm.rst | 1 +
20
docs/system/target-arm.rst | 2 +
16
MAINTAINERS | 1 +
21
3 files changed, 256 insertions(+)
17
3 files changed, 53 insertions(+)
22
create mode 100644 docs/system/arm/orangepi.rst
18
create mode 100644 docs/system/arm/nrf.rst
23
19
24
diff --git a/MAINTAINERS b/MAINTAINERS
20
diff --git a/docs/system/arm/nrf.rst b/docs/system/arm/nrf.rst
25
index XXXXXXX..XXXXXXX 100644
26
--- a/MAINTAINERS
27
+++ b/MAINTAINERS
28
@@ -XXX,XX +XXX,XX @@ S: Maintained
29
F: hw/*/allwinner-h3*
30
F: include/hw/*/allwinner-h3*
31
F: hw/arm/orangepi.c
32
+F: docs/system/orangepi.rst
33
34
ARM PrimeCell and CMSDK devices
35
M: Peter Maydell <peter.maydell@linaro.org>
36
diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
37
new file mode 100644
21
new file mode 100644
38
index XXXXXXX..XXXXXXX
22
index XXXXXXX..XXXXXXX
39
--- /dev/null
23
--- /dev/null
40
+++ b/docs/system/arm/orangepi.rst
24
+++ b/docs/system/arm/nrf.rst
41
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
42
+Orange Pi PC (``orangepi-pc``)
26
+Nordic nRF boards (``microbit``)
43
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27
+================================
44
+
28
+
45
+The Xunlong Orange Pi PC is an Allwinner H3 System on Chip
29
+The `Nordic nRF`_ chips are a family of ARM-based System-on-Chip that
46
+based embedded computer with mainline support in both U-Boot
30
+are designed to be used for low-power and short-range wireless solutions.
47
+and Linux. The board comes with a Quad Core Cortex-A7 @ 1.3GHz,
31
+
48
+1GiB RAM, 100Mbit ethernet, USB, SD/MMC, USB, HDMI and
32
+.. _Nordic nRF: https://www.nordicsemi.com/Products
49
+various other I/O.
33
+
34
+The nRF51 series is the first series for short range wireless applications.
35
+It is superseded by the nRF52 series.
36
+The following machines are based on this chip :
37
+
38
+- ``microbit`` BBC micro:bit board with nRF51822 SoC
39
+
40
+There are other series such as nRF52, nRF53 and nRF91 which are currently not
41
+supported by QEMU.
50
+
42
+
51
+Supported devices
43
+Supported devices
52
+"""""""""""""""""
44
+-----------------
53
+
45
+
54
+The Orange Pi PC machine supports the following devices:
46
+ * ARM Cortex-M0 (ARMv6-M)
47
+ * Serial ports (UART)
48
+ * Clock controller
49
+ * Timers
50
+ * Random Number Generator (RNG)
51
+ * GPIO controller
52
+ * NVMC
53
+ * SWI
55
+
54
+
56
+ * SMP (Quad Core Cortex-A7)
55
+Missing devices
57
+ * Generic Interrupt Controller configuration
56
+---------------
58
+ * SRAM mappings
59
+ * SDRAM controller
60
+ * Real Time Clock
61
+ * Timer device (re-used from Allwinner A10)
62
+ * UART
63
+ * SD/MMC storage controller
64
+ * EMAC ethernet
65
+ * USB 2.0 interfaces
66
+ * Clock Control Unit
67
+ * System Control module
68
+ * Security Identifier device
69
+
57
+
70
+Limitations
58
+ * Watchdog
71
+"""""""""""
59
+ * Real-Time Clock (RTC) controller
72
+
60
+ * TWI (i2c)
73
+Currently, Orange Pi PC does *not* support the following features:
61
+ * SPI controller
74
+
62
+ * Analog to Digital Converter (ADC)
75
+- Graphical output via HDMI, GPU and/or the Display Engine
63
+ * Quadrature decoder
76
+- Audio output
64
+ * Radio
77
+- Hardware Watchdog
78
+
79
+Also see the 'unimplemented' array in the Allwinner H3 SoC module
80
+for a complete list of unimplemented I/O devices: ``./hw/arm/allwinner-h3.c``
81
+
65
+
82
+Boot options
66
+Boot options
83
+""""""""""""
67
+------------
84
+
68
+
85
+The Orange Pi PC machine can start using the standard -kernel functionality
69
+The Micro:bit machine can be started using the ``-device`` option to load a
86
+for loading a Linux kernel or ELF executable. Additionally, the Orange Pi PC
70
+firmware in `ihex format`_. Example:
87
+machine can also emulate the BootROM which is present on an actual Allwinner H3
88
+based SoC, which loads the bootloader from a SD card, specified via the -sd argument
89
+to qemu-system-arm.
90
+
71
+
91
+Machine-specific options
72
+.. _ihex format: https://en.wikipedia.org/wiki/Intel_HEX
92
+""""""""""""""""""""""""
93
+
94
+The following machine-specific options are supported:
95
+
96
+- allwinner-rtc.base-year=YYYY
97
+
98
+ The Allwinner RTC device is automatically created by the Orange Pi PC machine
99
+ and uses a default base year value which can be overridden using the 'base-year' property.
100
+ The base year is the actual represented year when the RTC year value is zero.
101
+ This option can be used in case the target operating system driver uses a different
102
+ base year value. The minimum value for the base year is 1900.
103
+
104
+- allwinner-sid.identifier=abcd1122-a000-b000-c000-12345678ffff
105
+
106
+ The Security Identifier value can be read by the guest.
107
+ For example, U-Boot uses it to determine a unique MAC address.
108
+
109
+The above machine-specific options can be specified in qemu-system-arm
110
+via the '-global' argument, for example:
111
+
73
+
112
+.. code-block:: bash
74
+.. code-block:: bash
113
+
75
+
114
+ $ qemu-system-arm -M orangepi-pc -sd mycard.img \
76
+ $ qemu-system-arm -M microbit -device loader,file=test.hex
115
+ -global allwinner-rtc.base-year=2000
116
+
117
+Running mainline Linux
118
+""""""""""""""""""""""
119
+
120
+Mainline Linux kernels from 4.19 up to latest master are known to work.
121
+To build a Linux mainline kernel that can be booted by the Orange Pi PC machine,
122
+simply configure the kernel using the sunxi_defconfig configuration:
123
+
124
+.. code-block:: bash
125
+
126
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make mrproper
127
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make sunxi_defconfig
128
+
129
+To be able to use USB storage, you need to manually enable the corresponding
130
+configuration item. Start the kconfig configuration tool:
131
+
132
+.. code-block:: bash
133
+
134
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make menuconfig
135
+
136
+Navigate to the following item, enable it and save your configuration:
137
+
138
+ Device Drivers > USB support > USB Mass Storage support
139
+
140
+Build the Linux kernel with:
141
+
142
+.. code-block:: bash
143
+
144
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make
145
+
146
+To boot the newly build linux kernel in QEMU with the Orange Pi PC machine, use:
147
+
148
+.. code-block:: bash
149
+
150
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
151
+ -kernel /path/to/linux/arch/arm/boot/zImage \
152
+ -append 'console=ttyS0,115200' \
153
+ -dtb /path/to/linux/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dtb
154
+
155
+Orange Pi PC images
156
+"""""""""""""""""""
157
+
158
+Note that the mainline kernel does not have a root filesystem. You may provide it
159
+with an official Orange Pi PC image from the official website:
160
+
161
+ http://www.orangepi.org/downloadresources/
162
+
163
+Another possibility is to run an Armbian image for Orange Pi PC which
164
+can be downloaded from:
165
+
166
+ https://www.armbian.com/orange-pi-pc/
167
+
168
+Alternatively, you can also choose to build you own image with buildroot
169
+using the orangepi_pc_defconfig. Also see https://buildroot.org for more information.
170
+
171
+You can choose to attach the selected image either as an SD card or as USB mass storage.
172
+For example, to boot using the Orange Pi PC Debian image on SD card, simply add the -sd
173
+argument and provide the proper root= kernel parameter:
174
+
175
+.. code-block:: bash
176
+
177
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
178
+ -kernel /path/to/linux/arch/arm/boot/zImage \
179
+ -append 'console=ttyS0,115200 root=/dev/mmcblk0p2' \
180
+ -dtb /path/to/linux/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dtb \
181
+ -sd OrangePi_pc_debian_stretch_server_linux5.3.5_v1.0.img
182
+
183
+To attach the image as an USB mass storage device to the machine,
184
+simply append to the command:
185
+
186
+.. code-block:: bash
187
+
188
+ -drive if=none,id=stick,file=myimage.img \
189
+ -device usb-storage,bus=usb-bus.0,drive=stick
190
+
191
+Instead of providing a custom Linux kernel via the -kernel command you may also
192
+choose to let the Orange Pi PC machine load the bootloader from SD card, just like
193
+a real board would do using the BootROM. Simply pass the selected image via the -sd
194
+argument and remove the -kernel, -append, -dbt and -initrd arguments:
195
+
196
+.. code-block:: bash
197
+
198
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
199
+ -sd Armbian_19.11.3_Orangepipc_buster_current_5.3.9.img
200
+
201
+Note that both the official Orange Pi PC images and Armbian images start
202
+a lot of userland programs via systemd. Depending on the host hardware and OS,
203
+they may be slow to emulate, especially due to emulating the 4 cores.
204
+To help reduce the performance slow down due to emulating the 4 cores, you can
205
+give the following kernel parameters via U-Boot (or via -append):
206
+
207
+.. code-block:: bash
208
+
209
+ => setenv extraargs 'systemd.default_timeout_start_sec=9000 loglevel=7 nosmp console=ttyS0,115200'
210
+
211
+Running U-Boot
212
+""""""""""""""
213
+
214
+U-Boot mainline can be build and configured using the orangepi_pc_defconfig
215
+using similar commands as describe above for Linux. Note that it is recommended
216
+for development/testing to select the following configuration setting in U-Boot:
217
+
218
+ Device Tree Control > Provider for DTB for DT Control > Embedded DTB
219
+
220
+To start U-Boot using the Orange Pi PC machine, provide the
221
+u-boot binary to the -kernel argument:
222
+
223
+.. code-block:: bash
224
+
225
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
226
+ -kernel /path/to/uboot/u-boot -sd disk.img
227
+
228
+Use the following U-boot commands to load and boot a Linux kernel from SD card:
229
+
230
+.. code-block:: bash
231
+
232
+ => setenv bootargs console=ttyS0,115200
233
+ => ext2load mmc 0 0x42000000 zImage
234
+ => ext2load mmc 0 0x43000000 sun8i-h3-orangepi-pc.dtb
235
+ => bootz 0x42000000 - 0x43000000
236
+
237
+Running NetBSD
238
+""""""""""""""
239
+
240
+The NetBSD operating system also includes support for Allwinner H3 based boards,
241
+including the Orange Pi PC. NetBSD 9.0 is known to work best for the Orange Pi PC
242
+board and provides a fully working system with serial console, networking and storage.
243
+For the Orange Pi PC machine, get the 'evbarm-earmv7hf' based image from:
244
+
245
+ https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/evbarm-earmv7hf/binary/gzimg/armv7.img.gz
246
+
247
+The image requires manually installing U-Boot in the image. Build U-Boot with
248
+the orangepi_pc_defconfig configuration as described in the previous section.
249
+Next, unzip the NetBSD image and write the U-Boot binary including SPL using:
250
+
251
+.. code-block:: bash
252
+
253
+ $ gunzip armv7.img.gz
254
+ $ dd if=/path/to/u-boot-sunxi-with-spl.bin of=armv7.img bs=1024 seek=8 conv=notrunc
255
+
256
+Finally, before starting the machine the SD image must be extended such
257
+that the NetBSD kernel will not conclude the NetBSD partition is larger than
258
+the emulated SD card:
259
+
260
+.. code-block:: bash
261
+
262
+ $ dd if=/dev/zero bs=1M count=64 >> armv7.img
263
+
264
+Start the machine using the following command:
265
+
266
+.. code-block:: bash
267
+
268
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
269
+ -sd armv7.img -global allwinner-rtc.base-year=2000
270
+
271
+At the U-Boot stage, interrupt the automatic boot process by pressing a key
272
+and set the following environment variables before booting:
273
+
274
+.. code-block:: bash
275
+
276
+ => setenv bootargs root=ld0a
277
+ => setenv kernel netbsd-GENERIC.ub
278
+ => setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb
279
+ => setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; fdt addr ${fdt_addr_r}; bootm ${kernel_addr_r} - ${fdt_addr_r}'
280
+
281
+Optionally you may save the environment variables to SD card with 'saveenv'.
282
+To continue booting simply give the 'boot' command and NetBSD boots.
283
+
284
+Orange Pi PC acceptance tests
285
+"""""""""""""""""""""""""""""
286
+
287
+The Orange Pi PC machine has several acceptance tests included.
288
+To run the whole set of tests, build QEMU from source and simply
289
+provide the following command:
290
+
291
+.. code-block:: bash
292
+
293
+ $ AVOCADO_ALLOW_LARGE_STORAGE=yes avocado --show=app,console run \
294
+ -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
295
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
77
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
296
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
297
--- a/docs/system/target-arm.rst
79
--- a/docs/system/target-arm.rst
298
+++ b/docs/system/target-arm.rst
80
+++ b/docs/system/target-arm.rst
299
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
81
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
300
``qemu-system-aarch64 --machine help``.
82
arm/digic
301
302
.. toctree::
303
+ :maxdepth: 1
304
305
arm/integratorcp
306
arm/versatile
307
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
308
arm/stellaris
309
arm/musicpal
83
arm/musicpal
310
arm/sx1
84
arm/gumstix
311
+ arm/orangepi
85
+ arm/nrf
312
86
arm/nseries
313
Arm CPU features
87
arm/nuvoton
314
================
88
arm/orangepi
89
diff --git a/MAINTAINERS b/MAINTAINERS
90
index XXXXXXX..XXXXXXX 100644
91
--- a/MAINTAINERS
92
+++ b/MAINTAINERS
93
@@ -XXX,XX +XXX,XX @@ F: hw/*/microbit*.c
94
F: include/hw/*/nrf51*.h
95
F: include/hw/*/microbit*.h
96
F: tests/qtest/microbit-test.c
97
+F: docs/system/arm/nrf.rst
98
99
AVR Machines
100
-------------
315
--
101
--
316
2.20.1
102
2.20.1
317
103
318
104
diff view generated by jsdifflib