1
Second pull request of the week; mostly RTH's support for some
1
Another arm pullreq; nothing particularly exciting here.
2
new-in-v8.1/v8.3 instructions, and my v8M board model.
3
2
4
thanks
5
-- PMM
3
-- PMM
6
4
7
The following changes since commit 427cbc7e4136a061628cb4315cc8182ea36d772f:
8
5
9
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2018-03-01 18:46:41 +0000)
6
The following changes since commit e27d5b488ef08408691bfed61f34ee2858136287:
7
8
Merge remote-tracking branch 'remotes/juanquintela/tags/pull-migration-pull-request' into staging (2020-02-28 14:02:31 +0000)
10
9
11
are available in the Git repository at:
10
are available in the Git repository at:
12
11
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180302
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200228
14
13
15
for you to fetch changes up to e66a67bf28e1b4fce2e3d72a2610dbd48d9d3078:
14
for you to fetch changes up to 1904f9b5f1d94fe12fe021db6b504c87d684f6db:
16
15
17
target/arm: Enable ARM_FEATURE_V8_FCMA (2018-03-02 11:03:45 +0000)
16
hw/intc/arm_gic_kvm: Don't assume kernel can provide a GICv2 (2020-02-28 16:14:57 +0000)
18
17
19
----------------------------------------------------------------
18
----------------------------------------------------------------
20
target-arm queue:
19
target-arm queue:
21
* implement FCMA and RDM v8.1 and v8.3 instructions
20
* hw/arm: Use TYPE_PL011 to create serial port
22
* enable Cortex-M33 v8M core, and provide new mps2-an505 board model
21
* target/arm: Set ID_MMFR4.HPDS for aarch64_max_initfn
23
that uses it
22
* hw/arm/integratorcp: Map the audio codec controller
24
* decodetree: Propagate return value from translate subroutines
23
* GICv2: Correctly implement the limited number of priority bits
25
* xlnx-zynqmp: Implement the RTC device
24
* target/arm: refactoring of VFP related feature checks and decode
25
* xilinx_zynq: Fix USB port instantiation
26
* acceptance tests for n800, n810, integratorcp
27
* Implement v8.3-RCPC, v8.4-RCPC, v8.3-CCIDX
28
* arm_gic_kvm: Don't assume kernel can provide a GICv2
29
(provide better error message for user error)
26
30
27
----------------------------------------------------------------
31
----------------------------------------------------------------
28
Alistair Francis (3):
32
Gavin Shan (1):
29
xlnx-zynqmp-rtc: Initial commit
33
hw/arm: Use TYPE_PL011 to create serial port
30
xlnx-zynqmp-rtc: Add basic time support
31
xlnx-zynqmp: Connect the RTC device
32
34
33
Peter Maydell (19):
35
Guenter Roeck (2):
34
loader: Add new load_ramdisk_as()
36
hw/arm/xilinx_zynq: Fix USB port instantiation
35
hw/arm/boot: Honour CPU's address space for image loads
37
hw/usb/hcd-ehci-sysbus: Remove obsolete xlnx, ps7-usb class
36
hw/arm/armv7m: Honour CPU's address space for image loads
38
37
target/arm: Define an IDAU interface
39
Peter Maydell (5):
38
armv7m: Forward idau property to CPU object
40
target/arm: Fix wrong use of FIELD_EX32 on ID_AA64DFR0
39
target/arm: Define init-svtor property for the reset secure VTOR value
41
target/arm: Implement v8.3-RCPC
40
armv7m: Forward init-svtor property to CPU object
42
target/arm: Implement v8.4-RCPC
41
target/arm: Add Cortex-M33
43
target/arm: Implement ARMv8.3-CCIDX
42
hw/misc/unimp: Move struct to header file
44
hw/intc/arm_gic_kvm: Don't assume kernel can provide a GICv2
43
include/hw/or-irq.h: Add missing include guard
45
44
qdev: Add new qdev_init_gpio_in_named_with_opaque()
46
Philippe Mathieu-Daudé (3):
45
hw/core/split-irq: Device that splits IRQ lines
47
hw/arm/integratorcp: Map the audio codec controller
46
hw/misc/mps2-fpgaio: FPGA control block for MPS2 AN505
48
tests/acceptance: Extract boot_integratorcp() from test_integratorcp()
47
hw/misc/tz-ppc: Model TrustZone peripheral protection controller
49
tests/acceptance/integratorcp: Verify Tux is displayed on framebuffer
48
hw/misc/iotkit-secctl: Arm IoT Kit security controller initial skeleton
49
hw/misc/iotkit-secctl: Add handling for PPCs
50
hw/misc/iotkit-secctl: Add remaining simple registers
51
hw/arm/iotkit: Model Arm IOT Kit
52
mps2-an505: New board model: MPS2 with AN505 Cortex-M33 FPGA image
53
50
54
Richard Henderson (17):
51
Richard Henderson (17):
55
decodetree: Propagate return value from translate subroutines
52
target/arm: Set ID_MMFR4.HPDS for aarch64_max_initfn
56
target/arm: Add ARM_FEATURE_V8_RDM
53
target/arm: Add isar_feature_aa32_vfp_simd
57
target/arm: Refactor disas_simd_indexed decode
54
target/arm: Rename isar_feature_aa32_fpdp_v2
58
target/arm: Refactor disas_simd_indexed size checks
55
target/arm: Add isar_feature_aa32_{fpsp_v2, fpsp_v3, fpdp_v3}
59
target/arm: Decode aa64 armv8.1 scalar three same extra
56
target/arm: Add isar_feature_aa64_fp_simd, isar_feature_aa32_vfp
60
target/arm: Decode aa64 armv8.1 three same extra
57
target/arm: Perform fpdp_v2 check first
61
target/arm: Decode aa64 armv8.1 scalar/vector x indexed element
58
target/arm: Replace ARM_FEATURE_VFP3 checks with fp{sp, dp}_v3
62
target/arm: Decode aa32 armv8.1 three same
59
target/arm: Add missing checks for fpsp_v2
63
target/arm: Decode aa32 armv8.1 two reg and a scalar
60
target/arm: Replace ARM_FEATURE_VFP4 with isar_feature_aa32_simdfmac
64
target/arm: Enable ARM_FEATURE_V8_RDM
61
target/arm: Remove ARM_FEATURE_VFP check from disas_vfp_insn
65
target/arm: Add ARM_FEATURE_V8_FCMA
62
target/arm: Move VLLDM and VLSTM to vfp.decode
66
target/arm: Decode aa64 armv8.3 fcadd
63
target/arm: Move the vfp decodetree calls next to the base isa
67
target/arm: Decode aa64 armv8.3 fcmla
64
linux-user/arm: Replace ARM_FEATURE_VFP* tests for HWCAP
68
target/arm: Decode aa32 armv8.3 3-same
65
target/arm: Remove ARM_FEATURE_VFP*
69
target/arm: Decode aa32 armv8.3 2-reg-index
66
target/arm: Add formats for some vfp 2 and 3-register insns
70
target/arm: Decode t32 simd 3reg and 2reg_scalar extension
67
target/arm: Split VFM decode
71
target/arm: Enable ARM_FEATURE_V8_FCMA
68
target/arm: Split VMINMAXNM decode
72
69
73
hw/arm/Makefile.objs | 2 +
70
Sai Pavan Boddu (3):
74
hw/core/Makefile.objs | 1 +
71
arm_gic: Mask the un-supported priority bits
75
hw/misc/Makefile.objs | 4 +
72
cpu/a9mpcore: Set number of GIC priority bits to 5
76
hw/timer/Makefile.objs | 1 +
73
cpu/arm11mpcore: Set number of GIC priority bits to 4
77
target/arm/Makefile.objs | 2 +-
78
include/hw/arm/armv7m.h | 5 +
79
include/hw/arm/iotkit.h | 109 ++++++
80
include/hw/arm/xlnx-zynqmp.h | 2 +
81
include/hw/core/split-irq.h | 57 +++
82
include/hw/irq.h | 4 +-
83
include/hw/loader.h | 12 +-
84
include/hw/misc/iotkit-secctl.h | 103 ++++++
85
include/hw/misc/mps2-fpgaio.h | 43 +++
86
include/hw/misc/tz-ppc.h | 101 ++++++
87
include/hw/misc/unimp.h | 10 +
88
include/hw/or-irq.h | 5 +
89
include/hw/qdev-core.h | 30 +-
90
include/hw/timer/xlnx-zynqmp-rtc.h | 86 +++++
91
target/arm/cpu.h | 8 +
92
target/arm/helper.h | 31 ++
93
target/arm/idau.h | 61 ++++
94
hw/arm/armv7m.c | 35 +-
95
hw/arm/boot.c | 119 ++++---
96
hw/arm/iotkit.c | 598 +++++++++++++++++++++++++++++++
97
hw/arm/mps2-tz.c | 503 ++++++++++++++++++++++++++
98
hw/arm/xlnx-zynqmp.c | 14 +
99
hw/core/loader.c | 8 +-
100
hw/core/qdev.c | 8 +-
101
hw/core/split-irq.c | 89 +++++
102
hw/misc/iotkit-secctl.c | 704 +++++++++++++++++++++++++++++++++++++
103
hw/misc/mps2-fpgaio.c | 176 ++++++++++
104
hw/misc/tz-ppc.c | 302 ++++++++++++++++
105
hw/misc/unimp.c | 10 -
106
hw/timer/xlnx-zynqmp-rtc.c | 272 ++++++++++++++
107
linux-user/elfload.c | 2 +
108
target/arm/cpu.c | 66 +++-
109
target/arm/cpu64.c | 2 +
110
target/arm/helper.c | 28 +-
111
target/arm/translate-a64.c | 514 +++++++++++++++++++++------
112
target/arm/translate.c | 275 +++++++++++++--
113
target/arm/vec_helper.c | 429 ++++++++++++++++++++++
114
default-configs/arm-softmmu.mak | 5 +
115
hw/misc/trace-events | 24 ++
116
hw/timer/trace-events | 3 +
117
scripts/decodetree.py | 5 +-
118
45 files changed, 4668 insertions(+), 200 deletions(-)
119
create mode 100644 include/hw/arm/iotkit.h
120
create mode 100644 include/hw/core/split-irq.h
121
create mode 100644 include/hw/misc/iotkit-secctl.h
122
create mode 100644 include/hw/misc/mps2-fpgaio.h
123
create mode 100644 include/hw/misc/tz-ppc.h
124
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
125
create mode 100644 target/arm/idau.h
126
create mode 100644 hw/arm/iotkit.c
127
create mode 100644 hw/arm/mps2-tz.c
128
create mode 100644 hw/core/split-irq.c
129
create mode 100644 hw/misc/iotkit-secctl.c
130
create mode 100644 hw/misc/mps2-fpgaio.c
131
create mode 100644 hw/misc/tz-ppc.c
132
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
133
create mode 100644 target/arm/vec_helper.c
134
74
75
Thomas Huth (2):
76
tests/acceptance: Add a test for the N800 and N810 arm machines
77
tests/acceptance: Add a test for the integratorcp arm machine
78
79
include/hw/intc/arm_gic.h | 2 +
80
include/hw/intc/arm_gic_common.h | 1 +
81
target/arm/cpu.h | 88 +++++-
82
hw/arm/integratorcp.c | 1 +
83
hw/arm/sbsa-ref.c | 3 +-
84
hw/arm/virt.c | 3 +-
85
hw/arm/xilinx_zynq.c | 5 +-
86
hw/arm/xlnx-versal.c | 3 +-
87
hw/cpu/a9mpcore.c | 4 +
88
hw/cpu/arm11mpcore.c | 5 +
89
hw/intc/arm_gic.c | 33 +-
90
hw/intc/arm_gic_common.c | 1 +
91
hw/intc/arm_gic_kvm.c | 9 +
92
hw/intc/armv7m_nvic.c | 20 +-
93
hw/usb/hcd-ehci-sysbus.c | 17 -
94
linux-user/arm/signal.c | 4 +-
95
linux-user/elfload.c | 25 +-
96
target/arm/arch_dump.c | 11 +-
97
target/arm/cpu.c | 44 +--
98
target/arm/cpu64.c | 5 +-
99
target/arm/helper.c | 23 +-
100
target/arm/kvm32.c | 5 -
101
target/arm/kvm64.c | 1 -
102
target/arm/m_helper.c | 11 +-
103
target/arm/machine.c | 5 +-
104
target/arm/translate-a64.c | 114 +++++++
105
target/arm/translate-vfp.inc.c | 448 +++++++++++++++++----------
106
target/arm/translate.c | 122 ++------
107
MAINTAINERS | 2 +
108
hw/arm/Kconfig | 1 +
109
target/arm/vfp-uncond.decode | 12 +-
110
target/arm/vfp.decode | 153 ++++-----
111
tests/acceptance/machine_arm_integratorcp.py | 99 ++++++
112
tests/acceptance/machine_arm_n8x0.py | 49 +++
113
34 files changed, 865 insertions(+), 464 deletions(-)
114
create mode 100644 tests/acceptance/machine_arm_integratorcp.py
115
create mode 100644 tests/acceptance/machine_arm_n8x0.py
116
diff view generated by jsdifflib
1
Define a new board model for the MPS2 with an AN505 FPGA image
1
From: Gavin Shan <gshan@redhat.com>
2
containing a Cortex-M33. Since the FPGA images for TrustZone
3
cores (AN505, and the similar AN519 for Cortex-M23) have a
4
significantly different layout of devices to the non-TrustZone
5
images, we use a new source file rather than shoehorning them
6
into the existing mps2.c.
7
2
3
This uses TYPE_PL011 when creating the serial port so that the code
4
looks cleaner.
5
6
Signed-off-by: Gavin Shan <gshan@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20200224222223.4128-1-gshan@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-20-peter.maydell@linaro.org
11
---
11
---
12
hw/arm/Makefile.objs | 1 +
12
hw/arm/sbsa-ref.c | 3 ++-
13
hw/arm/mps2-tz.c | 503 +++++++++++++++++++++++++++++++++++++++++++++++++++
13
hw/arm/virt.c | 3 ++-
14
2 files changed, 504 insertions(+)
14
hw/arm/xlnx-versal.c | 3 ++-
15
create mode 100644 hw/arm/mps2-tz.c
15
3 files changed, 6 insertions(+), 3 deletions(-)
16
16
17
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/Makefile.objs
19
--- a/hw/arm/sbsa-ref.c
20
+++ b/hw/arm/Makefile.objs
20
+++ b/hw/arm/sbsa-ref.c
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
22
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
23
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
24
obj-$(CONFIG_MPS2) += mps2.o
25
+obj-$(CONFIG_MPS2) += mps2-tz.o
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
27
obj-$(CONFIG_IOTKIT) += iotkit.o
28
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
29
new file mode 100644
30
index XXXXXXX..XXXXXXX
31
--- /dev/null
32
+++ b/hw/arm/mps2-tz.c
33
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
34
+/*
22
#include "hw/pci-host/gpex.h"
35
+ * ARM V2M MPS2 board emulation, trustzone aware FPGA images
23
#include "hw/qdev-properties.h"
36
+ *
24
#include "hw/usb.h"
37
+ * Copyright (c) 2017 Linaro Limited
25
+#include "hw/char/pl011.h"
38
+ * Written by Peter Maydell
26
#include "net/net.h"
39
+ *
27
40
+ * This program is free software; you can redistribute it and/or modify
28
#define RAMLIMIT_GB 8192
41
+ * it under the terms of the GNU General Public License version 2 or
29
@@ -XXX,XX +XXX,XX @@ static void create_uart(const SBSAMachineState *sms, int uart,
42
+ * (at your option) any later version.
30
{
43
+ */
31
hwaddr base = sbsa_ref_memmap[uart].base;
44
+
32
int irq = sbsa_ref_irqmap[uart];
45
+/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
33
- DeviceState *dev = qdev_create(NULL, "pl011");
46
+ * FPGA but is otherwise the same as the 2). Since the CPU itself
34
+ DeviceState *dev = qdev_create(NULL, TYPE_PL011);
47
+ * and most of the devices are in the FPGA, the details of the board
35
SysBusDevice *s = SYS_BUS_DEVICE(dev);
48
+ * as seen by the guest depend significantly on the FPGA image.
36
49
+ * This source file covers the following FPGA images, for TrustZone cores:
37
qdev_prop_set_chr(dev, "chardev", chr);
50
+ * "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
38
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
51
+ *
39
index XXXXXXX..XXXXXXX 100644
52
+ * Links to the TRM for the board itself and to the various Application
40
--- a/hw/arm/virt.c
53
+ * Notes which document the FPGA images can be found here:
41
+++ b/hw/arm/virt.c
54
+ * https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
42
@@ -XXX,XX +XXX,XX @@
55
+ *
43
#include "hw/mem/nvdimm.h"
56
+ * Board TRM:
44
#include "hw/acpi/generic_event_device.h"
57
+ * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
45
#include "hw/virtio/virtio-iommu.h"
58
+ * Application Note AN505:
46
+#include "hw/char/pl011.h"
59
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
47
60
+ *
48
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
61
+ * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
49
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
62
+ * (ARM ECM0601256) for the details of some of the device layout:
50
@@ -XXX,XX +XXX,XX @@ static void create_uart(const VirtMachineState *vms, int uart,
63
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
51
int irq = vms->irqmap[uart];
64
+ */
52
const char compat[] = "arm,pl011\0arm,primecell";
65
+
53
const char clocknames[] = "uartclk\0apb_pclk";
66
+#include "qemu/osdep.h"
54
- DeviceState *dev = qdev_create(NULL, "pl011");
67
+#include "qapi/error.h"
55
+ DeviceState *dev = qdev_create(NULL, TYPE_PL011);
68
+#include "qemu/error-report.h"
56
SysBusDevice *s = SYS_BUS_DEVICE(dev);
69
+#include "hw/arm/arm.h"
57
70
+#include "hw/arm/armv7m.h"
58
qdev_prop_set_chr(dev, "chardev", chr);
71
+#include "hw/or-irq.h"
59
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
72
+#include "hw/boards.h"
60
index XXXXXXX..XXXXXXX 100644
73
+#include "exec/address-spaces.h"
61
--- a/hw/arm/xlnx-versal.c
74
+#include "sysemu/sysemu.h"
62
+++ b/hw/arm/xlnx-versal.c
75
+#include "hw/misc/unimp.h"
63
@@ -XXX,XX +XXX,XX @@
76
+#include "hw/char/cmsdk-apb-uart.h"
64
#include "hw/misc/unimp.h"
77
+#include "hw/timer/cmsdk-apb-timer.h"
65
#include "hw/intc/arm_gicv3_common.h"
78
+#include "hw/misc/mps2-scc.h"
66
#include "hw/arm/xlnx-versal.h"
79
+#include "hw/misc/mps2-fpgaio.h"
67
+#include "hw/char/pl011.h"
80
+#include "hw/arm/iotkit.h"
68
81
+#include "hw/devices.h"
69
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
82
+#include "net/net.h"
70
#define GEM_REVISION 0x40070106
83
+#include "hw/core/split-irq.h"
71
@@ -XXX,XX +XXX,XX @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
84
+
72
DeviceState *dev;
85
+typedef enum MPS2TZFPGAType {
73
MemoryRegion *mr;
86
+ FPGA_AN505,
74
87
+} MPS2TZFPGAType;
75
- dev = qdev_create(NULL, "pl011");
88
+
76
+ dev = qdev_create(NULL, TYPE_PL011);
89
+typedef struct {
77
s->lpd.iou.uart[i] = SYS_BUS_DEVICE(dev);
90
+ MachineClass parent;
78
qdev_prop_set_chr(dev, "chardev", serial_hd(i));
91
+ MPS2TZFPGAType fpga_type;
79
object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
92
+ uint32_t scc_id;
93
+} MPS2TZMachineClass;
94
+
95
+typedef struct {
96
+ MachineState parent;
97
+
98
+ IoTKit iotkit;
99
+ MemoryRegion psram;
100
+ MemoryRegion ssram1;
101
+ MemoryRegion ssram1_m;
102
+ MemoryRegion ssram23;
103
+ MPS2SCC scc;
104
+ MPS2FPGAIO fpgaio;
105
+ TZPPC ppc[5];
106
+ UnimplementedDeviceState ssram_mpc[3];
107
+ UnimplementedDeviceState spi[5];
108
+ UnimplementedDeviceState i2c[4];
109
+ UnimplementedDeviceState i2s_audio;
110
+ UnimplementedDeviceState gpio[5];
111
+ UnimplementedDeviceState dma[4];
112
+ UnimplementedDeviceState gfx;
113
+ CMSDKAPBUART uart[5];
114
+ SplitIRQ sec_resp_splitter;
115
+ qemu_or_irq uart_irq_orgate;
116
+} MPS2TZMachineState;
117
+
118
+#define TYPE_MPS2TZ_MACHINE "mps2tz"
119
+#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
120
+
121
+#define MPS2TZ_MACHINE(obj) \
122
+ OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
123
+#define MPS2TZ_MACHINE_GET_CLASS(obj) \
124
+ OBJECT_GET_CLASS(MPS2TZMachineClass, obj, TYPE_MPS2TZ_MACHINE)
125
+#define MPS2TZ_MACHINE_CLASS(klass) \
126
+ OBJECT_CLASS_CHECK(MPS2TZMachineClass, klass, TYPE_MPS2TZ_MACHINE)
127
+
128
+/* Main SYSCLK frequency in Hz */
129
+#define SYSCLK_FRQ 20000000
130
+
131
+/* Initialize the auxiliary RAM region @mr and map it into
132
+ * the memory map at @base.
133
+ */
134
+static void make_ram(MemoryRegion *mr, const char *name,
135
+ hwaddr base, hwaddr size)
136
+{
137
+ memory_region_init_ram(mr, NULL, name, size, &error_fatal);
138
+ memory_region_add_subregion(get_system_memory(), base, mr);
139
+}
140
+
141
+/* Create an alias of an entire original MemoryRegion @orig
142
+ * located at @base in the memory map.
143
+ */
144
+static void make_ram_alias(MemoryRegion *mr, const char *name,
145
+ MemoryRegion *orig, hwaddr base)
146
+{
147
+ memory_region_init_alias(mr, NULL, name, orig, 0,
148
+ memory_region_size(orig));
149
+ memory_region_add_subregion(get_system_memory(), base, mr);
150
+}
151
+
152
+static void init_sysbus_child(Object *parent, const char *childname,
153
+ void *child, size_t childsize,
154
+ const char *childtype)
155
+{
156
+ object_initialize(child, childsize, childtype);
157
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
158
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
159
+
160
+}
161
+
162
+/* Most of the devices in the AN505 FPGA image sit behind
163
+ * Peripheral Protection Controllers. These data structures
164
+ * define the layout of which devices sit behind which PPCs.
165
+ * The devfn for each port is a function which creates, configures
166
+ * and initializes the device, returning the MemoryRegion which
167
+ * needs to be plugged into the downstream end of the PPC port.
168
+ */
169
+typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
170
+ const char *name, hwaddr size);
171
+
172
+typedef struct PPCPortInfo {
173
+ const char *name;
174
+ MakeDevFn *devfn;
175
+ void *opaque;
176
+ hwaddr addr;
177
+ hwaddr size;
178
+} PPCPortInfo;
179
+
180
+typedef struct PPCInfo {
181
+ const char *name;
182
+ PPCPortInfo ports[TZ_NUM_PORTS];
183
+} PPCInfo;
184
+
185
+static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
186
+ void *opaque,
187
+ const char *name, hwaddr size)
188
+{
189
+ /* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
190
+ * and return a pointer to its MemoryRegion.
191
+ */
192
+ UnimplementedDeviceState *uds = opaque;
193
+
194
+ init_sysbus_child(OBJECT(mms), name, uds,
195
+ sizeof(UnimplementedDeviceState),
196
+ TYPE_UNIMPLEMENTED_DEVICE);
197
+ qdev_prop_set_string(DEVICE(uds), "name", name);
198
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
199
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
200
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
201
+}
202
+
203
+static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
204
+ const char *name, hwaddr size)
205
+{
206
+ CMSDKAPBUART *uart = opaque;
207
+ int i = uart - &mms->uart[0];
208
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
209
+ int rxirqno = i * 2;
210
+ int txirqno = i * 2 + 1;
211
+ int combirqno = i + 10;
212
+ SysBusDevice *s;
213
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
214
+ DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
215
+
216
+ init_sysbus_child(OBJECT(mms), name, uart,
217
+ sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART);
218
+ qdev_prop_set_chr(DEVICE(uart), "chardev", uartchr);
219
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
220
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
221
+ s = SYS_BUS_DEVICE(uart);
222
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
223
+ "EXP_IRQ", txirqno));
224
+ sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
225
+ "EXP_IRQ", rxirqno));
226
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
227
+ sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
228
+ sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
229
+ "EXP_IRQ", combirqno));
230
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
231
+}
232
+
233
+static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
234
+ const char *name, hwaddr size)
235
+{
236
+ MPS2SCC *scc = opaque;
237
+ DeviceState *sccdev;
238
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
239
+
240
+ object_initialize(scc, sizeof(mms->scc), TYPE_MPS2_SCC);
241
+ sccdev = DEVICE(scc);
242
+ qdev_set_parent_bus(sccdev, sysbus_get_default());
243
+ qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
244
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
245
+ qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
246
+ object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal);
247
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
248
+}
249
+
250
+static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
251
+ const char *name, hwaddr size)
252
+{
253
+ MPS2FPGAIO *fpgaio = opaque;
254
+
255
+ object_initialize(fpgaio, sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO);
256
+ qdev_set_parent_bus(DEVICE(fpgaio), sysbus_get_default());
257
+ object_property_set_bool(OBJECT(fpgaio), true, "realized", &error_fatal);
258
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
259
+}
260
+
261
+static void mps2tz_common_init(MachineState *machine)
262
+{
263
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
264
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
265
+ MemoryRegion *system_memory = get_system_memory();
266
+ DeviceState *iotkitdev;
267
+ DeviceState *dev_splitter;
268
+ int i;
269
+
270
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
271
+ error_report("This board can only be used with CPU %s",
272
+ mc->default_cpu_type);
273
+ exit(1);
274
+ }
275
+
276
+ init_sysbus_child(OBJECT(machine), "iotkit", &mms->iotkit,
277
+ sizeof(mms->iotkit), TYPE_IOTKIT);
278
+ iotkitdev = DEVICE(&mms->iotkit);
279
+ object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
280
+ "memory", &error_abort);
281
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
282
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
283
+ object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
284
+ &error_fatal);
285
+
286
+ /* The sec_resp_cfg output from the IoTKit must be split into multiple
287
+ * lines, one for each of the PPCs we create here.
288
+ */
289
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
290
+ TYPE_SPLIT_IRQ);
291
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
292
+ OBJECT(&mms->sec_resp_splitter), &error_abort);
293
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5,
294
+ "num-lines", &error_fatal);
295
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
296
+ "realized", &error_fatal);
297
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
298
+ qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
299
+ qdev_get_gpio_in(dev_splitter, 0));
300
+
301
+ /* The IoTKit sets up much of the memory layout, including
302
+ * the aliases between secure and non-secure regions in the
303
+ * address space. The FPGA itself contains:
304
+ *
305
+ * 0x00000000..0x003fffff SSRAM1
306
+ * 0x00400000..0x007fffff alias of SSRAM1
307
+ * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
308
+ * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
309
+ * 0x80000000..0x80ffffff 16MB PSRAM
310
+ */
311
+
312
+ /* The FPGA images have an odd combination of different RAMs,
313
+ * because in hardware they are different implementations and
314
+ * connected to different buses, giving varying performance/size
315
+ * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
316
+ * call the 16MB our "system memory", as it's the largest lump.
317
+ */
318
+ memory_region_allocate_system_memory(&mms->psram,
319
+ NULL, "mps.ram", 0x01000000);
320
+ memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
321
+
322
+ /* The SSRAM memories should all be behind Memory Protection Controllers,
323
+ * but we don't implement that yet.
324
+ */
325
+ make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000);
326
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x00400000);
327
+
328
+ make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000);
329
+
330
+ /* The overflow IRQs for all UARTs are ORed together.
331
+ * Tx, Rx and "combined" IRQs are sent to the NVIC separately.
332
+ * Create the OR gate for this.
333
+ */
334
+ object_initialize(&mms->uart_irq_orgate, sizeof(mms->uart_irq_orgate),
335
+ TYPE_OR_IRQ);
336
+ object_property_add_child(OBJECT(mms), "uart-irq-orgate",
337
+ OBJECT(&mms->uart_irq_orgate), &error_abort);
338
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), 10, "num-lines",
339
+ &error_fatal);
340
+ object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
341
+ "realized", &error_fatal);
342
+ qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
343
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
344
+
345
+ /* Most of the devices in the FPGA are behind Peripheral Protection
346
+ * Controllers. The required order for initializing things is:
347
+ * + initialize the PPC
348
+ * + initialize, configure and realize downstream devices
349
+ * + connect downstream device MemoryRegions to the PPC
350
+ * + realize the PPC
351
+ * + map the PPC's MemoryRegions to the places in the address map
352
+ * where the downstream devices should appear
353
+ * + wire up the PPC's control lines to the IoTKit object
354
+ */
355
+
356
+ const PPCInfo ppcs[] = { {
357
+ .name = "apb_ppcexp0",
358
+ .ports = {
359
+ { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0],
360
+ 0x58007000, 0x1000 },
361
+ { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1],
362
+ 0x58008000, 0x1000 },
363
+ { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2],
364
+ 0x58009000, 0x1000 },
365
+ },
366
+ }, {
367
+ .name = "apb_ppcexp1",
368
+ .ports = {
369
+ { "spi0", make_unimp_dev, &mms->spi[0], 0x40205000, 0x1000 },
370
+ { "spi1", make_unimp_dev, &mms->spi[1], 0x40206000, 0x1000 },
371
+ { "spi2", make_unimp_dev, &mms->spi[2], 0x40209000, 0x1000 },
372
+ { "spi3", make_unimp_dev, &mms->spi[3], 0x4020a000, 0x1000 },
373
+ { "spi4", make_unimp_dev, &mms->spi[4], 0x4020b000, 0x1000 },
374
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
375
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
376
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
377
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
378
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
379
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
380
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
381
+ { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
382
+ { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
383
+ },
384
+ }, {
385
+ .name = "apb_ppcexp2",
386
+ .ports = {
387
+ { "scc", make_scc, &mms->scc, 0x40300000, 0x1000 },
388
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
389
+ 0x40301000, 0x1000 },
390
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x40302000, 0x1000 },
391
+ },
392
+ }, {
393
+ .name = "ahb_ppcexp0",
394
+ .ports = {
395
+ { "gfx", make_unimp_dev, &mms->gfx, 0x41000000, 0x140000 },
396
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x40100000, 0x1000 },
397
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
398
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
399
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
400
+ { "gpio4", make_unimp_dev, &mms->gpio[4], 0x40104000, 0x1000 },
401
+ },
402
+ }, {
403
+ .name = "ahb_ppcexp1",
404
+ .ports = {
405
+ { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000 },
406
+ { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000 },
407
+ { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000 },
408
+ { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000 },
409
+ },
410
+ },
411
+ };
412
+
413
+ for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
414
+ const PPCInfo *ppcinfo = &ppcs[i];
415
+ TZPPC *ppc = &mms->ppc[i];
416
+ DeviceState *ppcdev;
417
+ int port;
418
+ char *gpioname;
419
+
420
+ init_sysbus_child(OBJECT(machine), ppcinfo->name, ppc,
421
+ sizeof(TZPPC), TYPE_TZ_PPC);
422
+ ppcdev = DEVICE(ppc);
423
+
424
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
425
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
426
+ MemoryRegion *mr;
427
+ char *portname;
428
+
429
+ if (!pinfo->devfn) {
430
+ continue;
431
+ }
432
+
433
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
434
+ portname = g_strdup_printf("port[%d]", port);
435
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
436
+ portname, &error_fatal);
437
+ g_free(portname);
438
+ }
439
+
440
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
441
+
442
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
443
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
444
+
445
+ if (!pinfo->devfn) {
446
+ continue;
447
+ }
448
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
449
+
450
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
451
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
452
+ qdev_get_gpio_in_named(ppcdev,
453
+ "cfg_nonsec",
454
+ port));
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
457
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
458
+ qdev_get_gpio_in_named(ppcdev,
459
+ "cfg_ap", port));
460
+ g_free(gpioname);
461
+ }
462
+
463
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
464
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
465
+ qdev_get_gpio_in_named(ppcdev,
466
+ "irq_enable", 0));
467
+ g_free(gpioname);
468
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
469
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
470
+ qdev_get_gpio_in_named(ppcdev,
471
+ "irq_clear", 0));
472
+ g_free(gpioname);
473
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
474
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
475
+ qdev_get_gpio_in_named(iotkitdev,
476
+ gpioname, 0));
477
+ g_free(gpioname);
478
+
479
+ qdev_connect_gpio_out(dev_splitter, i,
480
+ qdev_get_gpio_in_named(ppcdev,
481
+ "cfg_sec_resp", 0));
482
+ }
483
+
484
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
485
+ * except that it doesn't support the checksum-offload feature.
486
+ * The ethernet controller is not behind a PPC.
487
+ */
488
+ lan9118_init(&nd_table[0], 0x42000000,
489
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
490
+
491
+ create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
492
+
493
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
494
+}
495
+
496
+static void mps2tz_class_init(ObjectClass *oc, void *data)
497
+{
498
+ MachineClass *mc = MACHINE_CLASS(oc);
499
+
500
+ mc->init = mps2tz_common_init;
501
+ mc->max_cpus = 1;
502
+}
503
+
504
+static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
505
+{
506
+ MachineClass *mc = MACHINE_CLASS(oc);
507
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
508
+
509
+ mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
510
+ mmc->fpga_type = FPGA_AN505;
511
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
512
+ mmc->scc_id = 0x41040000 | (505 << 4);
513
+}
514
+
515
+static const TypeInfo mps2tz_info = {
516
+ .name = TYPE_MPS2TZ_MACHINE,
517
+ .parent = TYPE_MACHINE,
518
+ .abstract = true,
519
+ .instance_size = sizeof(MPS2TZMachineState),
520
+ .class_size = sizeof(MPS2TZMachineClass),
521
+ .class_init = mps2tz_class_init,
522
+};
523
+
524
+static const TypeInfo mps2tz_an505_info = {
525
+ .name = TYPE_MPS2TZ_AN505_MACHINE,
526
+ .parent = TYPE_MPS2TZ_MACHINE,
527
+ .class_init = mps2tz_an505_class_init,
528
+};
529
+
530
+static void mps2tz_machine_init(void)
531
+{
532
+ type_register_static(&mps2tz_info);
533
+ type_register_static(&mps2tz_an505_info);
534
+}
535
+
536
+type_init(mps2tz_machine_init);
537
--
80
--
538
2.16.2
81
2.20.1
539
82
540
83
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Allow the translate subroutines to return false for invalid insns.
3
We had set this for aarch32-only in arm_max_initfn, but
4
4
failed to set the same bit for aarch64.
5
At present we can of course invoke an invalid insn exception from within
6
the translate subroutine, but in the short term this consolidates code.
7
In the long term it would allow the decodetree language to support
8
overlapping patterns for ISA extensions.
9
5
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227232618.2908-1-richard.henderson@linaro.org
7
Message-id: 20200218190958.745-2-richard.henderson@linaro.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
scripts/decodetree.py | 5 ++---
11
target/arm/cpu64.c | 1 +
16
1 file changed, 2 insertions(+), 3 deletions(-)
12
1 file changed, 1 insertion(+)
17
13
18
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
14
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
19
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
20
--- a/scripts/decodetree.py
16
--- a/target/arm/cpu64.c
21
+++ b/scripts/decodetree.py
17
+++ b/target/arm/cpu64.c
22
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
18
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
23
global translate_prefix
19
cpu->isar.id_mmfr3 = u;
24
output('typedef ', self.base.base.struct_name(),
20
25
' arg_', self.name, ';\n')
21
u = cpu->isar.id_mmfr4;
26
- output(translate_scope, 'void ', translate_prefix, '_', self.name,
22
+ u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */
27
+ output(translate_scope, 'bool ', translate_prefix, '_', self.name,
23
u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
28
'(DisasContext *ctx, arg_', self.name,
24
cpu->isar.id_mmfr4 = u;
29
' *a, ', insntype, ' insn);\n')
30
31
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
32
output(ind, self.base.extract_name(), '(&u.f_', arg, ', insn);\n')
33
for n, f in self.fields.items():
34
output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
35
- output(ind, translate_prefix, '_', self.name,
36
+ output(ind, 'return ', translate_prefix, '_', self.name,
37
'(ctx, &u.f_', arg, ', insn);\n')
38
- output(ind, 'return true;\n')
39
# end Pattern
40
41
25
42
--
26
--
43
2.16.2
27
2.20.1
44
28
45
29
diff view generated by jsdifflib
1
Model the Arm IoT Kit documented in
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
3
2
4
The Arm IoT Kit is a subsystem which includes a CPU and some devices,
3
The Linux kernel displays errors why trying to detect the PL041
5
and is intended be extended by adding extra devices to form a
4
audio interface:
6
complete system. It is used in the MPS2 board's AN505 image for the
7
Cortex-M33.
8
5
6
Linux version 4.16.0 (linus@genomnajs) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #142 PREEMPT Wed May 9 13:24:55 CEST 2018
7
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00093177
8
CPU: VIVT data cache, VIVT instruction cache
9
OF: fdt: Machine model: ARM Integrator/CP
10
...
11
OF: amba_device_add() failed (-19) for /fpga/aaci@1d000000
12
13
Since we have it already modelled, simply plug it.
14
15
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20200223233033.15371-2-f4bug@amsat.org
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180220180325.29818-19-peter.maydell@linaro.org
12
---
19
---
13
hw/arm/Makefile.objs | 1 +
20
hw/arm/integratorcp.c | 1 +
14
include/hw/arm/iotkit.h | 109 ++++++++
21
hw/arm/Kconfig | 1 +
15
hw/arm/iotkit.c | 598 ++++++++++++++++++++++++++++++++++++++++
22
2 files changed, 2 insertions(+)
16
default-configs/arm-softmmu.mak | 1 +
17
4 files changed, 709 insertions(+)
18
create mode 100644 include/hw/arm/iotkit.h
19
create mode 100644 hw/arm/iotkit.c
20
23
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
24
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
22
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Makefile.objs
26
--- a/hw/arm/integratorcp.c
24
+++ b/hw/arm/Makefile.objs
27
+++ b/hw/arm/integratorcp.c
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
28
@@ -XXX,XX +XXX,XX @@ static void integratorcp_init(MachineState *machine)
26
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
29
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
27
obj-$(CONFIG_MPS2) += mps2.o
30
qdev_connect_gpio_out(dev, 1,
28
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
31
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
29
+obj-$(CONFIG_IOTKIT) += iotkit.o
32
+ sysbus_create_varargs("pl041", 0x1d000000, pic[25], NULL);
30
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
33
31
new file mode 100644
34
if (nd_table[0].used)
32
index XXXXXXX..XXXXXXX
35
smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
33
--- /dev/null
36
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
34
+++ b/include/hw/arm/iotkit.h
35
@@ -XXX,XX +XXX,XX @@
36
+/*
37
+ * ARM IoT Kit
38
+ *
39
+ * Copyright (c) 2018 Linaro Limited
40
+ * Written by Peter Maydell
41
+ *
42
+ * This program is free software; you can redistribute it and/or modify
43
+ * it under the terms of the GNU General Public License version 2 or
44
+ * (at your option) any later version.
45
+ */
46
+
47
+/* This is a model of the Arm IoT Kit which is documented in
48
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
49
+ * It contains:
50
+ * a Cortex-M33
51
+ * the IDAU
52
+ * some timers and watchdogs
53
+ * two peripheral protection controllers
54
+ * a memory protection controller
55
+ * a security controller
56
+ * a bus fabric which arranges that some parts of the address
57
+ * space are secure and non-secure aliases of each other
58
+ *
59
+ * QEMU interface:
60
+ * + QOM property "memory" is a MemoryRegion containing the devices provided
61
+ * by the board model.
62
+ * + QOM property "MAINCLK" is the frequency of the main system clock
63
+ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
64
+ * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
65
+ * are wired to the NVIC lines 32 .. n+32
66
+ * Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
67
+ * might provide:
68
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
69
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
70
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
71
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
72
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
73
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
74
+ * might provide:
75
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
76
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
77
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
78
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
79
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
80
+ */
81
+
82
+#ifndef IOTKIT_H
83
+#define IOTKIT_H
84
+
85
+#include "hw/sysbus.h"
86
+#include "hw/arm/armv7m.h"
87
+#include "hw/misc/iotkit-secctl.h"
88
+#include "hw/misc/tz-ppc.h"
89
+#include "hw/timer/cmsdk-apb-timer.h"
90
+#include "hw/misc/unimp.h"
91
+#include "hw/or-irq.h"
92
+#include "hw/core/split-irq.h"
93
+
94
+#define TYPE_IOTKIT "iotkit"
95
+#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
96
+
97
+/* We have an IRQ splitter and an OR gate input for each external PPC
98
+ * and the 2 internal PPCs
99
+ */
100
+#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
101
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
102
+
103
+typedef struct IoTKit {
104
+ /*< private >*/
105
+ SysBusDevice parent_obj;
106
+
107
+ /*< public >*/
108
+ ARMv7MState armv7m;
109
+ IoTKitSecCtl secctl;
110
+ TZPPC apb_ppc0;
111
+ TZPPC apb_ppc1;
112
+ CMSDKAPBTIMER timer0;
113
+ CMSDKAPBTIMER timer1;
114
+ qemu_or_irq ppc_irq_orgate;
115
+ SplitIRQ sec_resp_splitter;
116
+ SplitIRQ ppc_irq_splitter[NUM_PPCS];
117
+
118
+ UnimplementedDeviceState dualtimer;
119
+ UnimplementedDeviceState s32ktimer;
120
+
121
+ MemoryRegion container;
122
+ MemoryRegion alias1;
123
+ MemoryRegion alias2;
124
+ MemoryRegion alias3;
125
+ MemoryRegion sram0;
126
+
127
+ qemu_irq *exp_irqs;
128
+ qemu_irq ppc0_irq;
129
+ qemu_irq ppc1_irq;
130
+ qemu_irq sec_resp_cfg;
131
+ qemu_irq sec_resp_cfg_in;
132
+ qemu_irq nsc_cfg_in;
133
+
134
+ qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
135
+
136
+ uint32_t nsccfg;
137
+
138
+ /* Properties */
139
+ MemoryRegion *board_memory;
140
+ uint32_t exp_numirq;
141
+ uint32_t mainclk_frq;
142
+} IoTKit;
143
+
144
+#endif
145
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
146
new file mode 100644
147
index XXXXXXX..XXXXXXX
148
--- /dev/null
149
+++ b/hw/arm/iotkit.c
150
@@ -XXX,XX +XXX,XX @@
151
+/*
152
+ * Arm IoT Kit
153
+ *
154
+ * Copyright (c) 2018 Linaro Limited
155
+ * Written by Peter Maydell
156
+ *
157
+ * This program is free software; you can redistribute it and/or modify
158
+ * it under the terms of the GNU General Public License version 2 or
159
+ * (at your option) any later version.
160
+ */
161
+
162
+#include "qemu/osdep.h"
163
+#include "qemu/log.h"
164
+#include "qapi/error.h"
165
+#include "trace.h"
166
+#include "hw/sysbus.h"
167
+#include "hw/registerfields.h"
168
+#include "hw/arm/iotkit.h"
169
+#include "hw/misc/unimp.h"
170
+#include "hw/arm/arm.h"
171
+
172
+/* Create an alias region of @size bytes starting at @base
173
+ * which mirrors the memory starting at @orig.
174
+ */
175
+static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
176
+ hwaddr base, hwaddr size, hwaddr orig)
177
+{
178
+ memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
179
+ /* The alias is even lower priority than unimplemented_device regions */
180
+ memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
181
+}
182
+
183
+static void init_sysbus_child(Object *parent, const char *childname,
184
+ void *child, size_t childsize,
185
+ const char *childtype)
186
+{
187
+ object_initialize(child, childsize, childtype);
188
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
189
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
190
+}
191
+
192
+static void irq_status_forwarder(void *opaque, int n, int level)
193
+{
194
+ qemu_irq destirq = opaque;
195
+
196
+ qemu_set_irq(destirq, level);
197
+}
198
+
199
+static void nsccfg_handler(void *opaque, int n, int level)
200
+{
201
+ IoTKit *s = IOTKIT(opaque);
202
+
203
+ s->nsccfg = level;
204
+}
205
+
206
+static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
207
+{
208
+ /* Each of the 4 AHB and 4 APB PPCs that might be present in a
209
+ * system using the IoTKit has a collection of control lines which
210
+ * are provided by the security controller and which we want to
211
+ * expose as control lines on the IoTKit device itself, so the
212
+ * code using the IoTKit can wire them up to the PPCs.
213
+ */
214
+ SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
215
+ DeviceState *iotkitdev = DEVICE(s);
216
+ DeviceState *dev_secctl = DEVICE(&s->secctl);
217
+ DeviceState *dev_splitter = DEVICE(splitter);
218
+ char *name;
219
+
220
+ name = g_strdup_printf("%s_nonsec", ppcname);
221
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
222
+ g_free(name);
223
+ name = g_strdup_printf("%s_ap", ppcname);
224
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
225
+ g_free(name);
226
+ name = g_strdup_printf("%s_irq_enable", ppcname);
227
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
228
+ g_free(name);
229
+ name = g_strdup_printf("%s_irq_clear", ppcname);
230
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
231
+ g_free(name);
232
+
233
+ /* irq_status is a little more tricky, because we need to
234
+ * split it so we can send it both to the security controller
235
+ * and to our OR gate for the NVIC interrupt line.
236
+ * Connect up the splitter's outputs, and create a GPIO input
237
+ * which will pass the line state to the input splitter.
238
+ */
239
+ name = g_strdup_printf("%s_irq_status", ppcname);
240
+ qdev_connect_gpio_out(dev_splitter, 0,
241
+ qdev_get_gpio_in_named(dev_secctl,
242
+ name, 0));
243
+ qdev_connect_gpio_out(dev_splitter, 1,
244
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
245
+ s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
246
+ qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
247
+ s->irq_status_in[ppcnum], name, 1);
248
+ g_free(name);
249
+}
250
+
251
+static void iotkit_forward_sec_resp_cfg(IoTKit *s)
252
+{
253
+ /* Forward the 3rd output from the splitter device as a
254
+ * named GPIO output of the iotkit object.
255
+ */
256
+ DeviceState *dev = DEVICE(s);
257
+ DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
258
+
259
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
260
+ s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
261
+ s->sec_resp_cfg, 1);
262
+ qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
263
+}
264
+
265
+static void iotkit_init(Object *obj)
266
+{
267
+ IoTKit *s = IOTKIT(obj);
268
+ int i;
269
+
270
+ memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
271
+
272
+ init_sysbus_child(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
273
+ TYPE_ARMV7M);
274
+ qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
275
+ ARM_CPU_TYPE_NAME("cortex-m33"));
276
+
277
+ init_sysbus_child(obj, "secctl", &s->secctl, sizeof(s->secctl),
278
+ TYPE_IOTKIT_SECCTL);
279
+ init_sysbus_child(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
280
+ TYPE_TZ_PPC);
281
+ init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
282
+ TYPE_TZ_PPC);
283
+ init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
284
+ TYPE_CMSDK_APB_TIMER);
285
+ init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
286
+ TYPE_CMSDK_APB_TIMER);
287
+ init_sysbus_child(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
288
+ TYPE_UNIMPLEMENTED_DEVICE);
289
+ object_initialize(&s->ppc_irq_orgate, sizeof(s->ppc_irq_orgate),
290
+ TYPE_OR_IRQ);
291
+ object_property_add_child(obj, "ppc-irq-orgate",
292
+ OBJECT(&s->ppc_irq_orgate), &error_abort);
293
+ object_initialize(&s->sec_resp_splitter, sizeof(s->sec_resp_splitter),
294
+ TYPE_SPLIT_IRQ);
295
+ object_property_add_child(obj, "sec-resp-splitter",
296
+ OBJECT(&s->sec_resp_splitter), &error_abort);
297
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
298
+ char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
299
+ SplitIRQ *splitter = &s->ppc_irq_splitter[i];
300
+
301
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
302
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
303
+ }
304
+ init_sysbus_child(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
305
+ TYPE_UNIMPLEMENTED_DEVICE);
306
+}
307
+
308
+static void iotkit_exp_irq(void *opaque, int n, int level)
309
+{
310
+ IoTKit *s = IOTKIT(opaque);
311
+
312
+ qemu_set_irq(s->exp_irqs[n], level);
313
+}
314
+
315
+static void iotkit_realize(DeviceState *dev, Error **errp)
316
+{
317
+ IoTKit *s = IOTKIT(dev);
318
+ int i;
319
+ MemoryRegion *mr;
320
+ Error *err = NULL;
321
+ SysBusDevice *sbd_apb_ppc0;
322
+ SysBusDevice *sbd_secctl;
323
+ DeviceState *dev_apb_ppc0;
324
+ DeviceState *dev_apb_ppc1;
325
+ DeviceState *dev_secctl;
326
+ DeviceState *dev_splitter;
327
+
328
+ if (!s->board_memory) {
329
+ error_setg(errp, "memory property was not set");
330
+ return;
331
+ }
332
+
333
+ if (!s->mainclk_frq) {
334
+ error_setg(errp, "MAINCLK property was not set");
335
+ return;
336
+ }
337
+
338
+ /* Handling of which devices should be available only to secure
339
+ * code is usually done differently for M profile than for A profile.
340
+ * Instead of putting some devices only into the secure address space,
341
+ * devices exist in both address spaces but with hard-wired security
342
+ * permissions that will cause the CPU to fault for non-secure accesses.
343
+ *
344
+ * The IoTKit has an IDAU (Implementation Defined Access Unit),
345
+ * which specifies hard-wired security permissions for different
346
+ * areas of the physical address space. For the IoTKit IDAU, the
347
+ * top 4 bits of the physical address are the IDAU region ID, and
348
+ * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
349
+ * region, otherwise it is an S region.
350
+ *
351
+ * The various devices and RAMs are generally all mapped twice,
352
+ * once into a region that the IDAU defines as secure and once
353
+ * into a non-secure region. They sit behind either a Memory
354
+ * Protection Controller (for RAM) or a Peripheral Protection
355
+ * Controller (for devices), which allow a more fine grained
356
+ * configuration of whether non-secure accesses are permitted.
357
+ *
358
+ * (The other place that guest software can configure security
359
+ * permissions is in the architected SAU (Security Attribution
360
+ * Unit), which is entirely inside the CPU. The IDAU can upgrade
361
+ * the security attributes for a region to more restrictive than
362
+ * the SAU specifies, but cannot downgrade them.)
363
+ *
364
+ * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
365
+ * 0x20000000..0x2007ffff 32KB FPGA block RAM
366
+ * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
367
+ * 0x40000000..0x4000ffff base peripheral region 1
368
+ * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
369
+ * 0x40020000..0x4002ffff system control element peripherals
370
+ * 0x40080000..0x400fffff base peripheral region 2
371
+ * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
372
+ */
373
+
374
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
375
+
376
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
377
+ /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
378
+ * register in the IoT Kit System Control Register block, and the
379
+ * initial value of that is in turn specifiable by the FPGA that
380
+ * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
381
+ * and simply set the CPU's init-svtor to the IoT Kit default value.
382
+ */
383
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
384
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
385
+ "memory", &err);
386
+ if (err) {
387
+ error_propagate(errp, err);
388
+ return;
389
+ }
390
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
391
+ if (err) {
392
+ error_propagate(errp, err);
393
+ return;
394
+ }
395
+ object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
396
+ if (err) {
397
+ error_propagate(errp, err);
398
+ return;
399
+ }
400
+
401
+ /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
402
+ s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
403
+ for (i = 0; i < s->exp_numirq; i++) {
404
+ s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
405
+ }
406
+ qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
407
+
408
+ /* Set up the big aliases first */
409
+ make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
410
+ make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
411
+ /* The 0x50000000..0x5fffffff region is not a pure alias: it has
412
+ * a few extra devices that only appear there (generally the
413
+ * control interfaces for the protection controllers).
414
+ * We implement this by mapping those devices over the top of this
415
+ * alias MR at a higher priority.
416
+ */
417
+ make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
418
+
419
+ /* This RAM should be behind a Memory Protection Controller, but we
420
+ * don't implement that yet.
421
+ */
422
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
423
+ if (err) {
424
+ error_propagate(errp, err);
425
+ return;
426
+ }
427
+ memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
428
+
429
+ /* Security controller */
430
+ object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
431
+ if (err) {
432
+ error_propagate(errp, err);
433
+ return;
434
+ }
435
+ sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
436
+ dev_secctl = DEVICE(&s->secctl);
437
+ sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
438
+ sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
439
+
440
+ s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
441
+ qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
442
+
443
+ /* The sec_resp_cfg output from the security controller must be split into
444
+ * multiple lines, one for each of the PPCs within the IoTKit and one
445
+ * that will be an output from the IoTKit to the system.
446
+ */
447
+ object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
448
+ "num-lines", &err);
449
+ if (err) {
450
+ error_propagate(errp, err);
451
+ return;
452
+ }
453
+ object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
454
+ "realized", &err);
455
+ if (err) {
456
+ error_propagate(errp, err);
457
+ return;
458
+ }
459
+ dev_splitter = DEVICE(&s->sec_resp_splitter);
460
+ qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
461
+ qdev_get_gpio_in(dev_splitter, 0));
462
+
463
+ /* Devices behind APB PPC0:
464
+ * 0x40000000: timer0
465
+ * 0x40001000: timer1
466
+ * 0x40002000: dual timer
467
+ * We must configure and realize each downstream device and connect
468
+ * it to the appropriate PPC port; then we can realize the PPC and
469
+ * map its upstream ends to the right place in the container.
470
+ */
471
+ qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
472
+ object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
473
+ if (err) {
474
+ error_propagate(errp, err);
475
+ return;
476
+ }
477
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
478
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
479
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
480
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
481
+ if (err) {
482
+ error_propagate(errp, err);
483
+ return;
484
+ }
485
+
486
+ qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
487
+ object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
488
+ if (err) {
489
+ error_propagate(errp, err);
490
+ return;
491
+ }
492
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
493
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
494
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
495
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
496
+ if (err) {
497
+ error_propagate(errp, err);
498
+ return;
499
+ }
500
+
501
+ qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
502
+ qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
503
+ object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
504
+ if (err) {
505
+ error_propagate(errp, err);
506
+ return;
507
+ }
508
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
509
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
510
+ if (err) {
511
+ error_propagate(errp, err);
512
+ return;
513
+ }
514
+
515
+ object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
516
+ if (err) {
517
+ error_propagate(errp, err);
518
+ return;
519
+ }
520
+
521
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
522
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
523
+
524
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
525
+ memory_region_add_subregion(&s->container, 0x40000000, mr);
526
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
527
+ memory_region_add_subregion(&s->container, 0x40001000, mr);
528
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
529
+ memory_region_add_subregion(&s->container, 0x40002000, mr);
530
+ for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
531
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
532
+ qdev_get_gpio_in_named(dev_apb_ppc0,
533
+ "cfg_nonsec", i));
534
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
535
+ qdev_get_gpio_in_named(dev_apb_ppc0,
536
+ "cfg_ap", i));
537
+ }
538
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
539
+ qdev_get_gpio_in_named(dev_apb_ppc0,
540
+ "irq_enable", 0));
541
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
542
+ qdev_get_gpio_in_named(dev_apb_ppc0,
543
+ "irq_clear", 0));
544
+ qdev_connect_gpio_out(dev_splitter, 0,
545
+ qdev_get_gpio_in_named(dev_apb_ppc0,
546
+ "cfg_sec_resp", 0));
547
+
548
+ /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
549
+ * ones) are sent individually to the security controller, and also
550
+ * ORed together to give a single combined PPC interrupt to the NVIC.
551
+ */
552
+ object_property_set_int(OBJECT(&s->ppc_irq_orgate),
553
+ NUM_PPCS, "num-lines", &err);
554
+ if (err) {
555
+ error_propagate(errp, err);
556
+ return;
557
+ }
558
+ object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
559
+ "realized", &err);
560
+ if (err) {
561
+ error_propagate(errp, err);
562
+ return;
563
+ }
564
+ qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
565
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
566
+
567
+ /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
568
+
569
+ /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
570
+ /* Devices behind APB PPC1:
571
+ * 0x4002f000: S32K timer
572
+ */
573
+ qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
574
+ qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
575
+ object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
576
+ if (err) {
577
+ error_propagate(errp, err);
578
+ return;
579
+ }
580
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
581
+ object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
582
+ if (err) {
583
+ error_propagate(errp, err);
584
+ return;
585
+ }
586
+
587
+ object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
588
+ if (err) {
589
+ error_propagate(errp, err);
590
+ return;
591
+ }
592
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
593
+ memory_region_add_subregion(&s->container, 0x4002f000, mr);
594
+
595
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
596
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
597
+ qdev_get_gpio_in_named(dev_apb_ppc1,
598
+ "cfg_nonsec", 0));
599
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
600
+ qdev_get_gpio_in_named(dev_apb_ppc1,
601
+ "cfg_ap", 0));
602
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
603
+ qdev_get_gpio_in_named(dev_apb_ppc1,
604
+ "irq_enable", 0));
605
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
606
+ qdev_get_gpio_in_named(dev_apb_ppc1,
607
+ "irq_clear", 0));
608
+ qdev_connect_gpio_out(dev_splitter, 1,
609
+ qdev_get_gpio_in_named(dev_apb_ppc1,
610
+ "cfg_sec_resp", 0));
611
+
612
+ /* Using create_unimplemented_device() maps the stub into the
613
+ * system address space rather than into our container, but the
614
+ * overall effect to the guest is the same.
615
+ */
616
+ create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
617
+
618
+ create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
619
+ create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
620
+
621
+ /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
622
+
623
+ create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
624
+ create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
625
+
626
+ create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
627
+
628
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
629
+ Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
630
+
631
+ object_property_set_int(splitter, 2, "num-lines", &err);
632
+ if (err) {
633
+ error_propagate(errp, err);
634
+ return;
635
+ }
636
+ object_property_set_bool(splitter, true, "realized", &err);
637
+ if (err) {
638
+ error_propagate(errp, err);
639
+ return;
640
+ }
641
+ }
642
+
643
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
644
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
645
+
646
+ iotkit_forward_ppc(s, ppcname, i);
647
+ g_free(ppcname);
648
+ }
649
+
650
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
651
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
652
+
653
+ iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
654
+ g_free(ppcname);
655
+ }
656
+
657
+ for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
658
+ /* Wire up IRQ splitter for internal PPCs */
659
+ DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
660
+ char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
661
+ i - NUM_EXTERNAL_PPCS);
662
+ TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
663
+
664
+ qdev_connect_gpio_out(devs, 0,
665
+ qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
666
+ qdev_connect_gpio_out(devs, 1,
667
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
668
+ qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
669
+ qdev_get_gpio_in(devs, 0));
670
+ }
671
+
672
+ iotkit_forward_sec_resp_cfg(s);
673
+
674
+ system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
675
+}
676
+
677
+static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
678
+ int *iregion, bool *exempt, bool *ns, bool *nsc)
679
+{
680
+ /* For IoTKit systems the IDAU responses are simple logical functions
681
+ * of the address bits. The NSC attribute is guest-adjustable via the
682
+ * NSCCFG register in the security controller.
683
+ */
684
+ IoTKit *s = IOTKIT(ii);
685
+ int region = extract32(address, 28, 4);
686
+
687
+ *ns = !(region & 1);
688
+ *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
689
+ /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
690
+ *exempt = (address & 0xeff00000) == 0xe0000000;
691
+ *iregion = region;
692
+}
693
+
694
+static const VMStateDescription iotkit_vmstate = {
695
+ .name = "iotkit",
696
+ .version_id = 1,
697
+ .minimum_version_id = 1,
698
+ .fields = (VMStateField[]) {
699
+ VMSTATE_UINT32(nsccfg, IoTKit),
700
+ VMSTATE_END_OF_LIST()
701
+ }
702
+};
703
+
704
+static Property iotkit_properties[] = {
705
+ DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
706
+ MemoryRegion *),
707
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
708
+ DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
709
+ DEFINE_PROP_END_OF_LIST()
710
+};
711
+
712
+static void iotkit_reset(DeviceState *dev)
713
+{
714
+ IoTKit *s = IOTKIT(dev);
715
+
716
+ s->nsccfg = 0;
717
+}
718
+
719
+static void iotkit_class_init(ObjectClass *klass, void *data)
720
+{
721
+ DeviceClass *dc = DEVICE_CLASS(klass);
722
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
723
+
724
+ dc->realize = iotkit_realize;
725
+ dc->vmsd = &iotkit_vmstate;
726
+ dc->props = iotkit_properties;
727
+ dc->reset = iotkit_reset;
728
+ iic->check = iotkit_idau_check;
729
+}
730
+
731
+static const TypeInfo iotkit_info = {
732
+ .name = TYPE_IOTKIT,
733
+ .parent = TYPE_SYS_BUS_DEVICE,
734
+ .instance_size = sizeof(IoTKit),
735
+ .instance_init = iotkit_init,
736
+ .class_init = iotkit_class_init,
737
+ .interfaces = (InterfaceInfo[]) {
738
+ { TYPE_IDAU_INTERFACE },
739
+ { }
740
+ }
741
+};
742
+
743
+static void iotkit_register_types(void)
744
+{
745
+ type_register_static(&iotkit_info);
746
+}
747
+
748
+type_init(iotkit_register_types);
749
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
750
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
751
--- a/default-configs/arm-softmmu.mak
38
--- a/hw/arm/Kconfig
752
+++ b/default-configs/arm-softmmu.mak
39
+++ b/hw/arm/Kconfig
753
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
40
@@ -XXX,XX +XXX,XX @@ config INTEGRATOR
754
CONFIG_MPS2_SCC=y
41
select INTEGRATOR_DEBUG
755
42
select PL011 # UART
756
CONFIG_TZ_PPC=y
43
select PL031 # RTC
757
+CONFIG_IOTKIT=y
44
+ select PL041 # audio
758
CONFIG_IOTKIT_SECCTL=y
45
select PL050 # keyboard/mouse
759
46
select PL110 # pl111 LCD controller
760
CONFIG_VERSATILE_PCI=y
47
select PL181 # display
761
--
48
--
762
2.16.2
49
2.20.1
763
50
764
51
diff view generated by jsdifflib
1
Create an "init-svtor" property on the armv7m container
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
object which we can forward to the CPU object.
3
2
3
The GICv2 allows the implementation to implement a variable number
4
of priority bits; unimplemented bits in the priority registers
5
are read as zeros, writes ignored. We were previously always
6
implementing a full 8 bits of priority, which is allowed but not
7
what the real hardware typically does (which is usually to have
8
4 or 5 bits of priority).
9
10
Add a new device property to allow the number of implemented
11
property bits to be specified.
12
13
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
14
Message-id: 1582537164-764-2-git-send-email-sai.pavan.boddu@xilinx.com
15
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
[PMM: improved commit message]
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180220180325.29818-8-peter.maydell@linaro.org
7
---
19
---
8
include/hw/arm/armv7m.h | 2 ++
20
include/hw/intc/arm_gic.h | 2 ++
9
hw/arm/armv7m.c | 9 +++++++++
21
include/hw/intc/arm_gic_common.h | 1 +
10
2 files changed, 11 insertions(+)
22
hw/intc/arm_gic.c | 33 ++++++++++++++++++++++++++++++--
23
hw/intc/arm_gic_common.c | 1 +
24
4 files changed, 35 insertions(+), 2 deletions(-)
11
25
12
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
26
diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h
13
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armv7m.h
28
--- a/include/hw/intc/arm_gic.h
15
+++ b/include/hw/arm/armv7m.h
29
+++ b/include/hw/intc/arm_gic.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct {
30
@@ -XXX,XX +XXX,XX @@
17
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
31
18
* devices will be automatically layered on top of this view.)
32
/* Number of SGI target-list bits */
19
* + Property "idau": IDAU interface (forwarded to CPU object)
33
#define GIC_TARGETLIST_BITS 8
20
+ * + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
34
+#define GIC_MAX_PRIORITY_BITS 8
21
*/
35
+#define GIC_MIN_PRIORITY_BITS 4
22
typedef struct ARMv7MState {
36
23
/*< private >*/
37
#define TYPE_ARM_GIC "arm_gic"
24
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
38
#define ARM_GIC(obj) \
25
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
39
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
26
MemoryRegion *board_memory;
27
Object *idau;
28
+ uint32_t init_svtor;
29
} ARMv7MState;
30
31
#endif
32
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
33
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/armv7m.c
41
--- a/include/hw/intc/arm_gic_common.h
35
+++ b/hw/arm/armv7m.c
42
+++ b/include/hw/intc/arm_gic_common.h
36
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
43
@@ -XXX,XX +XXX,XX @@ typedef struct GICState {
44
uint16_t priority_mask[GIC_NCPU_VCPU];
45
uint16_t running_priority[GIC_NCPU_VCPU];
46
uint16_t current_pending[GIC_NCPU_VCPU];
47
+ uint32_t n_prio_bits;
48
49
/* If we present the GICv2 without security extensions to a guest,
50
* the guest can configure the GICC_CTLR to configure group 1 binary point
51
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/intc/arm_gic.c
54
+++ b/hw/intc/arm_gic.c
55
@@ -XXX,XX +XXX,XX @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
56
return ret;
57
}
58
59
+static uint32_t gic_fullprio_mask(GICState *s, int cpu)
60
+{
61
+ /*
62
+ * Return a mask word which clears the unimplemented priority
63
+ * bits from a priority value for an interrupt. (Not to be
64
+ * confused with the group priority, whose mask depends on BPR.)
65
+ */
66
+ int priBits;
67
+
68
+ if (gic_is_vcpu(cpu)) {
69
+ priBits = GIC_VIRT_MAX_GROUP_PRIO_BITS;
70
+ } else {
71
+ priBits = s->n_prio_bits;
72
+ }
73
+ return ~0U << (8 - priBits);
74
+}
75
+
76
void gic_dist_set_priority(GICState *s, int cpu, int irq, uint8_t val,
77
MemTxAttrs attrs)
78
{
79
@@ -XXX,XX +XXX,XX @@ void gic_dist_set_priority(GICState *s, int cpu, int irq, uint8_t val,
80
val = 0x80 | (val >> 1); /* Non-secure view */
81
}
82
83
+ val &= gic_fullprio_mask(s, cpu);
84
+
85
if (irq < GIC_INTERNAL) {
86
s->priority1[irq][cpu] = val;
87
} else {
88
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_get_priority(GICState *s, int cpu, int irq,
89
}
90
prio = (prio << 1) & 0xff; /* Non-secure view */
91
}
92
- return prio;
93
+ return prio & gic_fullprio_mask(s, cpu);
94
}
95
96
static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask,
97
@@ -XXX,XX +XXX,XX @@ static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask,
37
return;
98
return;
38
}
99
}
39
}
100
}
40
+ if (object_property_find(OBJECT(s->cpu), "init-svtor", NULL)) {
101
- s->priority_mask[cpu] = pmask;
41
+ object_property_set_uint(OBJECT(s->cpu), s->init_svtor,
102
+ s->priority_mask[cpu] = pmask & gic_fullprio_mask(s, cpu);
42
+ "init-svtor", &err);
103
}
43
+ if (err != NULL) {
104
44
+ error_propagate(errp, err);
105
static uint32_t gic_get_priority_mask(GICState *s, int cpu, MemTxAttrs attrs)
45
+ return;
106
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
46
+ }
107
return;
108
}
109
110
+ if (s->n_prio_bits > GIC_MAX_PRIORITY_BITS ||
111
+ (s->virt_extn ? s->n_prio_bits < GIC_VIRT_MAX_GROUP_PRIO_BITS :
112
+ s->n_prio_bits < GIC_MIN_PRIORITY_BITS)) {
113
+ error_setg(errp, "num-priority-bits cannot be greater than %d"
114
+ " or less than %d", GIC_MAX_PRIORITY_BITS,
115
+ s->virt_extn ? GIC_VIRT_MAX_GROUP_PRIO_BITS :
116
+ GIC_MIN_PRIORITY_BITS);
117
+ return;
47
+ }
118
+ }
48
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
119
+
49
if (err != NULL) {
120
/* This creates distributor, main CPU interface (s->cpuiomem[0]) and if
50
error_propagate(errp, err);
121
* enabled, virtualization extensions related interfaces (main virtual
51
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
122
* interface (s->vifaceiomem[0]) and virtual CPU interface).
52
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
123
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
53
MemoryRegion *),
124
index XXXXXXX..XXXXXXX 100644
54
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
125
--- a/hw/intc/arm_gic_common.c
55
+ DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
126
+++ b/hw/intc/arm_gic_common.c
127
@@ -XXX,XX +XXX,XX @@ static Property arm_gic_common_properties[] = {
128
DEFINE_PROP_BOOL("has-security-extensions", GICState, security_extn, 0),
129
/* True if the GIC should implement the virtualization extensions */
130
DEFINE_PROP_BOOL("has-virtualization-extensions", GICState, virt_extn, 0),
131
+ DEFINE_PROP_UINT32("num-priority-bits", GICState, n_prio_bits, 8),
56
DEFINE_PROP_END_OF_LIST(),
132
DEFINE_PROP_END_OF_LIST(),
57
};
133
};
58
134
59
--
135
--
60
2.16.2
136
2.20.1
61
137
62
138
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
2
3
Allow the guest to determine the time set from the QEMU command line.
3
All A9 CPUs have a GIC with 5 bits of priority.
4
4
5
This includes adding a trace event to debug the new time.
5
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
6
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
7
Message-id: 1582537164-764-3-git-send-email-sai.pavan.boddu@xilinx.com
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
include/hw/timer/xlnx-zynqmp-rtc.h | 2 ++
12
hw/cpu/a9mpcore.c | 4 ++++
13
hw/timer/xlnx-zynqmp-rtc.c | 58 ++++++++++++++++++++++++++++++++++++++
13
1 file changed, 4 insertions(+)
14
hw/timer/trace-events | 3 ++
15
3 files changed, 63 insertions(+)
16
14
17
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
15
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/xlnx-zynqmp-rtc.h
17
--- a/hw/cpu/a9mpcore.c
20
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
18
+++ b/hw/cpu/a9mpcore.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPRTC {
19
@@ -XXX,XX +XXX,XX @@
22
qemu_irq irq_rtc_int;
20
#include "hw/qdev-properties.h"
23
qemu_irq irq_addr_error_int;
21
#include "hw/core/cpu.h"
24
22
25
+ uint32_t tick_offset;
23
+#define A9_GIC_NUM_PRIORITY_BITS 5
26
+
24
+
27
uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
25
static void a9mp_priv_set_irq(void *opaque, int irq, int level)
28
RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
29
} XlnxZynqMPRTC;
30
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/xlnx-zynqmp-rtc.c
33
+++ b/hw/timer/xlnx-zynqmp-rtc.c
34
@@ -XXX,XX +XXX,XX @@
35
#include "hw/register.h"
36
#include "qemu/bitops.h"
37
#include "qemu/log.h"
38
+#include "hw/ptimer.h"
39
+#include "qemu/cutils.h"
40
+#include "sysemu/sysemu.h"
41
+#include "trace.h"
42
#include "hw/timer/xlnx-zynqmp-rtc.h"
43
44
#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
45
@@ -XXX,XX +XXX,XX @@ static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
46
qemu_set_irq(s->irq_addr_error_int, pending);
47
}
48
49
+static uint32_t rtc_get_count(XlnxZynqMPRTC *s)
50
+{
51
+ int64_t now = qemu_clock_get_ns(rtc_clock);
52
+ return s->tick_offset + now / NANOSECONDS_PER_SECOND;
53
+}
54
+
55
+static uint64_t current_time_postr(RegisterInfo *reg, uint64_t val64)
56
+{
57
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
58
+
59
+ return rtc_get_count(s);
60
+}
61
+
62
static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
63
{
26
{
64
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
27
A9MPPrivState *s = (A9MPPrivState *)opaque;
65
@@ -XXX,XX +XXX,XX @@ static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
28
@@ -XXX,XX +XXX,XX @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
66
29
gicdev = DEVICE(&s->gic);
67
static const RegisterAccessInfo rtc_regs_info[] = {
30
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
68
{ .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
31
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
69
+ .unimp = MAKE_64BIT_MASK(0, 32),
32
+ qdev_prop_set_uint32(gicdev, "num-priority-bits",
70
},{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
33
+ A9_GIC_NUM_PRIORITY_BITS);
71
.ro = 0xffffffff,
34
72
+ .post_read = current_time_postr,
35
/* Make the GIC's TZ support match the CPUs. We assume that
73
},{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
36
* either all the CPUs have TZ, or none do.
74
+ .unimp = MAKE_64BIT_MASK(0, 32),
75
},{ .name = "CALIB_READ", .addr = A_CALIB_READ,
76
.ro = 0x1fffff,
77
},{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
78
.ro = 0xffffffff,
79
+ .post_read = current_time_postr,
80
},{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
81
.ro = 0xffff,
82
},{ .name = "ALARM", .addr = A_ALARM,
83
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
84
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
85
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
86
RegisterInfoArray *reg_array;
87
+ struct tm current_tm;
88
89
memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
90
XLNX_ZYNQMP_RTC_R_MAX * 4);
91
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
92
sysbus_init_mmio(sbd, &s->iomem);
93
sysbus_init_irq(sbd, &s->irq_rtc_int);
94
sysbus_init_irq(sbd, &s->irq_addr_error_int);
95
+
96
+ qemu_get_timedate(&current_tm, 0);
97
+ s->tick_offset = mktimegm(&current_tm) -
98
+ qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
99
+
100
+ trace_xlnx_zynqmp_rtc_gettime(current_tm.tm_year, current_tm.tm_mon,
101
+ current_tm.tm_mday, current_tm.tm_hour,
102
+ current_tm.tm_min, current_tm.tm_sec);
103
+}
104
+
105
+static int rtc_pre_save(void *opaque)
106
+{
107
+ XlnxZynqMPRTC *s = opaque;
108
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
109
+
110
+ /* Add the time at migration */
111
+ s->tick_offset = s->tick_offset + now;
112
+
113
+ return 0;
114
+}
115
+
116
+static int rtc_post_load(void *opaque, int version_id)
117
+{
118
+ XlnxZynqMPRTC *s = opaque;
119
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
120
+
121
+ /* Subtract the time after migration. This combined with the pre_save
122
+ * action results in us having subtracted the time that the guest was
123
+ * stopped to the offset.
124
+ */
125
+ s->tick_offset = s->tick_offset - now;
126
+
127
+ return 0;
128
}
129
130
static const VMStateDescription vmstate_rtc = {
131
.name = TYPE_XLNX_ZYNQMP_RTC,
132
.version_id = 1,
133
.minimum_version_id = 1,
134
+ .pre_save = rtc_pre_save,
135
+ .post_load = rtc_post_load,
136
.fields = (VMStateField[]) {
137
VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
138
+ VMSTATE_UINT32(tick_offset, XlnxZynqMPRTC),
139
VMSTATE_END_OF_LIST(),
140
}
141
};
142
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
143
index XXXXXXX..XXXXXXX 100644
144
--- a/hw/timer/trace-events
145
+++ b/hw/timer/trace-events
146
@@ -XXX,XX +XXX,XX @@ systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr
147
cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
148
cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
149
cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
150
+
151
+# hw/timer/xlnx-zynqmp-rtc.c
152
+xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
153
--
37
--
154
2.16.2
38
2.20.1
155
39
156
40
diff view generated by jsdifflib
1
The or-irq.h header file is missing the customary guard against
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
multiple inclusion, which means compilation fails if it gets
3
included twice. Fix the omission.
4
2
3
The GIC built into the ARM11MPCore is always implemented with 4
4
priority bits; set the GIC property accordingly.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1582537164-764-4-git-send-email-sai.pavan.boddu@xilinx.com
9
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: tweaked commit message]
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-11-peter.maydell@linaro.org
9
---
13
---
10
include/hw/or-irq.h | 5 +++++
14
hw/cpu/arm11mpcore.c | 5 +++++
11
1 file changed, 5 insertions(+)
15
1 file changed, 5 insertions(+)
12
16
13
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
17
diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/or-irq.h
19
--- a/hw/cpu/arm11mpcore.c
16
+++ b/include/hw/or-irq.h
20
+++ b/hw/cpu/arm11mpcore.c
17
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
18
* THE SOFTWARE.
22
#include "hw/irq.h"
19
*/
23
#include "hw/qdev-properties.h"
20
24
21
+#ifndef HW_OR_IRQ_H
25
+#define ARM11MPCORE_NUM_GIC_PRIORITY_BITS 4
22
+#define HW_OR_IRQ_H
26
27
static void mpcore_priv_set_irq(void *opaque, int irq, int level)
28
{
29
@@ -XXX,XX +XXX,XX @@ static void mpcore_priv_realize(DeviceState *dev, Error **errp)
30
31
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
32
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
33
+ qdev_prop_set_uint32(gicdev, "num-priority-bits",
34
+ ARM11MPCORE_NUM_GIC_PRIORITY_BITS);
23
+
35
+
24
#include "hw/irq.h"
25
#include "hw/sysbus.h"
26
#include "qom/object.h"
27
@@ -XXX,XX +XXX,XX @@ struct OrIRQState {
28
bool levels[MAX_OR_LINES];
29
uint16_t num_lines;
30
};
31
+
36
+
32
+#endif
37
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
38
if (err != NULL) {
39
error_propagate(errp, err);
33
--
40
--
34
2.16.2
41
2.20.1
35
42
36
43
diff view generated by jsdifflib
1
In v8M, the Implementation Defined Attribution Unit (IDAU) is
1
From: Richard Henderson <richard.henderson@linaro.org>
2
a small piece of hardware typically implemented in the SoC
2
3
which provides board or SoC specific security attribution
3
Use this in the places that were checking ARM_FEATURE_VFP, and
4
information for each address that the CPU performs MPU/SAU
4
are obviously testing for the existance of the register set
5
checks on. For QEMU, we model this with a QOM interface which
5
as opposed to testing for some particular instruction extension.
6
is implemented by the board or SoC object and connected to
6
7
the CPU using a link property.
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
This commit defines the new interface class, adds the link
9
Message-id: 20200224222232.13807-2-richard.henderson@linaro.org
10
property to the CPU object, and makes the SAU checking
11
code call the IDAU interface if one is present.
12
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>
15
Message-id: 20180220180325.29818-5-peter.maydell@linaro.org
16
---
11
---
17
target/arm/cpu.h | 3 +++
12
target/arm/cpu.h | 9 +++++++++
18
target/arm/idau.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++
13
hw/intc/armv7m_nvic.c | 20 ++++++++++----------
19
target/arm/cpu.c | 15 +++++++++++++
14
linux-user/arm/signal.c | 4 ++--
20
target/arm/helper.c | 28 +++++++++++++++++++++---
15
target/arm/arch_dump.c | 11 ++++++-----
21
4 files changed, 104 insertions(+), 3 deletions(-)
16
target/arm/cpu.c | 4 ++--
22
create mode 100644 target/arm/idau.h
17
target/arm/helper.c | 4 ++--
18
target/arm/m_helper.c | 11 ++++++-----
19
7 files changed, 37 insertions(+), 26 deletions(-)
23
20
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
23
--- a/target/arm/cpu.h
27
+++ b/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
28
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
25
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
29
/* MemoryRegion to use for secure physical accesses */
26
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
30
MemoryRegion *secure_memory;
27
}
31
28
32
+ /* For v8M, pointer to the IDAU interface provided by board/SoC */
29
+static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id)
33
+ Object *idau;
30
+{
31
+ /*
32
+ * Return true if either VFP or SIMD is implemented.
33
+ * In this case, a minimum of VFP w/ D0-D15.
34
+ */
35
+ return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0;
36
+}
34
+
37
+
35
/* 'compatible' string for this CPU for Linux device trees */
38
static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id)
36
const char *dtb_compatible;
39
{
37
40
/* Return true if D16-D31 are implemented */
38
diff --git a/target/arm/idau.h b/target/arm/idau.h
41
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
39
new file mode 100644
42
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX
43
--- a/hw/intc/armv7m_nvic.c
41
--- /dev/null
44
+++ b/hw/intc/armv7m_nvic.c
42
+++ b/target/arm/idau.h
45
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
43
@@ -XXX,XX +XXX,XX @@
46
case 0xd84: /* CSSELR */
44
+/*
47
return cpu->env.v7m.csselr[attrs.secure];
45
+ * QEMU ARM CPU -- interface for the Arm v8M IDAU
48
case 0xd88: /* CPACR */
46
+ *
49
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
47
+ * Copyright (c) 2018 Linaro Ltd
50
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
48
+ *
51
return 0;
49
+ * This program is free software; you can redistribute it and/or
52
}
50
+ * modify it under the terms of the GNU General Public License
53
return cpu->env.v7m.cpacr[attrs.secure];
51
+ * as published by the Free Software Foundation; either version 2
54
case 0xd8c: /* NSACR */
52
+ * of the License, or (at your option) any later version.
55
- if (!attrs.secure || !arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
53
+ *
56
+ if (!attrs.secure || !cpu_isar_feature(aa32_vfp_simd, cpu)) {
54
+ * This program is distributed in the hope that it will be useful,
57
return 0;
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
}
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59
return cpu->env.v7m.nsacr;
57
+ * GNU General Public License for more details.
60
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
58
+ *
61
}
59
+ * You should have received a copy of the GNU General Public License
62
return cpu->env.v7m.sfar;
60
+ * along with this program; if not, see
63
case 0xf34: /* FPCCR */
61
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
64
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
62
+ *
65
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
63
+ * In the v8M architecture, the IDAU is a small piece of hardware
66
return 0;
64
+ * typically implemented in the SoC which provides board or SoC
67
}
65
+ * specific security attribution information for each address that
68
if (attrs.secure) {
66
+ * the CPU performs MPU/SAU checks on. For QEMU, we model this with a
69
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
67
+ * QOM interface which is implemented by the board or SoC object and
70
return value;
68
+ * connected to the CPU using a link property.
71
}
69
+ */
72
case 0xf38: /* FPCAR */
70
+
73
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
71
+#ifndef TARGET_ARM_IDAU_H
74
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
72
+#define TARGET_ARM_IDAU_H
75
return 0;
73
+
76
}
74
+#include "qom/object.h"
77
return cpu->env.v7m.fpcar[attrs.secure];
75
+
78
case 0xf3c: /* FPDSCR */
76
+#define TYPE_IDAU_INTERFACE "idau-interface"
79
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
77
+#define IDAU_INTERFACE(obj) \
80
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
78
+ INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE)
81
return 0;
79
+#define IDAU_INTERFACE_CLASS(class) \
82
}
80
+ OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE)
83
return cpu->env.v7m.fpdscr[attrs.secure];
81
+#define IDAU_INTERFACE_GET_CLASS(obj) \
84
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
82
+ OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE)
85
}
83
+
86
break;
84
+typedef struct IDAUInterface {
87
case 0xd88: /* CPACR */
85
+ Object parent;
88
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
86
+} IDAUInterface;
89
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
87
+
90
/* We implement only the Floating Point extension's CP10/CP11 */
88
+#define IREGION_NOTVALID -1
91
cpu->env.v7m.cpacr[attrs.secure] = value & (0xf << 20);
89
+
92
}
90
+typedef struct IDAUInterfaceClass {
93
break;
91
+ InterfaceClass parent;
94
case 0xd8c: /* NSACR */
92
+
95
- if (attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
93
+ /* Check the specified address and return the IDAU security information
96
+ if (attrs.secure && cpu_isar_feature(aa32_vfp_simd, cpu)) {
94
+ * for it by filling in iregion, exempt, ns and nsc:
97
/* We implement only the Floating Point extension's CP10/CP11 */
95
+ * iregion: IDAU region number, or IREGION_NOTVALID if not valid
98
cpu->env.v7m.nsacr = value & (3 << 10);
96
+ * exempt: true if address is exempt from security attribution
99
}
97
+ * ns: true if the address is NonSecure
100
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
98
+ * nsc: true if the address is NonSecure-callable
101
break;
99
+ */
102
}
100
+ void (*check)(IDAUInterface *ii, uint32_t address, int *iregion,
103
case 0xf34: /* FPCCR */
101
+ bool *exempt, bool *ns, bool *nsc);
104
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
102
+} IDAUInterfaceClass;
105
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
103
+
106
/* Not all bits here are banked. */
104
+#endif
107
uint32_t fpccr_s;
108
109
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
110
}
111
break;
112
case 0xf38: /* FPCAR */
113
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
114
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
115
value &= ~7;
116
cpu->env.v7m.fpcar[attrs.secure] = value;
117
}
118
break;
119
case 0xf3c: /* FPDSCR */
120
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
121
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
122
value &= 0x07c00000;
123
cpu->env.v7m.fpdscr[attrs.secure] = value;
124
}
125
diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/linux-user/arm/signal.c
128
+++ b/linux-user/arm/signal.c
129
@@ -XXX,XX +XXX,XX @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
130
setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
131
/* Save coprocessor signal frame. */
132
regspace = uc->tuc_regspace;
133
- if (arm_feature(env, ARM_FEATURE_VFP)) {
134
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
135
regspace = setup_sigframe_v2_vfp(regspace, env);
136
}
137
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
138
@@ -XXX,XX +XXX,XX @@ static int do_sigframe_return_v2(CPUARMState *env,
139
140
/* Restore coprocessor signal frame */
141
regspace = uc->tuc_regspace;
142
- if (arm_feature(env, ARM_FEATURE_VFP)) {
143
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
144
regspace = restore_sigframe_v2_vfp(env, regspace);
145
if (!regspace) {
146
return 1;
147
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/target/arm/arch_dump.c
150
+++ b/target/arm/arch_dump.c
151
@@ -XXX,XX +XXX,XX @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
152
int cpuid, void *opaque)
153
{
154
struct arm_note note;
155
- CPUARMState *env = &ARM_CPU(cs)->env;
156
+ ARMCPU *cpu = ARM_CPU(cs);
157
+ CPUARMState *env = &cpu->env;
158
DumpState *s = opaque;
159
- int ret, i, fpvalid = !!arm_feature(env, ARM_FEATURE_VFP);
160
+ int ret, i;
161
+ bool fpvalid = cpu_isar_feature(aa32_vfp_simd, cpu);
162
163
arm_note_init(&note, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus));
164
165
@@ -XXX,XX +XXX,XX @@ int cpu_get_dump_info(ArchDumpInfo *info,
166
ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
167
{
168
ARMCPU *cpu = ARM_CPU(first_cpu);
169
- CPUARMState *env = &cpu->env;
170
size_t note_size;
171
172
if (class == ELFCLASS64) {
173
@@ -XXX,XX +XXX,XX @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
174
note_size += AARCH64_PRFPREG_NOTE_SIZE;
175
#ifdef TARGET_AARCH64
176
if (cpu_isar_feature(aa64_sve, cpu)) {
177
- note_size += AARCH64_SVE_NOTE_SIZE(env);
178
+ note_size += AARCH64_SVE_NOTE_SIZE(&cpu->env);
179
}
180
#endif
181
} else {
182
note_size = ARM_PRSTATUS_NOTE_SIZE;
183
- if (arm_feature(env, ARM_FEATURE_VFP)) {
184
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
185
note_size += ARM_VFP_NOTE_SIZE;
186
}
187
}
105
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
188
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
106
index XXXXXXX..XXXXXXX 100644
189
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/cpu.c
190
--- a/target/arm/cpu.c
108
+++ b/target/arm/cpu.c
191
+++ b/target/arm/cpu.c
109
@@ -XXX,XX +XXX,XX @@
192
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
110
*/
193
env->v7m.ccr[M_REG_S] |= R_V7M_CCR_UNALIGN_TRP_MASK;
111
194
}
112
#include "qemu/osdep.h"
195
113
+#include "target/arm/idau.h"
196
- if (arm_feature(env, ARM_FEATURE_VFP)) {
114
#include "qemu/error-report.h"
197
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
115
#include "qapi/error.h"
198
env->v7m.fpccr[M_REG_NS] = R_V7M_FPCCR_ASPEN_MASK;
116
#include "cpu.h"
199
env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
117
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
200
R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
118
}
201
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
119
}
202
int numvfpregs = 0;
120
203
if (cpu_isar_feature(aa32_simd_r32, cpu)) {
121
+ if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) {
204
numvfpregs = 32;
122
+ object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->idau,
205
- } else if (arm_feature(env, ARM_FEATURE_VFP)) {
123
+ qdev_prop_allow_set_link_before_realize,
206
+ } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
124
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
207
numvfpregs = 16;
125
+ &error_abort);
208
}
126
+ }
209
for (i = 0; i < numvfpregs; i++) {
127
+
128
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
129
&error_abort);
130
}
131
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
132
.class_init = arm_cpu_class_init,
133
};
134
135
+static const TypeInfo idau_interface_type_info = {
136
+ .name = TYPE_IDAU_INTERFACE,
137
+ .parent = TYPE_INTERFACE,
138
+ .class_size = sizeof(IDAUInterfaceClass),
139
+};
140
+
141
static void arm_cpu_register_types(void)
142
{
143
const ARMCPUInfo *info = arm_cpus;
144
145
type_register_static(&arm_cpu_type_info);
146
+ type_register_static(&idau_interface_type_info);
147
148
while (info->name) {
149
cpu_register(info);
150
diff --git a/target/arm/helper.c b/target/arm/helper.c
210
diff --git a/target/arm/helper.c b/target/arm/helper.c
151
index XXXXXXX..XXXXXXX 100644
211
index XXXXXXX..XXXXXXX 100644
152
--- a/target/arm/helper.c
212
--- a/target/arm/helper.c
153
+++ b/target/arm/helper.c
213
+++ b/target/arm/helper.c
154
@@ -XXX,XX +XXX,XX @@
214
@@ -XXX,XX +XXX,XX @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
155
#include "qemu/osdep.h"
215
* ASEDIS [31] and D32DIS [30] are both UNK/SBZP without VFP.
156
+#include "target/arm/idau.h"
216
* TRCDIS [28] is RAZ/WI since we do not implement a trace macrocell.
157
#include "trace.h"
217
*/
158
#include "cpu.h"
218
- if (arm_feature(env, ARM_FEATURE_VFP)) {
159
#include "internals.h"
219
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
160
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
220
/* VFP coprocessor: cp10 & cp11 [23:20] */
221
mask |= (1 << 31) | (1 << 30) | (0xf << 20);
222
223
@@ -XXX,XX +XXX,XX @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
224
} else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
225
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
226
35, "arm-vfp3.xml", 0);
227
- } else if (arm_feature(env, ARM_FEATURE_VFP)) {
228
+ } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
229
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
230
19, "arm-vfp.xml", 0);
231
}
232
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/target/arm/m_helper.c
235
+++ b/target/arm/m_helper.c
236
@@ -XXX,XX +XXX,XX @@ static uint32_t v7m_integrity_sig(CPUARMState *env, uint32_t lr)
161
*/
237
*/
162
ARMCPU *cpu = arm_env_get_cpu(env);
238
uint32_t sig = 0xfefa125a;
163
int r;
239
164
+ bool idau_exempt = false, idau_ns = true, idau_nsc = true;
240
- if (!arm_feature(env, ARM_FEATURE_VFP) || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
165
+ int idau_region = IREGION_NOTVALID;
241
+ if (!cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))
166
242
+ || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
167
- /* TODO: implement IDAU */
243
sig |= 1;
168
+ if (cpu->idau) {
244
}
169
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
245
return sig;
170
+ IDAUInterface *ii = IDAU_INTERFACE(cpu->idau);
246
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
171
+
247
172
+ iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns,
248
if (dotailchain) {
173
+ &idau_nsc);
249
/* Sanitize LR FType and PREFIX bits */
174
+ }
250
- if (!arm_feature(env, ARM_FEATURE_VFP)) {
175
251
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
176
if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
252
lr |= R_V7M_EXCRET_FTYPE_MASK;
177
/* 0xf0000000..0xffffffff is always S for insn fetches */
253
}
178
return;
254
lr = deposit32(lr, 24, 8, 0xff);
179
}
255
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
180
256
181
- if (v8m_is_sau_exempt(env, address, access_type)) {
257
ftype = excret & R_V7M_EXCRET_FTYPE_MASK;
182
+ if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) {
258
183
sattrs->ns = !regime_is_secure(env, mmu_idx);
259
- if (!arm_feature(env, ARM_FEATURE_VFP) && !ftype) {
184
return;
260
+ if (!ftype && !cpu_isar_feature(aa32_vfp_simd, cpu)) {
185
}
261
qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero FTYPE in exception "
186
262
"exit PC value 0x%" PRIx32 " is UNPREDICTABLE "
187
+ if (idau_region != IREGION_NOTVALID) {
263
"if FPU not present\n",
188
+ sattrs->irvalid = true;
264
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
189
+ sattrs->iregion = idau_region;
265
* SFPA is RAZ/WI from NS. FPCA is RO if NSACR.CP10 == 0,
190
+ }
266
* RES0 if the FPU is not present, and is stored in the S bank
191
+
267
*/
192
switch (env->sau.ctrl & 3) {
268
- if (arm_feature(env, ARM_FEATURE_VFP) &&
193
case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
269
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env)) &&
194
break;
270
extract32(env->v7m.nsacr, 10, 1)) {
195
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
271
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
196
}
272
env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
197
}
273
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
198
274
env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
199
- /* TODO when we support the IDAU then it may override the result here */
275
env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
200
+ /* The IDAU will override the SAU lookup results if it specifies
276
}
201
+ * higher security than the SAU does.
277
- if (arm_feature(env, ARM_FEATURE_VFP)) {
202
+ */
278
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
203
+ if (!idau_ns) {
279
/*
204
+ if (sattrs->ns || (!idau_nsc && sattrs->nsc)) {
280
* SFPA is RAZ/WI from NS or if no FPU.
205
+ sattrs->ns = false;
281
* FPCA is RO if NSACR.CP10 == 0, RES0 if the FPU is not present.
206
+ sattrs->nsc = idau_nsc;
207
+ }
208
+ }
209
break;
210
}
211
}
212
--
282
--
213
2.16.2
283
2.20.1
214
284
215
285
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
3
The old name, isar_feature_aa32_fpdp, does not reflect
4
4
that the test includes VFPv2. We will introduce another
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
feature tests for VFPv3.
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180228193125.20577-2-richard.henderson@linaro.org
9
Message-id: 20200224222232.13807-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
target/arm/cpu.h | 1 +
12
target/arm/cpu.h | 4 ++--
12
linux-user/elfload.c | 1 +
13
target/arm/translate-vfp.inc.c | 40 +++++++++++++++++-----------------
13
2 files changed, 2 insertions(+)
14
2 files changed, 22 insertions(+), 22 deletions(-)
14
15
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ enum arm_features {
20
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
20
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
21
return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
21
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
22
}
22
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
23
23
+ ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
24
-static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id)
24
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
25
+static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
25
};
26
{
26
27
- /* Return true if CPU supports double precision floating point */
27
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
28
+ /* Return true if CPU supports double precision floating point, VFPv2 */
29
return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
30
}
31
32
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
28
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
29
--- a/linux-user/elfload.c
34
--- a/target/arm/translate-vfp.inc.c
30
+++ b/linux-user/elfload.c
35
+++ b/target/arm/translate-vfp.inc.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
32
GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
37
return false;
33
GET_FEATURE(ARM_FEATURE_V8_FP16,
38
}
34
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
39
35
+ GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
40
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
36
#undef GET_FEATURE
41
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
37
42
return false;
38
return hwcaps;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
46
return false;
47
}
48
49
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
50
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
51
return false;
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
55
return false;
56
}
57
58
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
59
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
60
return false;
61
}
62
63
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
64
return false;
65
}
66
67
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
68
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
69
return false;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
73
return false;
74
}
75
76
- if (!dc_isar_feature(aa32_fpdp, s)) {
77
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
78
return false;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
82
return false;
83
}
84
85
- if (!dc_isar_feature(aa32_fpdp, s)) {
86
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
87
return false;
88
}
89
90
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
91
return false;
92
}
93
94
- if (!dc_isar_feature(aa32_fpdp, s)) {
95
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
96
return false;
97
}
98
99
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
100
return false;
101
}
102
103
- if (!dc_isar_feature(aa32_fpdp, s)) {
104
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
105
return false;
106
}
107
108
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
109
return false;
110
}
111
112
- if (!dc_isar_feature(aa32_fpdp, s)) {
113
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
114
return false;
115
}
116
117
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
118
return false;
119
}
120
121
- if (!dc_isar_feature(aa32_fpdp, s)) {
122
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
123
return false;
124
}
125
126
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
127
return false;
128
}
129
130
- if (!dc_isar_feature(aa32_fpdp, s)) {
131
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
132
return false;
133
}
134
135
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
136
return false;
137
}
138
139
- if (!dc_isar_feature(aa32_fpdp, s)) {
140
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
141
return false;
142
}
143
144
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
145
return false;
146
}
147
148
- if (!dc_isar_feature(aa32_fpdp, s)) {
149
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
150
return false;
151
}
152
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
154
return false;
155
}
156
157
- if (!dc_isar_feature(aa32_fpdp, s)) {
158
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
159
return false;
160
}
161
162
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
163
return false;
164
}
165
166
- if (!dc_isar_feature(aa32_fpdp, s)) {
167
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
168
return false;
169
}
170
171
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
172
return false;
173
}
174
175
- if (!dc_isar_feature(aa32_fpdp, s)) {
176
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
177
return false;
178
}
179
180
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
181
return false;
182
}
183
184
- if (!dc_isar_feature(aa32_fpdp, s)) {
185
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
186
return false;
187
}
188
189
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
190
return false;
191
}
192
193
- if (!dc_isar_feature(aa32_fpdp, s)) {
194
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
195
return false;
196
}
197
198
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
199
return false;
200
}
201
202
- if (!dc_isar_feature(aa32_fpdp, s)) {
203
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
204
return false;
205
}
206
207
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
208
return false;
209
}
210
211
- if (!dc_isar_feature(aa32_fpdp, s)) {
212
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
213
return false;
214
}
215
39
--
216
--
40
2.16.2
217
2.20.1
41
218
42
219
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
We will shortly use these to test for VFPv2 and VFPv3
4
in different situations.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-12-richard.henderson@linaro.org
8
Message-id: 20200224222232.13807-4-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper.h | 7 ++++
11
target/arm/cpu.h | 18 ++++++++++++++++++
9
target/arm/translate-a64.c | 48 ++++++++++++++++++++++-
12
1 file changed, 18 insertions(+)
10
target/arm/vec_helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 151 insertions(+), 1 deletion(-)
12
13
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
16
--- a/target/arm/cpu.h
16
+++ b/target/arm/helper.h
17
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
18
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
18
DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
19
return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
19
void, ptr, ptr, ptr, ptr, i32)
20
21
+DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG,
22
+ void, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+
28
#ifdef TARGET_AARCH64
29
#include "helper-a64.h"
30
#endif
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-a64.c
34
+++ b/target/arm/translate-a64.c
35
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
36
is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
37
}
20
}
38
21
39
+/* Expand a 3-operand + fpstatus pointer + simd data value operation using
22
+static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id)
40
+ * an out-of-line helper.
41
+ */
42
+static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
43
+ int rm, bool is_fp16, int data,
44
+ gen_helper_gvec_3_ptr *fn)
45
+{
23
+{
46
+ TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
24
+ /* Return true if CPU supports single precision floating point, VFPv2 */
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
25
+ return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0;
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), fpst,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
51
+ tcg_temp_free_ptr(fpst);
52
+}
26
+}
53
+
27
+
54
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
28
+static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id)
55
* than the 32 bit equivalent.
56
*/
57
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
58
int size = extract32(insn, 22, 2);
59
bool u = extract32(insn, 29, 1);
60
bool is_q = extract32(insn, 30, 1);
61
- int feature;
62
+ int feature, rot;
63
64
switch (u * 16 + opcode) {
65
case 0x10: /* SQRDMLAH (vector) */
66
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
}
68
feature = ARM_FEATURE_V8_RDM;
69
break;
70
+ case 0xc: /* FCADD, #90 */
71
+ case 0xe: /* FCADD, #270 */
72
+ if (size == 0
73
+ || (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
74
+ || (size == 3 && !is_q)) {
75
+ unallocated_encoding(s);
76
+ return;
77
+ }
78
+ feature = ARM_FEATURE_V8_FCMA;
79
+ break;
80
default:
81
unallocated_encoding(s);
82
return;
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
84
}
85
return;
86
87
+ case 0xc: /* FCADD, #90 */
88
+ case 0xe: /* FCADD, #270 */
89
+ rot = extract32(opcode, 1, 1);
90
+ switch (size) {
91
+ case 1:
92
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
93
+ gen_helper_gvec_fcaddh);
94
+ break;
95
+ case 2:
96
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
97
+ gen_helper_gvec_fcadds);
98
+ break;
99
+ case 3:
100
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
101
+ gen_helper_gvec_fcaddd);
102
+ break;
103
+ default:
104
+ g_assert_not_reached();
105
+ }
106
+ return;
107
+
108
default:
109
g_assert_not_reached();
110
}
111
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/vec_helper.c
114
+++ b/target/arm/vec_helper.c
115
@@ -XXX,XX +XXX,XX @@
116
#include "exec/exec-all.h"
117
#include "exec/helper-proto.h"
118
#include "tcg/tcg-gvec-desc.h"
119
+#include "fpu/softfloat.h"
120
121
122
+/* Note that vector data is stored in host-endian 64-bit chunks,
123
+ so addressing units smaller than that needs a host-endian fixup. */
124
+#ifdef HOST_WORDS_BIGENDIAN
125
+#define H1(x) ((x) ^ 7)
126
+#define H2(x) ((x) ^ 3)
127
+#define H4(x) ((x) ^ 1)
128
+#else
129
+#define H1(x) (x)
130
+#define H2(x) (x)
131
+#define H4(x) (x)
132
+#endif
133
+
134
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
135
136
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
137
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
138
}
139
clear_tail(d, opr_sz, simd_maxsz(desc));
140
}
141
+
142
+void HELPER(gvec_fcaddh)(void *vd, void *vn, void *vm,
143
+ void *vfpst, uint32_t desc)
144
+{
29
+{
145
+ uintptr_t opr_sz = simd_oprsz(desc);
30
+ /* Return true if CPU supports single precision floating point, VFPv3 */
146
+ float16 *d = vd;
31
+ return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2;
147
+ float16 *n = vn;
148
+ float16 *m = vm;
149
+ float_status *fpst = vfpst;
150
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
151
+ uint32_t neg_imag = neg_real ^ 1;
152
+ uintptr_t i;
153
+
154
+ /* Shift boolean to the sign bit so we can xor to negate. */
155
+ neg_real <<= 15;
156
+ neg_imag <<= 15;
157
+
158
+ for (i = 0; i < opr_sz / 2; i += 2) {
159
+ float16 e0 = n[H2(i)];
160
+ float16 e1 = m[H2(i + 1)] ^ neg_imag;
161
+ float16 e2 = n[H2(i + 1)];
162
+ float16 e3 = m[H2(i)] ^ neg_real;
163
+
164
+ d[H2(i)] = float16_add(e0, e1, fpst);
165
+ d[H2(i + 1)] = float16_add(e2, e3, fpst);
166
+ }
167
+ clear_tail(d, opr_sz, simd_maxsz(desc));
168
+}
32
+}
169
+
33
+
170
+void HELPER(gvec_fcadds)(void *vd, void *vn, void *vm,
34
static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
171
+ void *vfpst, uint32_t desc)
35
{
36
/* Return true if CPU supports double precision floating point, VFPv2 */
37
return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
38
}
39
40
+static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id)
172
+{
41
+{
173
+ uintptr_t opr_sz = simd_oprsz(desc);
42
+ /* Return true if CPU supports double precision floating point, VFPv3 */
174
+ float32 *d = vd;
43
+ return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2;
175
+ float32 *n = vn;
176
+ float32 *m = vm;
177
+ float_status *fpst = vfpst;
178
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
179
+ uint32_t neg_imag = neg_real ^ 1;
180
+ uintptr_t i;
181
+
182
+ /* Shift boolean to the sign bit so we can xor to negate. */
183
+ neg_real <<= 31;
184
+ neg_imag <<= 31;
185
+
186
+ for (i = 0; i < opr_sz / 4; i += 2) {
187
+ float32 e0 = n[H4(i)];
188
+ float32 e1 = m[H4(i + 1)] ^ neg_imag;
189
+ float32 e2 = n[H4(i + 1)];
190
+ float32 e3 = m[H4(i)] ^ neg_real;
191
+
192
+ d[H4(i)] = float32_add(e0, e1, fpst);
193
+ d[H4(i + 1)] = float32_add(e2, e3, fpst);
194
+ }
195
+ clear_tail(d, opr_sz, simd_maxsz(desc));
196
+}
44
+}
197
+
45
+
198
+void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
46
/*
199
+ void *vfpst, uint32_t desc)
47
* We always set the FP and SIMD FP16 fields to indicate identical
200
+{
48
* levels of support (assuming SIMD is implemented at all), so
201
+ uintptr_t opr_sz = simd_oprsz(desc);
202
+ float64 *d = vd;
203
+ float64 *n = vn;
204
+ float64 *m = vm;
205
+ float_status *fpst = vfpst;
206
+ uint64_t neg_real = extract64(desc, SIMD_DATA_SHIFT, 1);
207
+ uint64_t neg_imag = neg_real ^ 1;
208
+ uintptr_t i;
209
+
210
+ /* Shift boolean to the sign bit so we can xor to negate. */
211
+ neg_real <<= 63;
212
+ neg_imag <<= 63;
213
+
214
+ for (i = 0; i < opr_sz / 8; i += 2) {
215
+ float64 e0 = n[i];
216
+ float64 e1 = m[i + 1] ^ neg_imag;
217
+ float64 e2 = n[i + 1];
218
+ float64 e3 = m[i] ^ neg_real;
219
+
220
+ d[i] = float64_add(e0, e1, fpst);
221
+ d[i + 1] = float64_add(e2, e3, fpst);
222
+ }
223
+ clear_tail(d, opr_sz, simd_maxsz(desc));
224
+}
225
--
49
--
226
2.16.2
50
2.20.1
227
51
228
52
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
We cannot easily create "any" functions for these, because the
4
ID_AA64PFR0 fields for FP and SIMD signal "enabled" with zero.
5
Which means that an aarch32-only cpu will return incorrect results
6
when testing the aarch64 registers.
7
8
To use these, we must either have context or additionally test
9
vs ARM_FEATURE_AARCH64.
4
10
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180228193125.20577-17-richard.henderson@linaro.org
13
Message-id: 20200224222232.13807-5-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
15
---
10
target/arm/cpu.c | 1 +
16
target/arm/cpu.h | 11 +++++++++++
11
target/arm/cpu64.c | 1 +
17
target/arm/cpu.c | 9 ++++++---
12
2 files changed, 2 insertions(+)
18
target/arm/machine.c | 5 +++--
19
3 files changed, 20 insertions(+), 5 deletions(-)
13
20
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id)
26
return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2;
27
}
28
29
+static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id)
30
+{
31
+ return isar_feature_aa32_fpsp_v2(id) || isar_feature_aa32_fpdp_v2(id);
32
+}
33
+
34
/*
35
* We always set the FP and SIMD FP16 fields to indicate identical
36
* levels of support (assuming SIMD is implemented at all), so
37
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
38
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2;
39
}
40
41
+static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
42
+{
43
+ /* We always set the AdvSIMD and FP fields identically. */
44
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf;
45
+}
46
+
47
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
48
{
49
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
50
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
52
--- a/target/arm/cpu.c
17
+++ b/target/arm/cpu.c
53
+++ b/target/arm/cpu.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
54
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
19
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
55
* KVM does not currently allow us to lie to the guest about its
20
set_feature(&cpu->env, ARM_FEATURE_CRC);
56
* ID/feature registers, so the guest always sees what the host has.
21
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
57
*/
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
58
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
23
cpu->midr = 0xffffffff;
59
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
60
+ ? cpu_isar_feature(aa64_fp_simd, cpu)
61
+ : cpu_isar_feature(aa32_vfp, cpu)) {
62
cpu->has_vfp = true;
63
if (!kvm_enabled()) {
64
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_vfp_property);
65
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
66
* We rely on no XScale CPU having VFP so we can use the same bits in the
67
* TB flags field for VECSTRIDE and XSCALE_CPAR.
68
*/
69
- assert(!(arm_feature(env, ARM_FEATURE_VFP) &&
70
- arm_feature(env, ARM_FEATURE_XSCALE)));
71
+ assert(arm_feature(&cpu->env, ARM_FEATURE_AARCH64) ||
72
+ !cpu_isar_feature(aa32_vfp_simd, cpu) ||
73
+ !arm_feature(env, ARM_FEATURE_XSCALE));
74
75
if (arm_feature(env, ARM_FEATURE_V7) &&
76
!arm_feature(env, ARM_FEATURE_M) &&
77
diff --git a/target/arm/machine.c b/target/arm/machine.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/machine.c
80
+++ b/target/arm/machine.c
81
@@ -XXX,XX +XXX,XX @@
82
static bool vfp_needed(void *opaque)
83
{
84
ARMCPU *cpu = opaque;
85
- CPUARMState *env = &cpu->env;
86
87
- return arm_feature(env, ARM_FEATURE_VFP);
88
+ return (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
89
+ ? cpu_isar_feature(aa64_fp_simd, cpu)
90
+ : cpu_isar_feature(aa32_vfp_simd, cpu));
24
}
91
}
25
#endif
92
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
93
static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu64.c
29
+++ b/target/arm/cpu64.c
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
31
set_feature(&cpu->env, ARM_FEATURE_CRC);
32
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
33
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
35
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
36
cpu->dcz_blocksize = 7; /* 512 bytes */
37
}
38
--
94
--
39
2.16.2
95
2.20.1
40
96
41
97
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Shuffle the order of the checks so that we test the ISA
4
before we test anything else, such as the register arguments.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180228193125.20577-15-richard.henderson@linaro.org
8
Message-id: 20200224222232.13807-7-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-vfp.inc.c | 140 +++++++++++++++++----------------
9
1 file changed, 61 insertions(+)
12
1 file changed, 71 insertions(+), 69 deletions(-)
10
13
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
16
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate.c
17
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
16
return 0;
19
return false;
17
}
20
}
18
21
19
+/* Advanced SIMD two registers and a scalar extension.
22
- /* UNDEF accesses to D16-D31 if they don't exist */
20
+ * 31 24 23 22 20 16 12 11 10 9 8 3 0
23
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
21
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
24
- ((a->vm | a->vn | a->vd) & 0x10)) {
22
+ * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
25
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
23
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
26
return false;
24
+ *
27
}
25
+ */
28
26
+
29
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
27
+static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
30
+ /* UNDEF accesses to D16-D31 if they don't exist */
28
+{
31
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
29
+ int rd, rn, rm, rot, size, opr_sz;
32
+ ((a->vm | a->vn | a->vd) & 0x10)) {
30
+ TCGv_ptr fpst;
33
return false;
31
+ bool q;
34
}
32
+
35
33
+ q = extract32(insn, 6, 1);
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
34
+ VFP_DREG_D(rd, insn);
37
return false;
35
+ VFP_DREG_N(rn, insn);
38
}
36
+ VFP_DREG_M(rm, insn);
39
37
+ if ((rd | rn) & q) {
40
- /* UNDEF accesses to D16-D31 if they don't exist */
38
+ return 1;
41
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
39
+ }
42
- ((a->vm | a->vn | a->vd) & 0x10)) {
40
+
43
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
41
+ if ((insn & 0xff000f10) == 0xfe000800) {
44
return false;
42
+ /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
45
}
43
+ rot = extract32(insn, 20, 2);
46
44
+ size = extract32(insn, 23, 1);
47
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
48
+ /* UNDEF accesses to D16-D31 if they don't exist */
46
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
49
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
47
+ return 1;
50
+ ((a->vm | a->vn | a->vd) & 0x10)) {
48
+ }
51
return false;
49
+ } else {
52
}
50
+ return 1;
53
51
+ }
54
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
52
+
55
return false;
53
+ if (s->fp_excp_el) {
56
}
54
+ gen_exception_insn(s, 4, EXCP_UDEF,
57
55
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
58
- /* UNDEF accesses to D16-D31 if they don't exist */
56
+ return 0;
59
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
57
+ }
60
- ((a->vm | a->vd) & 0x10)) {
58
+ if (!s->vfp_enabled) {
61
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
59
+ return 1;
62
return false;
60
+ }
63
}
61
+
64
62
+ opr_sz = (1 + q) * 8;
65
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
63
+ fpst = get_fpstatus_ptr(1);
66
+ /* UNDEF accesses to D16-D31 if they don't exist */
64
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
67
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
65
+ vfp_reg_offset(1, rn),
68
+ ((a->vm | a->vd) & 0x10)) {
66
+ vfp_reg_offset(1, rm), fpst,
69
return false;
67
+ opr_sz, opr_sz, rot,
70
}
68
+ size ? gen_helper_gvec_fcmlas_idx
71
69
+ : gen_helper_gvec_fcmlah_idx);
72
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
70
+ tcg_temp_free_ptr(fpst);
73
return false;
71
+ return 0;
74
}
72
+}
75
73
+
76
- /* UNDEF accesses to D16-D31 if they don't exist */
74
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
77
- if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
78
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
79
return false;
80
}
81
82
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
83
+ /* UNDEF accesses to D16-D31 if they don't exist */
84
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
85
return false;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
89
TCGv_i64 f0, f1, fd;
90
TCGv_ptr fpst;
91
92
- /* UNDEF accesses to D16-D31 if they don't exist */
93
- if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
94
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
95
return false;
96
}
97
98
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
99
+ /* UNDEF accesses to D16-D31 if they don't exist */
100
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
101
return false;
102
}
103
104
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
105
int veclen = s->vec_len;
106
TCGv_i64 f0, fd;
107
108
- /* UNDEF accesses to D16-D31 if they don't exist */
109
- if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
110
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
111
return false;
112
}
113
114
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
115
+ /* UNDEF accesses to D16-D31 if they don't exist */
116
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
117
return false;
118
}
119
120
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
121
return false;
122
}
123
124
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
125
+ /* UNDEF accesses to D16-D31 if they don't exist. */
126
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
127
+ ((a->vd | a->vn | a->vm) & 0x10)) {
128
return false;
129
}
130
131
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
132
133
vd = a->vd;
134
135
- /* UNDEF accesses to D16-D31 if they don't exist. */
136
- if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
137
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
138
return false;
139
}
140
141
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
142
+ /* UNDEF accesses to D16-D31 if they don't exist. */
143
+ if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
144
return false;
145
}
146
147
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
75
{
148
{
76
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
149
TCGv_i64 vd, vm;
77
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
150
78
goto illegal_op;
151
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
79
}
152
+ return false;
80
return;
153
+ }
81
+ } else if ((insn & 0x0f000a00) == 0x0e000800
154
+
82
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
155
/* Vm/M bits must be zero for the Z variant */
83
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
156
if (a->z && a->vm != 0) {
84
+ goto illegal_op;
157
return false;
85
+ }
158
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
86
+ return;
159
return false;
87
} else if ((insn & 0x0fe00000) == 0x0c400000) {
160
}
88
/* Coprocessor double register transfer. */
161
89
ARCH(5TE);
162
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
163
- return false;
164
- }
165
-
166
if (!vfp_access_check(s)) {
167
return true;
168
}
169
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
170
TCGv_i32 tmp;
171
TCGv_i64 vd;
172
173
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
174
+ return false;
175
+ }
176
+
177
if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
178
return false;
179
}
180
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
181
return false;
182
}
183
184
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
185
- return false;
186
- }
187
-
188
if (!vfp_access_check(s)) {
189
return true;
190
}
191
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
192
TCGv_i32 tmp;
193
TCGv_i64 vm;
194
195
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
196
+ return false;
197
+ }
198
+
199
if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
200
return false;
201
}
202
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
203
return false;
204
}
205
206
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
207
- return false;
208
- }
209
-
210
if (!vfp_access_check(s)) {
211
return true;
212
}
213
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
214
TCGv_ptr fpst;
215
TCGv_i64 tmp;
216
217
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
218
+ return false;
219
+ }
220
+
221
if (!dc_isar_feature(aa32_vrint, s)) {
222
return false;
223
}
224
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
225
return false;
226
}
227
228
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
229
- return false;
230
- }
231
-
232
if (!vfp_access_check(s)) {
233
return true;
234
}
235
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
236
TCGv_i64 tmp;
237
TCGv_i32 tcg_rmode;
238
239
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
240
+ return false;
241
+ }
242
+
243
if (!dc_isar_feature(aa32_vrint, s)) {
244
return false;
245
}
246
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
247
return false;
248
}
249
250
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
251
- return false;
252
- }
253
-
254
if (!vfp_access_check(s)) {
255
return true;
256
}
257
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
258
TCGv_ptr fpst;
259
TCGv_i64 tmp;
260
261
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
262
+ return false;
263
+ }
264
+
265
if (!dc_isar_feature(aa32_vrint, s)) {
266
return false;
267
}
268
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
269
return false;
270
}
271
272
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
273
- return false;
274
- }
275
-
276
if (!vfp_access_check(s)) {
277
return true;
278
}
279
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
280
TCGv_i64 vd;
281
TCGv_i32 vm;
282
283
- /* UNDEF accesses to D16-D31 if they don't exist. */
284
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
285
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
286
return false;
287
}
288
289
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
290
+ /* UNDEF accesses to D16-D31 if they don't exist. */
291
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
292
return false;
293
}
294
295
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
296
TCGv_i64 vm;
297
TCGv_i32 vd;
298
299
- /* UNDEF accesses to D16-D31 if they don't exist. */
300
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
301
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
302
return false;
303
}
304
305
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
306
+ /* UNDEF accesses to D16-D31 if they don't exist. */
307
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
308
return false;
309
}
310
311
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
312
TCGv_i64 vd;
313
TCGv_ptr fpst;
314
315
- /* UNDEF accesses to D16-D31 if they don't exist. */
316
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
317
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
318
return false;
319
}
320
321
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
322
+ /* UNDEF accesses to D16-D31 if they don't exist. */
323
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
324
return false;
325
}
326
327
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
328
TCGv_i32 vd;
329
TCGv_i64 vm;
330
331
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
332
+ return false;
333
+ }
334
+
335
if (!dc_isar_feature(aa32_jscvt, s)) {
336
return false;
337
}
338
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
339
return false;
340
}
341
342
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
343
- return false;
344
- }
345
-
346
if (!vfp_access_check(s)) {
347
return true;
348
}
349
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
350
TCGv_ptr fpst;
351
int frac_bits;
352
353
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
354
+ return false;
355
+ }
356
+
357
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
358
return false;
359
}
360
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
361
return false;
362
}
363
364
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
365
- return false;
366
- }
367
-
368
if (!vfp_access_check(s)) {
369
return true;
370
}
371
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
372
TCGv_i64 vm;
373
TCGv_ptr fpst;
374
375
- /* UNDEF accesses to D16-D31 if they don't exist. */
376
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
377
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
378
return false;
379
}
380
381
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
382
+ /* UNDEF accesses to D16-D31 if they don't exist. */
383
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
384
return false;
385
}
386
90
--
387
--
91
2.16.2
388
2.20.1
92
389
93
390
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Sort this check to the start of a trans_* function.
4
Merge this with any existing test for fpdp_v2.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180228193125.20577-13-richard.henderson@linaro.org
8
Message-id: 20200224222232.13807-8-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: renamed e1/e2/e3/e4 to use the same naming as the version
7
of the pseudocode in the Arm ARM]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/helper.h | 11 ++++
11
target/arm/translate-vfp.inc.c | 24 ++++++++----------------
11
target/arm/translate-a64.c | 94 +++++++++++++++++++++++++---
12
1 file changed, 8 insertions(+), 16 deletions(-)
12
target/arm/vec_helper.c | 149 +++++++++++++++++++++++++++++++++++++++++++++
13
3 files changed, 246 insertions(+), 8 deletions(-)
14
13
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
16
--- a/target/arm/translate-vfp.inc.c
18
+++ b/target/arm/helper.h
17
+++ b/target/arm/translate-vfp.inc.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
18
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
20
DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
19
* VFPv2 allows access to FPSID from userspace; VFPv3 restricts
21
void, ptr, ptr, ptr, ptr, i32)
20
* all ID registers to privileged access only.
22
21
*/
23
+DEF_HELPER_FLAGS_5(gvec_fcmlah, TCG_CALL_NO_RWG,
22
- if (IS_USER(s) && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
24
+ void, ptr, ptr, ptr, ptr, i32)
23
+ if (IS_USER(s) && dc_isar_feature(aa32_fpsp_v3, s)) {
25
+DEF_HELPER_FLAGS_5(gvec_fcmlah_idx, TCG_CALL_NO_RWG,
24
return false;
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_5(gvec_fcmlas, TCG_CALL_NO_RWG,
28
+ void, ptr, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+
34
#ifdef TARGET_AARCH64
35
#include "helper-a64.h"
36
#endif
37
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-a64.c
40
+++ b/target/arm/translate-a64.c
41
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
42
}
25
}
43
feature = ARM_FEATURE_V8_RDM;
26
ignore_vfp_enabled = true;
44
break;
27
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
45
+ case 0x8: /* FCMLA, #0 */
28
case ARM_VFP_FPINST:
46
+ case 0x9: /* FCMLA, #90 */
29
case ARM_VFP_FPINST2:
47
+ case 0xa: /* FCMLA, #180 */
30
/* Not present in VFPv3 */
48
+ case 0xb: /* FCMLA, #270 */
31
- if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
49
case 0xc: /* FCADD, #90 */
32
+ if (IS_USER(s) || dc_isar_feature(aa32_fpsp_v3, s)) {
50
case 0xe: /* FCADD, #270 */
33
return false;
51
if (size == 0
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
53
}
54
return;
55
56
+ case 0x8: /* FCMLA, #0 */
57
+ case 0x9: /* FCMLA, #90 */
58
+ case 0xa: /* FCMLA, #180 */
59
+ case 0xb: /* FCMLA, #270 */
60
+ rot = extract32(opcode, 0, 2);
61
+ switch (size) {
62
+ case 1:
63
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
64
+ gen_helper_gvec_fcmlah);
65
+ break;
66
+ case 2:
67
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
68
+ gen_helper_gvec_fcmlas);
69
+ break;
70
+ case 3:
71
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
72
+ gen_helper_gvec_fcmlad);
73
+ break;
74
+ default:
75
+ g_assert_not_reached();
76
+ }
77
+ return;
78
+
79
case 0xc: /* FCADD, #90 */
80
case 0xe: /* FCADD, #270 */
81
rot = extract32(opcode, 1, 1);
82
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
83
int rn = extract32(insn, 5, 5);
84
int rd = extract32(insn, 0, 5);
85
bool is_long = false;
86
- bool is_fp = false;
87
+ int is_fp = 0;
88
bool is_fp16 = false;
89
int index;
90
TCGv_ptr fpst;
91
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
92
case 0x05: /* FMLS */
93
case 0x09: /* FMUL */
94
case 0x19: /* FMULX */
95
- is_fp = true;
96
+ is_fp = 1;
97
break;
98
case 0x1d: /* SQRDMLAH */
99
case 0x1f: /* SQRDMLSH */
100
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
101
return;
102
}
34
}
103
break;
35
break;
104
+ case 0x11: /* FCMLA #0 */
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
105
+ case 0x13: /* FCMLA #90 */
37
106
+ case 0x15: /* FCMLA #180 */
38
vd = a->vd;
107
+ case 0x17: /* FCMLA #270 */
39
108
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)) {
40
- if (!dc_isar_feature(aa32_fpshvec, s) &&
109
+ unallocated_encoding(s);
41
- (veclen != 0 || s->vec_stride != 0)) {
110
+ return;
42
+ if (!dc_isar_feature(aa32_fpsp_v3, s)) {
111
+ }
43
return false;
112
+ is_fp = 2;
113
+ break;
114
default:
115
unallocated_encoding(s);
116
return;
117
}
44
}
118
45
119
- if (is_fp) {
46
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
120
+ switch (is_fp) {
47
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
121
+ case 1: /* normal fp */
48
+ (veclen != 0 || s->vec_stride != 0)) {
122
/* convert insn encoded size to TCGMemOp size */
49
return false;
123
switch (size) {
124
case 0: /* half-precision */
125
- if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
126
- unallocated_encoding(s);
127
- return;
128
- }
129
size = MO_16;
130
+ is_fp16 = true;
131
break;
132
case MO_32: /* single precision */
133
case MO_64: /* double precision */
134
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
135
unallocated_encoding(s);
136
return;
137
}
138
- } else {
139
+ break;
140
+
141
+ case 2: /* complex fp */
142
+ /* Each indexable element is a complex pair. */
143
+ size <<= 1;
144
+ switch (size) {
145
+ case MO_32:
146
+ if (h && !is_q) {
147
+ unallocated_encoding(s);
148
+ return;
149
+ }
150
+ is_fp16 = true;
151
+ break;
152
+ case MO_64:
153
+ break;
154
+ default:
155
+ unallocated_encoding(s);
156
+ return;
157
+ }
158
+ break;
159
+
160
+ default: /* integer */
161
switch (size) {
162
case MO_8:
163
case MO_64:
164
unallocated_encoding(s);
165
return;
166
}
167
+ break;
168
+ }
169
+ if (is_fp16 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
170
+ unallocated_encoding(s);
171
+ return;
172
}
50
}
173
51
174
/* Given TCGMemOp size, adjust register and indexing. */
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
175
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
53
176
fpst = NULL;
54
vd = a->vd;
55
56
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
57
+ if (!dc_isar_feature(aa32_fpdp_v3, s)) {
58
return false;
177
}
59
}
178
60
179
+ switch (16 * u + opcode) {
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
180
+ case 0x11: /* FCMLA #0 */
62
return false;
181
+ case 0x13: /* FCMLA #90 */
182
+ case 0x15: /* FCMLA #180 */
183
+ case 0x17: /* FCMLA #270 */
184
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
185
+ vec_full_reg_offset(s, rn),
186
+ vec_reg_offset(s, rm, index, size), fpst,
187
+ is_q ? 16 : 8, vec_full_reg_size(s),
188
+ extract32(insn, 13, 2), /* rot */
189
+ size == MO_64
190
+ ? gen_helper_gvec_fcmlas_idx
191
+ : gen_helper_gvec_fcmlah_idx);
192
+ tcg_temp_free_ptr(fpst);
193
+ return;
194
+ }
195
+
196
if (size == 3) {
197
TCGv_i64 tcg_idx = tcg_temp_new_i64();
198
int pass;
199
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/target/arm/vec_helper.c
202
+++ b/target/arm/vec_helper.c
203
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
204
}
63
}
205
clear_tail(d, opr_sz, simd_maxsz(desc));
64
206
}
65
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
207
+
66
- return false;
208
+void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm,
67
- }
209
+ void *vfpst, uint32_t desc)
68
-
210
+{
69
if (!vfp_access_check(s)) {
211
+ uintptr_t opr_sz = simd_oprsz(desc);
70
return true;
212
+ float16 *d = vd;
71
}
213
+ float16 *n = vn;
72
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
214
+ float16 *m = vm;
73
TCGv_ptr fpst;
215
+ float_status *fpst = vfpst;
74
int frac_bits;
216
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
75
217
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
76
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
218
+ uint32_t neg_real = flip ^ neg_imag;
77
+ if (!dc_isar_feature(aa32_fpsp_v3, s)) {
219
+ uintptr_t i;
78
return false;
220
+
79
}
221
+ /* Shift boolean to the sign bit so we can xor to negate. */
80
222
+ neg_real <<= 15;
81
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
223
+ neg_imag <<= 15;
82
TCGv_ptr fpst;
224
+
83
int frac_bits;
225
+ for (i = 0; i < opr_sz / 2; i += 2) {
84
226
+ float16 e2 = n[H2(i + flip)];
85
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
227
+ float16 e1 = m[H2(i + flip)] ^ neg_real;
86
- return false;
228
+ float16 e4 = e2;
87
- }
229
+ float16 e3 = m[H2(i + 1 - flip)] ^ neg_imag;
88
-
230
+
89
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
231
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
90
+ if (!dc_isar_feature(aa32_fpdp_v3, s)) {
232
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
91
return false;
233
+ }
92
}
234
+ clear_tail(d, opr_sz, simd_maxsz(desc));
93
235
+}
236
+
237
+void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
238
+ void *vfpst, uint32_t desc)
239
+{
240
+ uintptr_t opr_sz = simd_oprsz(desc);
241
+ float16 *d = vd;
242
+ float16 *n = vn;
243
+ float16 *m = vm;
244
+ float_status *fpst = vfpst;
245
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
246
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
247
+ uint32_t neg_real = flip ^ neg_imag;
248
+ uintptr_t i;
249
+ float16 e1 = m[H2(flip)];
250
+ float16 e3 = m[H2(1 - flip)];
251
+
252
+ /* Shift boolean to the sign bit so we can xor to negate. */
253
+ neg_real <<= 15;
254
+ neg_imag <<= 15;
255
+ e1 ^= neg_real;
256
+ e3 ^= neg_imag;
257
+
258
+ for (i = 0; i < opr_sz / 2; i += 2) {
259
+ float16 e2 = n[H2(i + flip)];
260
+ float16 e4 = e2;
261
+
262
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
263
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
264
+ }
265
+ clear_tail(d, opr_sz, simd_maxsz(desc));
266
+}
267
+
268
+void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm,
269
+ void *vfpst, uint32_t desc)
270
+{
271
+ uintptr_t opr_sz = simd_oprsz(desc);
272
+ float32 *d = vd;
273
+ float32 *n = vn;
274
+ float32 *m = vm;
275
+ float_status *fpst = vfpst;
276
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
277
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
278
+ uint32_t neg_real = flip ^ neg_imag;
279
+ uintptr_t i;
280
+
281
+ /* Shift boolean to the sign bit so we can xor to negate. */
282
+ neg_real <<= 31;
283
+ neg_imag <<= 31;
284
+
285
+ for (i = 0; i < opr_sz / 4; i += 2) {
286
+ float32 e2 = n[H4(i + flip)];
287
+ float32 e1 = m[H4(i + flip)] ^ neg_real;
288
+ float32 e4 = e2;
289
+ float32 e3 = m[H4(i + 1 - flip)] ^ neg_imag;
290
+
291
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
292
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
293
+ }
294
+ clear_tail(d, opr_sz, simd_maxsz(desc));
295
+}
296
+
297
+void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
298
+ void *vfpst, uint32_t desc)
299
+{
300
+ uintptr_t opr_sz = simd_oprsz(desc);
301
+ float32 *d = vd;
302
+ float32 *n = vn;
303
+ float32 *m = vm;
304
+ float_status *fpst = vfpst;
305
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
306
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
307
+ uint32_t neg_real = flip ^ neg_imag;
308
+ uintptr_t i;
309
+ float32 e1 = m[H4(flip)];
310
+ float32 e3 = m[H4(1 - flip)];
311
+
312
+ /* Shift boolean to the sign bit so we can xor to negate. */
313
+ neg_real <<= 31;
314
+ neg_imag <<= 31;
315
+ e1 ^= neg_real;
316
+ e3 ^= neg_imag;
317
+
318
+ for (i = 0; i < opr_sz / 4; i += 2) {
319
+ float32 e2 = n[H4(i + flip)];
320
+ float32 e4 = e2;
321
+
322
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
323
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
324
+ }
325
+ clear_tail(d, opr_sz, simd_maxsz(desc));
326
+}
327
+
328
+void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
329
+ void *vfpst, uint32_t desc)
330
+{
331
+ uintptr_t opr_sz = simd_oprsz(desc);
332
+ float64 *d = vd;
333
+ float64 *n = vn;
334
+ float64 *m = vm;
335
+ float_status *fpst = vfpst;
336
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
337
+ uint64_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
338
+ uint64_t neg_real = flip ^ neg_imag;
339
+ uintptr_t i;
340
+
341
+ /* Shift boolean to the sign bit so we can xor to negate. */
342
+ neg_real <<= 63;
343
+ neg_imag <<= 63;
344
+
345
+ for (i = 0; i < opr_sz / 8; i += 2) {
346
+ float64 e2 = n[i + flip];
347
+ float64 e1 = m[i + flip] ^ neg_real;
348
+ float64 e4 = e2;
349
+ float64 e3 = m[i + 1 - flip] ^ neg_imag;
350
+
351
+ d[i] = float64_muladd(e2, e1, d[i], 0, fpst);
352
+ d[i + 1] = float64_muladd(e4, e3, d[i + 1], 0, fpst);
353
+ }
354
+ clear_tail(d, opr_sz, simd_maxsz(desc));
355
+}
356
--
94
--
357
2.16.2
95
2.20.1
358
96
359
97
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Include the U bit in the switches rather than testing separately.
3
We will eventually remove the early ARM_FEATURE_VFP test,
4
4
so add a proper test for each trans_* that does not already
5
have another ISA test.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20200224222232.13807-9-richard.henderson@linaro.org
7
Message-id: 20180228193125.20577-3-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/translate-a64.c | 129 +++++++++++++++++++++------------------------
12
target/arm/translate-vfp.inc.c | 78 ++++++++++++++++++++++++++++++----
11
1 file changed, 61 insertions(+), 68 deletions(-)
13
1 file changed, 69 insertions(+), 9 deletions(-)
12
14
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
17
--- a/target/arm/translate-vfp.inc.c
16
+++ b/target/arm/translate-a64.c
18
+++ b/target/arm/translate-vfp.inc.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
18
int index;
20
int pass;
21
uint32_t offset;
22
23
+ /* SIZE == 2 is a VFP instruction; otherwise NEON. */
24
+ if (a->size == 2
25
+ ? !dc_isar_feature(aa32_fpsp_v2, s)
26
+ : !arm_dc_feature(s, ARM_FEATURE_NEON)) {
27
+ return false;
28
+ }
29
+
30
/* UNDEF accesses to D16-D31 if they don't exist */
31
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
32
return false;
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
34
pass = extract32(offset, 2, 1);
35
offset = extract32(offset, 0, 2) * 8;
36
37
- if (a->size != 2 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
38
- return false;
39
- }
40
-
41
if (!vfp_access_check(s)) {
42
return true;
43
}
44
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
45
int pass;
46
uint32_t offset;
47
48
+ /* SIZE == 2 is a VFP instruction; otherwise NEON. */
49
+ if (a->size == 2
50
+ ? !dc_isar_feature(aa32_fpsp_v2, s)
51
+ : !arm_dc_feature(s, ARM_FEATURE_NEON)) {
52
+ return false;
53
+ }
54
+
55
/* UNDEF accesses to D16-D31 if they don't exist */
56
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
57
return false;
58
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
59
pass = extract32(offset, 2, 1);
60
offset = extract32(offset, 0, 2) * 8;
61
62
- if (a->size != 2 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
63
- return false;
64
- }
65
-
66
if (!vfp_access_check(s)) {
67
return true;
68
}
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
70
TCGv_i32 tmp;
71
bool ignore_vfp_enabled = false;
72
73
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
74
+ return false;
75
+ }
76
+
77
if (arm_dc_feature(s, ARM_FEATURE_M)) {
78
/*
79
* The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
80
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
81
{
82
TCGv_i32 tmp;
83
84
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
85
+ return false;
86
+ }
87
+
88
if (!vfp_access_check(s)) {
89
return true;
90
}
91
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a)
92
{
93
TCGv_i32 tmp;
94
95
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
96
+ return false;
97
+ }
98
+
99
/*
100
* VMOV between two general-purpose registers and two single precision
101
* floating point registers
102
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
103
104
/*
105
* VMOV between two general-purpose registers and one double precision
106
- * floating point register
107
+ * floating point register. Note that this does not require support
108
+ * for double precision arithmetic.
109
*/
110
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
111
+ return false;
112
+ }
113
114
/* UNDEF accesses to D16-D31 if they don't exist */
115
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
116
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
117
uint32_t offset;
118
TCGv_i32 addr, tmp;
119
120
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
121
+ return false;
122
+ }
123
+
124
if (!vfp_access_check(s)) {
125
return true;
126
}
127
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
128
TCGv_i32 addr;
129
TCGv_i64 tmp;
130
131
+ /* Note that this does not require support for double arithmetic. */
132
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
133
+ return false;
134
+ }
135
+
136
/* UNDEF accesses to D16-D31 if they don't exist */
137
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
138
return false;
139
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a)
140
TCGv_i32 addr, tmp;
141
int i, n;
142
143
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
144
+ return false;
145
+ }
146
+
147
n = a->imm;
148
149
if (n == 0 || (a->vd + n) > 32) {
150
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
151
TCGv_i64 tmp;
152
int i, n;
153
154
+ /* Note that this does not require support for double arithmetic. */
155
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
156
+ return false;
157
+ }
158
+
159
n = a->imm >> 1;
160
161
if (n == 0 || (a->vd + n) > 32 || n > 16) {
162
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
163
TCGv_i32 f0, f1, fd;
19
TCGv_ptr fpst;
164
TCGv_ptr fpst;
20
165
21
- switch (opcode) {
166
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
22
- case 0x0: /* MLA */
167
+ return false;
23
- case 0x4: /* MLS */
168
+ }
24
- if (!u || is_scalar) {
169
+
25
+ switch (16 * u + opcode) {
170
if (!dc_isar_feature(aa32_fpshvec, s) &&
26
+ case 0x08: /* MUL */
171
(veclen != 0 || s->vec_stride != 0)) {
27
+ case 0x10: /* MLA */
172
return false;
28
+ case 0x14: /* MLS */
173
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
29
+ if (is_scalar) {
174
int veclen = s->vec_len;
30
unallocated_encoding(s);
175
TCGv_i32 f0, fd;
31
return;
176
32
}
177
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
33
break;
178
+ return false;
34
- case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
179
+ }
35
- case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
180
+
36
- case 0xa: /* SMULL, SMULL2, UMULL, UMULL2 */
181
if (!dc_isar_feature(aa32_fpshvec, s) &&
37
+ case 0x02: /* SMLAL, SMLAL2 */
182
(veclen != 0 || s->vec_stride != 0)) {
38
+ case 0x12: /* UMLAL, UMLAL2 */
183
return false;
39
+ case 0x06: /* SMLSL, SMLSL2 */
184
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
40
+ case 0x16: /* UMLSL, UMLSL2 */
185
{
41
+ case 0x0a: /* SMULL, SMULL2 */
186
TCGv_i32 vd, vm;
42
+ case 0x1a: /* UMULL, UMULL2 */
187
43
if (is_scalar) {
188
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
44
unallocated_encoding(s);
189
+ return false;
45
return;
190
+ }
46
}
191
+
47
is_long = true;
192
/* Vm/M bits must be zero for the Z variant */
48
break;
193
if (a->z && a->vm != 0) {
49
- case 0x3: /* SQDMLAL, SQDMLAL2 */
194
return false;
50
- case 0x7: /* SQDMLSL, SQDMLSL2 */
195
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
51
- case 0xb: /* SQDMULL, SQDMULL2 */
196
TCGv_i32 vm;
52
+ case 0x03: /* SQDMLAL, SQDMLAL2 */
197
TCGv_ptr fpst;
53
+ case 0x07: /* SQDMLSL, SQDMLSL2 */
198
54
+ case 0x0b: /* SQDMULL, SQDMULL2 */
199
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
55
is_long = true;
200
+ return false;
56
- /* fall through */
201
+ }
57
- case 0xc: /* SQDMULH */
202
+
58
- case 0xd: /* SQRDMULH */
203
if (!vfp_access_check(s)) {
59
- if (u) {
204
return true;
60
- unallocated_encoding(s);
205
}
61
- return;
206
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
62
- }
207
TCGv_i32 vm;
63
break;
208
TCGv_ptr fpst;
64
- case 0x8: /* MUL */
209
65
- if (u || is_scalar) {
210
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
66
- unallocated_encoding(s);
211
+ return false;
67
- return;
212
+ }
68
- }
213
+
69
+ case 0x0c: /* SQDMULH */
214
if (!vfp_access_check(s)) {
70
+ case 0x0d: /* SQRDMULH */
215
return true;
71
break;
216
}
72
- case 0x1: /* FMLA */
73
- case 0x5: /* FMLS */
74
- if (u) {
75
- unallocated_encoding(s);
76
- return;
77
- }
78
- /* fall through */
79
- case 0x9: /* FMUL, FMULX */
80
+ case 0x01: /* FMLA */
81
+ case 0x05: /* FMLS */
82
+ case 0x09: /* FMUL */
83
+ case 0x19: /* FMULX */
84
if (size == 1) {
85
unallocated_encoding(s);
86
return;
87
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
88
89
read_vec_element(s, tcg_op, rn, pass, MO_64);
90
91
- switch (opcode) {
92
- case 0x5: /* FMLS */
93
+ switch (16 * u + opcode) {
94
+ case 0x05: /* FMLS */
95
/* As usual for ARM, separate negation for fused multiply-add */
96
gen_helper_vfp_negd(tcg_op, tcg_op);
97
/* fall through */
98
- case 0x1: /* FMLA */
99
+ case 0x01: /* FMLA */
100
read_vec_element(s, tcg_res, rd, pass, MO_64);
101
gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
102
break;
103
- case 0x9: /* FMUL, FMULX */
104
- if (u) {
105
- gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
106
- } else {
107
- gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
108
- }
109
+ case 0x09: /* FMUL */
110
+ gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
111
+ break;
112
+ case 0x19: /* FMULX */
113
+ gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
114
break;
115
default:
116
g_assert_not_reached();
117
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
118
119
read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
120
121
- switch (opcode) {
122
- case 0x0: /* MLA */
123
- case 0x4: /* MLS */
124
- case 0x8: /* MUL */
125
+ switch (16 * u + opcode) {
126
+ case 0x08: /* MUL */
127
+ case 0x10: /* MLA */
128
+ case 0x14: /* MLS */
129
{
130
static NeonGenTwoOpFn * const fns[2][2] = {
131
{ gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
132
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
133
genfn(tcg_res, tcg_op, tcg_res);
134
break;
135
}
136
- case 0x5: /* FMLS */
137
- case 0x1: /* FMLA */
138
+ case 0x05: /* FMLS */
139
+ case 0x01: /* FMLA */
140
read_vec_element_i32(s, tcg_res, rd, pass,
141
is_scalar ? size : MO_32);
142
switch (size) {
143
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
144
g_assert_not_reached();
145
}
146
break;
147
- case 0x9: /* FMUL, FMULX */
148
+ case 0x09: /* FMUL */
149
switch (size) {
150
case 1:
151
- if (u) {
152
- if (is_scalar) {
153
- gen_helper_advsimd_mulxh(tcg_res, tcg_op,
154
- tcg_idx, fpst);
155
- } else {
156
- gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
157
- tcg_idx, fpst);
158
- }
159
+ if (is_scalar) {
160
+ gen_helper_advsimd_mulh(tcg_res, tcg_op,
161
+ tcg_idx, fpst);
162
} else {
163
- if (is_scalar) {
164
- gen_helper_advsimd_mulh(tcg_res, tcg_op,
165
- tcg_idx, fpst);
166
- } else {
167
- gen_helper_advsimd_mul2h(tcg_res, tcg_op,
168
- tcg_idx, fpst);
169
- }
170
+ gen_helper_advsimd_mul2h(tcg_res, tcg_op,
171
+ tcg_idx, fpst);
172
}
173
break;
174
case 2:
175
- if (u) {
176
- gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
177
- } else {
178
- gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
179
- }
180
+ gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
181
break;
182
default:
183
g_assert_not_reached();
184
}
185
break;
186
- case 0xc: /* SQDMULH */
187
+ case 0x19: /* FMULX */
188
+ switch (size) {
189
+ case 1:
190
+ if (is_scalar) {
191
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op,
192
+ tcg_idx, fpst);
193
+ } else {
194
+ gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
195
+ tcg_idx, fpst);
196
+ }
197
+ break;
198
+ case 2:
199
+ gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
200
+ break;
201
+ default:
202
+ g_assert_not_reached();
203
+ }
204
+ break;
205
+ case 0x0c: /* SQDMULH */
206
if (size == 1) {
207
gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
208
tcg_op, tcg_idx);
209
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
210
tcg_op, tcg_idx);
211
}
212
break;
213
- case 0xd: /* SQRDMULH */
214
+ case 0x0d: /* SQRDMULH */
215
if (size == 1) {
216
gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
217
tcg_op, tcg_idx);
218
--
217
--
219
2.16.2
218
2.20.1
220
219
221
220
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
All remaining tests for VFP4 are for fused multiply-add insns.
4
5
Since the MVFR1 field is used for both VFP and NEON, move its adjustment
6
from the !has_neon block to the (!has_vfp && !has_neon) block.
7
8
Test for vfp of the appropraite width alongside the test for simdfmac
9
within translate-vfp.inc.c. Within disas_neon_data_insn, we have
10
already tested for ARM_FEATURE_NEON.
11
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200224222232.13807-10-richard.henderson@linaro.org
5
Message-id: 20180228193125.20577-8-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
16
---
8
target/arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++-----------
17
target/arm/cpu.h | 12 ++++++++++++
9
1 file changed, 67 insertions(+), 19 deletions(-)
18
target/arm/cpu.c | 6 +++++-
19
target/arm/translate-vfp.inc.c | 22 ++++++++++++++++++----
20
target/arm/translate.c | 2 +-
21
4 files changed, 36 insertions(+), 6 deletions(-)
10
22
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/cpu.h
26
+++ b/target/arm/cpu.h
27
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
28
return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1;
29
}
30
31
+/*
32
+ * Note that this ID register field covers both VFP and Neon FMAC,
33
+ * so should usually be tested in combination with some other
34
+ * check that confirms the presence of whichever of VFP or Neon is
35
+ * relevant, to avoid accidentally enabling a Neon feature on
36
+ * a VFP-no-Neon core or vice-versa.
37
+ */
38
+static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id)
39
+{
40
+ return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0;
41
+}
42
+
43
static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
44
{
45
return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1;
46
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.c
49
+++ b/target/arm/cpu.c
50
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
51
u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
52
u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
53
u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
54
- u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0);
55
cpu->isar.mvfr1 = u;
56
57
u = cpu->isar.mvfr2;
58
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
59
u = cpu->isar.mvfr0;
60
u = FIELD_DP32(u, MVFR0, SIMDREG, 0);
61
cpu->isar.mvfr0 = u;
62
+
63
+ /* Despite the name, this field covers both VFP and Neon */
64
+ u = cpu->isar.mvfr1;
65
+ u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0);
66
+ cpu->isar.mvfr1 = u;
67
}
68
69
if (arm_feature(env, ARM_FEATURE_M) && !cpu->has_dsp) {
70
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/translate-vfp.inc.c
73
+++ b/target/arm/translate-vfp.inc.c
74
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
75
76
/*
77
* Present in VFPv4 only.
78
+ * Note that we can't rely on the SIMDFMAC check alone, because
79
+ * in a Neon-no-VFP core that ID register field will be non-zero.
80
+ */
81
+ if (!dc_isar_feature(aa32_simdfmac, s) ||
82
+ !dc_isar_feature(aa32_fpsp_v2, s)) {
83
+ return false;
84
+ }
85
+ /*
86
* In v7A, UNPREDICTABLE with non-zero vector length/stride; from
87
* v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
88
*/
89
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) ||
90
- (s->vec_len != 0 || s->vec_stride != 0)) {
91
+ if (s->vec_len != 0 || s->vec_stride != 0) {
92
return false;
93
}
94
95
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
96
97
/*
98
* Present in VFPv4 only.
99
+ * Note that we can't rely on the SIMDFMAC check alone, because
100
+ * in a Neon-no-VFP core that ID register field will be non-zero.
101
+ */
102
+ if (!dc_isar_feature(aa32_simdfmac, s) ||
103
+ !dc_isar_feature(aa32_fpdp_v2, s)) {
104
+ return false;
105
+ }
106
+ /*
107
* In v7A, UNPREDICTABLE with non-zero vector length/stride; from
108
* v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
109
*/
110
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) ||
111
- (s->vec_len != 0 || s->vec_stride != 0)) {
112
+ if (s->vec_len != 0 || s->vec_stride != 0) {
113
return false;
114
}
115
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
116
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
117
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
118
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
119
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@
16
#include "disas/disas.h"
17
#include "exec/exec-all.h"
18
#include "tcg-op.h"
19
+#include "tcg-op-gvec.h"
20
#include "qemu/log.h"
21
#include "qemu/bitops.h"
22
#include "arm_ldst.h"
23
@@ -XXX,XX +XXX,XX @@ static void gen_neon_narrow_op(int op, int u, int size,
24
#define NEON_3R_VPMAX 20
25
#define NEON_3R_VPMIN 21
26
#define NEON_3R_VQDMULH_VQRDMULH 22
27
-#define NEON_3R_VPADD 23
28
+#define NEON_3R_VPADD_VQRDMLAH 23
29
#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
30
-#define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
31
+#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
32
#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
33
#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
34
#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
35
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_3r_sizes[] = {
36
[NEON_3R_VPMAX] = 0x7,
37
[NEON_3R_VPMIN] = 0x7,
38
[NEON_3R_VQDMULH_VQRDMULH] = 0x6,
39
- [NEON_3R_VPADD] = 0x7,
40
+ [NEON_3R_VPADD_VQRDMLAH] = 0x7,
41
[NEON_3R_SHA] = 0xf, /* size field encodes op type */
42
- [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
43
+ [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
44
[NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
45
[NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
46
[NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
47
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
48
[NEON_2RM_VCVT_UF] = 0x4,
49
};
50
51
+
52
+/* Expand v8.1 simd helper. */
53
+static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
54
+ int q, int rd, int rn, int rm)
55
+{
56
+ if (arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
57
+ int opr_sz = (1 + q) * 8;
58
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
59
+ vfp_reg_offset(1, rn),
60
+ vfp_reg_offset(1, rm), cpu_env,
61
+ opr_sz, opr_sz, 0, fn);
62
+ return 0;
63
+ }
64
+ return 1;
65
+}
66
+
67
/* Translate a NEON data processing instruction. Return nonzero if the
68
instruction is invalid.
69
We process data in a mixture of 32-bit and 64-bit chunks.
70
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
120
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
71
if (q && ((rd | rn | rm) & 1)) {
72
return 1;
73
}
74
- /*
75
- * The SHA-1/SHA-256 3-register instructions require special treatment
76
- * here, as their size field is overloaded as an op type selector, and
77
- * they all consume their input in a single pass.
78
- */
79
- if (op == NEON_3R_SHA) {
80
+ switch (op) {
81
+ case NEON_3R_SHA:
82
+ /* The SHA-1/SHA-256 3-register instructions require special
83
+ * treatment here, as their size field is overloaded as an
84
+ * op type selector, and they all consume their input in a
85
+ * single pass.
86
+ */
87
if (!q) {
88
return 1;
89
}
90
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
91
tcg_temp_free_ptr(ptr2);
92
tcg_temp_free_ptr(ptr3);
93
return 0;
94
+
95
+ case NEON_3R_VPADD_VQRDMLAH:
96
+ if (!u) {
97
+ break; /* VPADD */
98
+ }
99
+ /* VQRDMLAH */
100
+ switch (size) {
101
+ case 1:
102
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
103
+ q, rd, rn, rm);
104
+ case 2:
105
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
106
+ q, rd, rn, rm);
107
+ }
108
+ return 1;
109
+
110
+ case NEON_3R_VFM_VQRDMLSH:
111
+ if (!u) {
112
+ /* VFM, VFMS */
113
+ if (size == 1) {
114
+ return 1;
115
+ }
116
+ break;
117
+ }
118
+ /* VQRDMLSH */
119
+ switch (size) {
120
+ case 1:
121
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
122
+ q, rd, rn, rm);
123
+ case 2:
124
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
125
+ q, rd, rn, rm);
126
+ }
127
+ return 1;
128
}
129
if (size == 3 && op != NEON_3R_LOGIC) {
130
/* 64-bit element instructions. */
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
132
rm = rtmp;
133
}
121
}
134
break;
122
break;
135
- case NEON_3R_VPADD:
123
case NEON_3R_VFM_VQRDMLSH:
136
- if (u) {
124
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
137
- return 1;
125
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
138
- }
139
- /* Fall through */
140
+ case NEON_3R_VPADD_VQRDMLAH:
141
case NEON_3R_VPMAX:
142
case NEON_3R_VPMIN:
143
pairwise = 1;
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
return 1;
126
return 1;
146
}
127
}
147
break;
128
break;
148
- case NEON_3R_VFM:
149
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
150
+ case NEON_3R_VFM_VQRDMLSH:
151
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
152
return 1;
153
}
154
break;
155
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
156
}
157
}
158
break;
159
- case NEON_3R_VPADD:
160
+ case NEON_3R_VPADD_VQRDMLAH:
161
switch (size) {
162
case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
163
case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
164
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
165
}
166
}
167
break;
168
- case NEON_3R_VFM:
169
+ case NEON_3R_VFM_VQRDMLSH:
170
{
171
/* VFMA, VFMS: fused multiply-add */
172
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
173
--
129
--
174
2.16.2
130
2.20.1
175
131
176
132
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
We now have proper ISA checks within each trans_* function.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-9-richard.henderson@linaro.org
7
Message-id: 20200224222232.13807-11-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/translate.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
10
target/arm/translate.c | 4 ----
9
1 file changed, 42 insertions(+), 4 deletions(-)
11
1 file changed, 4 deletions(-)
10
12
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
15
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
16
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static const char *regnames[] =
17
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
16
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
18
*/
17
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
19
static int disas_vfp_insn(DisasContext *s, uint32_t insn)
18
19
+/* Function prototypes for gen_ functions calling Neon helpers. */
20
+typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
21
+ TCGv_i32, TCGv_i32);
22
+
23
/* initialize TCG globals. */
24
void arm_translate_init(void)
25
{
20
{
26
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
21
- if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
27
}
22
- return 1;
28
neon_store_reg64(cpu_V0, rd + pass);
23
- }
29
}
30
-
24
-
31
-
25
/*
32
break;
26
* If the decodetree decoder handles this insn it will always
33
- default: /* 14 and 15 are RESERVED */
27
* emit code to either execute the insn or generate an appropriate
34
- return 1;
35
+ case 14: /* VQRDMLAH scalar */
36
+ case 15: /* VQRDMLSH scalar */
37
+ {
38
+ NeonGenThreeOpEnvFn *fn;
39
+
40
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
41
+ return 1;
42
+ }
43
+ if (u && ((rd | rn) & 1)) {
44
+ return 1;
45
+ }
46
+ if (op == 14) {
47
+ if (size == 1) {
48
+ fn = gen_helper_neon_qrdmlah_s16;
49
+ } else {
50
+ fn = gen_helper_neon_qrdmlah_s32;
51
+ }
52
+ } else {
53
+ if (size == 1) {
54
+ fn = gen_helper_neon_qrdmlsh_s16;
55
+ } else {
56
+ fn = gen_helper_neon_qrdmlsh_s32;
57
+ }
58
+ }
59
+
60
+ tmp2 = neon_get_scalar(size, rm);
61
+ for (pass = 0; pass < (u ? 4 : 2); pass++) {
62
+ tmp = neon_load_reg(rn, pass);
63
+ tmp3 = neon_load_reg(rd, pass);
64
+ fn(tmp, cpu_env, tmp, tmp2, tmp3);
65
+ tcg_temp_free_i32(tmp3);
66
+ neon_store_reg(rd, pass, tmp);
67
+ }
68
+ tcg_temp_free_i32(tmp2);
69
+ }
70
+ break;
71
+ default:
72
+ g_assert_not_reached();
73
}
74
}
75
} else { /* size == 3 */
76
--
28
--
77
2.16.2
29
2.20.1
78
30
79
31
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Happily, the bits are in the same places compared to a32.
3
Now that we no longer have an early check for ARM_FEATURE_VFP,
4
we can use the proper ISA check in trans_VLLDM_VLSTM.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180228193125.20577-16-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20200224222232.13807-12-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate.c | 14 +++++++++++++-
11
target/arm/translate-vfp.inc.c | 39 +++++++++++++++++++++++++
11
1 file changed, 13 insertions(+), 1 deletion(-)
12
target/arm/translate.c | 53 ++++++----------------------------
13
target/arm/vfp.decode | 2 ++
14
3 files changed, 50 insertions(+), 44 deletions(-)
12
15
16
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-vfp.inc.c
19
+++ b/target/arm/translate-vfp.inc.c
20
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
21
tcg_temp_free_ptr(fpst);
22
return true;
23
}
24
+
25
+/*
26
+ * Decode VLLDM and VLSTM are nonstandard because:
27
+ * * if there is no FPU then these insns must NOP in
28
+ * Secure state and UNDEF in Nonsecure state
29
+ * * if there is an FPU then these insns do not have
30
+ * the usual behaviour that vfp_access_check() provides of
31
+ * being controlled by CPACR/NSACR enable bits or the
32
+ * lazy-stacking logic.
33
+ */
34
+static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
35
+{
36
+ TCGv_i32 fptr;
37
+
38
+ if (!arm_dc_feature(s, ARM_FEATURE_M) ||
39
+ !arm_dc_feature(s, ARM_FEATURE_V8)) {
40
+ return false;
41
+ }
42
+ /* If not secure, UNDEF. */
43
+ if (!s->v8m_secure) {
44
+ return false;
45
+ }
46
+ /* If no fpu, NOP. */
47
+ if (!dc_isar_feature(aa32_vfp, s)) {
48
+ return true;
49
+ }
50
+
51
+ fptr = load_reg(s, a->rn);
52
+ if (a->l) {
53
+ gen_helper_v7m_vlldm(cpu_env, fptr);
54
+ } else {
55
+ gen_helper_v7m_vlstm(cpu_env, fptr);
56
+ }
57
+ tcg_temp_free_i32(fptr);
58
+
59
+ /* End the TB, because we have updated FP control bits */
60
+ s->base.is_jmp = DISAS_UPDATE;
61
+ return true;
62
+}
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
63
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
65
--- a/target/arm/translate.c
16
+++ b/target/arm/translate.c
66
+++ b/target/arm/translate.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
67
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
18
default_exception_el(s));
68
goto illegal_op; /* op0 = 0b11 : unallocated */
69
}
70
71
- /*
72
- * Decode VLLDM and VLSTM first: these are nonstandard because:
73
- * * if there is no FPU then these insns must NOP in
74
- * Secure state and UNDEF in Nonsecure state
75
- * * if there is an FPU then these insns do not have
76
- * the usual behaviour that disas_vfp_insn() provides of
77
- * being controlled by CPACR/NSACR enable bits or the
78
- * lazy-stacking logic.
79
- */
80
- if (arm_dc_feature(s, ARM_FEATURE_V8) &&
81
- (insn & 0xffa00f00) == 0xec200a00) {
82
- /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
83
- * - VLLDM, VLSTM
84
- * We choose to UNDEF if the RAZ bits are non-zero.
85
- */
86
- if (!s->v8m_secure || (insn & 0x0040f0ff)) {
87
+ if (disas_vfp_insn(s, insn)) {
88
+ if (((insn >> 8) & 0xe) == 10 &&
89
+ dc_isar_feature(aa32_fpsp_v2, s)) {
90
+ /* FP, and the CPU supports it */
91
goto illegal_op;
92
+ } else {
93
+ /* All other insns: NOCP */
94
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
95
+ syn_uncategorized(),
96
+ default_exception_el(s));
97
}
98
-
99
- if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
100
- uint32_t rn = (insn >> 16) & 0xf;
101
- TCGv_i32 fptr = load_reg(s, rn);
102
-
103
- if (extract32(insn, 20, 1)) {
104
- gen_helper_v7m_vlldm(cpu_env, fptr);
105
- } else {
106
- gen_helper_v7m_vlstm(cpu_env, fptr);
107
- }
108
- tcg_temp_free_i32(fptr);
109
-
110
- /* End the TB, because we have updated FP control bits */
111
- s->base.is_jmp = DISAS_UPDATE;
112
- }
113
- break;
114
}
115
- if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
116
- ((insn >> 8) & 0xe) == 10) {
117
- /* FP, and the CPU supports it */
118
- if (disas_vfp_insn(s, insn)) {
119
- goto illegal_op;
120
- }
121
- break;
122
- }
123
-
124
- /* All other insns: NOCP */
125
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized(),
126
- default_exception_el(s));
19
break;
127
break;
20
}
128
}
21
- if (((insn >> 24) & 3) == 3) {
129
if ((insn & 0xfe000a00) == 0xfc000800
22
+ if ((insn & 0xfe000a00) == 0xfc000800
130
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
23
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
131
index XXXXXXX..XXXXXXX 100644
24
+ /* The Thumb2 and ARM encodings are identical. */
132
--- a/target/arm/vfp.decode
25
+ if (disas_neon_insn_3same_ext(s, insn)) {
133
+++ b/target/arm/vfp.decode
26
+ goto illegal_op;
134
@@ -XXX,XX +XXX,XX @@ VCVT_sp_int ---- 1110 1.11 110 s:1 .... 1010 rz:1 1.0 .... \
27
+ }
135
vd=%vd_sp vm=%vm_sp
28
+ } else if ((insn & 0xff000a00) == 0xfe000800
136
VCVT_dp_int ---- 1110 1.11 110 s:1 .... 1011 rz:1 1.0 .... \
29
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
137
vd=%vd_sp vm=%vm_dp
30
+ /* The Thumb2 and ARM encodings are identical. */
138
+
31
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
139
+VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
32
+ goto illegal_op;
33
+ }
34
+ } else if (((insn >> 24) & 3) == 3) {
35
/* Translate into the equivalent ARM encoding. */
36
insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
37
if (disas_neon_data_insn(s, insn)) {
38
--
140
--
39
2.16.2
141
2.20.1
40
142
41
143
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Have the calls adjacent as an intermediate step toward
4
actually merging the decodes.
2
5
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180228193125.20577-14-richard.henderson@linaro.org
8
Message-id: 20200224222232.13807-13-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/translate.c | 83 +++++++++++++++---------------------------
9
1 file changed, 68 insertions(+)
12
1 file changed, 29 insertions(+), 54 deletions(-)
10
13
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
16
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
17
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
16
return 0;
19
tcg_temp_free_i32(tmp);
17
}
20
}
18
21
19
+/* Advanced SIMD three registers of the same length extension.
22
-/*
20
+ * 31 25 23 22 20 16 12 11 10 9 8 3 0
23
- * Disassemble a VFP instruction. Returns nonzero if an error occurred
21
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
24
- * (ie. an undefined instruction).
22
+ * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
25
- */
23
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
26
-static int disas_vfp_insn(DisasContext *s, uint32_t insn)
24
+ */
27
-{
25
+static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
28
- /*
26
+{
29
- * If the decodetree decoder handles this insn it will always
27
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
30
- * emit code to either execute the insn or generate an appropriate
28
+ int rd, rn, rm, rot, size, opr_sz;
31
- * exception; so we don't need to ever return non-zero to tell
29
+ TCGv_ptr fpst;
32
- * the calling code to emit an UNDEF exception.
30
+ bool q;
33
- */
31
+
34
- if (extract32(insn, 28, 4) == 0xf) {
32
+ q = extract32(insn, 6, 1);
35
- if (disas_vfp_uncond(s, insn)) {
33
+ VFP_DREG_D(rd, insn);
36
- return 0;
34
+ VFP_DREG_N(rn, insn);
37
- }
35
+ VFP_DREG_M(rm, insn);
38
- } else {
36
+ if ((rd | rn | rm) & q) {
39
- if (disas_vfp(s, insn)) {
37
+ return 1;
40
- return 0;
38
+ }
41
- }
39
+
42
- }
40
+ if ((insn & 0xfe200f10) == 0xfc200800) {
43
- /* If the decodetree decoder didn't handle this insn, it must be UNDEF */
41
+ /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
44
- return 1;
42
+ size = extract32(insn, 20, 1);
45
-}
43
+ rot = extract32(insn, 23, 2);
46
-
44
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
47
static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
45
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
48
{
46
+ return 1;
49
#ifndef CONFIG_USER_ONLY
50
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
51
ARCH(5);
52
53
/* Unconditional instructions. */
54
- if (disas_a32_uncond(s, insn)) {
55
+ /* TODO: Perhaps merge these into one decodetree output file. */
56
+ if (disas_a32_uncond(s, insn) ||
57
+ disas_vfp_uncond(s, insn)) {
58
return;
59
}
60
/* fall back to legacy decoder */
61
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
62
}
63
return;
64
}
65
- if ((insn & 0x0f000e10) == 0x0e000a00) {
66
- /* VFP. */
67
- if (disas_vfp_insn(s, insn)) {
68
- goto illegal_op;
69
- }
70
- return;
71
- }
72
if ((insn & 0x0e000f00) == 0x0c000100) {
73
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
74
/* iWMMXt register transfer. */
75
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
76
arm_skip_unless(s, cond);
77
}
78
79
- if (disas_a32(s, insn)) {
80
+ /* TODO: Perhaps merge these into one decodetree output file. */
81
+ if (disas_a32(s, insn) ||
82
+ disas_vfp(s, insn)) {
83
return;
84
}
85
/* fall back to legacy decoder */
86
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
87
case 0xd:
88
case 0xe:
89
if (((insn >> 8) & 0xe) == 10) {
90
- /* VFP. */
91
- if (disas_vfp_insn(s, insn)) {
92
- goto illegal_op;
93
- }
94
- } else if (disas_coproc_insn(s, insn)) {
95
+ /* VFP, but failed disas_vfp. */
96
+ goto illegal_op;
47
+ }
97
+ }
48
+ fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
98
+ if (disas_coproc_insn(s, insn)) {
49
+ } else if ((insn & 0xfea00f10) == 0xfc800800) {
99
/* Coprocessor. */
50
+ /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
100
goto illegal_op;
51
+ size = extract32(insn, 20, 1);
101
}
52
+ rot = extract32(insn, 24, 1);
102
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
53
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
103
ARCH(6T2);
54
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
104
}
55
+ return 1;
105
56
+ }
106
- if (disas_t32(s, insn)) {
57
+ fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
107
+ /*
58
+ } else {
108
+ * TODO: Perhaps merge these into one decodetree output file.
59
+ return 1;
109
+ * Note disas_vfp is written for a32 with cond field in the
60
+ }
110
+ * top nibble. The t32 encoding requires 0xe in the top nibble.
61
+
111
+ */
62
+ if (s->fp_excp_el) {
112
+ if (disas_t32(s, insn) ||
63
+ gen_exception_insn(s, 4, EXCP_UDEF,
113
+ disas_vfp_uncond(s, insn) ||
64
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
114
+ ((insn >> 28) == 0xe && disas_vfp(s, insn))) {
65
+ return 0;
115
return;
66
+ }
116
}
67
+ if (!s->vfp_enabled) {
117
/* fall back to legacy decoder */
68
+ return 1;
118
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
69
+ }
119
goto illegal_op; /* op0 = 0b11 : unallocated */
70
+
71
+ opr_sz = (1 + q) * 8;
72
+ fpst = get_fpstatus_ptr(1);
73
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
74
+ vfp_reg_offset(1, rn),
75
+ vfp_reg_offset(1, rm), fpst,
76
+ opr_sz, opr_sz, rot, fn_gvec_ptr);
77
+ tcg_temp_free_ptr(fpst);
78
+ return 0;
79
+}
80
+
81
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
82
{
83
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
84
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
85
}
86
}
87
}
120
}
88
+ } else if ((insn & 0x0e000a00) == 0x0c000800
121
89
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
122
- if (disas_vfp_insn(s, insn)) {
90
+ if (disas_neon_insn_3same_ext(s, insn)) {
123
- if (((insn >> 8) & 0xe) == 10 &&
124
- dc_isar_feature(aa32_fpsp_v2, s)) {
125
- /* FP, and the CPU supports it */
126
- goto illegal_op;
127
- } else {
128
- /* All other insns: NOCP */
129
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
130
- syn_uncategorized(),
131
- default_exception_el(s));
132
- }
133
+ if (((insn >> 8) & 0xe) == 10 &&
134
+ dc_isar_feature(aa32_fpsp_v2, s)) {
135
+ /* FP, and the CPU supports it */
91
+ goto illegal_op;
136
+ goto illegal_op;
92
+ }
137
+ } else {
93
+ return;
138
+ /* All other insns: NOCP */
94
} else if ((insn & 0x0fe00000) == 0x0c400000) {
139
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
95
/* Coprocessor double register transfer. */
140
+ syn_uncategorized(),
96
ARCH(5TE);
141
+ default_exception_el(s));
142
}
143
break;
144
}
145
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
146
goto illegal_op;
147
}
148
} else if (((insn >> 8) & 0xe) == 10) {
149
- if (disas_vfp_insn(s, insn)) {
150
- goto illegal_op;
151
- }
152
+ /* VFP, but failed disas_vfp. */
153
+ goto illegal_op;
154
} else {
155
if (insn & (1 << 28))
156
goto illegal_op;
97
--
157
--
98
2.16.2
158
2.20.1
99
159
100
160
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
3
Use isar feature tests instead of feature bit tests.
4
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Although none of QEMUs current cpus have VFPv3 without D32,
6
replace the large comment explaining why with one line that
7
sets ARM_HWCAP_ARM_VFPv3D16 under the correct conditions.
8
Mirror the test sequence used in the linux kernel.
9
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180228193125.20577-11-richard.henderson@linaro.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20200224222232.13807-14-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
14
---
10
target/arm/cpu.h | 1 +
15
linux-user/elfload.c | 23 +++++++++++++----------
11
linux-user/elfload.c | 1 +
16
1 file changed, 13 insertions(+), 10 deletions(-)
12
2 files changed, 2 insertions(+)
13
17
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ enum arm_features {
19
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
20
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
21
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
22
+ ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
23
};
24
25
static inline int arm_feature(CPUARMState *env, int feature)
26
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
27
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
28
--- a/linux-user/elfload.c
20
--- a/linux-user/elfload.c
29
+++ b/linux-user/elfload.c
21
+++ b/linux-user/elfload.c
30
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
22
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
31
GET_FEATURE(ARM_FEATURE_V8_FP16,
23
32
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
24
/* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */
33
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
25
GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP);
34
+ GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
26
- GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
35
#undef GET_FEATURE
27
GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
28
GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
29
GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
30
- GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3);
31
GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS);
32
- GET_FEATURE(ARM_FEATURE_VFP4, ARM_HWCAP_ARM_VFPv4);
33
+ GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
34
GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA);
35
GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT);
36
- /* All QEMU's VFPv3 CPUs have 32 registers, see VFP_DREG in translate.c.
37
- * Note that the ARM_HWCAP_ARM_VFPv3D16 bit is always the inverse of
38
- * ARM_HWCAP_ARM_VFPD32 (and so always clear for QEMU); it is unrelated
39
- * to our VFP_FP16 feature bit.
40
- */
41
- GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPD32);
42
- GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
43
+ GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP);
44
+
45
+ if (cpu_isar_feature(aa32_fpsp_v3, cpu) ||
46
+ cpu_isar_feature(aa32_fpdp_v3, cpu)) {
47
+ hwcaps |= ARM_HWCAP_ARM_VFPv3;
48
+ if (cpu_isar_feature(aa32_simd_r32, cpu)) {
49
+ hwcaps |= ARM_HWCAP_ARM_VFPD32;
50
+ } else {
51
+ hwcaps |= ARM_HWCAP_ARM_VFPv3D16;
52
+ }
53
+ }
54
+ GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4);
36
55
37
return hwcaps;
56
return hwcaps;
57
}
38
--
58
--
39
2.16.2
59
2.20.1
40
60
41
61
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
We have converted all tests against these features
4
4
to ISAR tests.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20200224222232.13807-15-richard.henderson@linaro.org
7
Message-id: 20180228193125.20577-10-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/cpu.c | 1 +
11
target/arm/cpu.h | 3 ---
11
target/arm/cpu64.c | 1 +
12
target/arm/cpu.c | 25 -------------------------
12
2 files changed, 2 insertions(+)
13
target/arm/cpu64.c | 3 ---
13
14
target/arm/kvm32.c | 5 -----
15
target/arm/kvm64.c | 1 -
16
5 files changed, 37 deletions(-)
17
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
23
* mapping in linux-user/elfload.c:get_elf_hwcap().
24
*/
25
enum arm_features {
26
- ARM_FEATURE_VFP,
27
ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */
28
ARM_FEATURE_XSCALE, /* Intel XScale extensions. */
29
ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
31
ARM_FEATURE_V7,
32
ARM_FEATURE_THUMB2,
33
ARM_FEATURE_PMSA, /* no MMU; may have Memory Protection Unit */
34
- ARM_FEATURE_VFP3,
35
ARM_FEATURE_NEON,
36
ARM_FEATURE_M, /* Microcontroller profile. */
37
ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
38
@@ -XXX,XX +XXX,XX @@ enum arm_features {
39
ARM_FEATURE_V5,
40
ARM_FEATURE_STRONGARM,
41
ARM_FEATURE_VAPA, /* cp15 VA to PA lookups */
42
- ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */
43
ARM_FEATURE_GENERIC_TIMER,
44
ARM_FEATURE_MVFR, /* Media and VFP Feature Registers 0 and 1 */
45
ARM_FEATURE_DUMMY_C15_REGS, /* RAZ/WI all of cp15 crn=15 */
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
46
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
48
--- a/target/arm/cpu.c
17
+++ b/target/arm/cpu.c
49
+++ b/target/arm/cpu.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
50
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
19
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
51
if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
20
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
52
set_feature(&cpu->env, ARM_FEATURE_PMSA);
21
set_feature(&cpu->env, ARM_FEATURE_CRC);
53
}
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
54
- /* Similarly for the VFP feature bits */
23
cpu->midr = 0xffffffff;
55
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP4)) {
56
- set_feature(&cpu->env, ARM_FEATURE_VFP3);
57
- }
58
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP3)) {
59
- set_feature(&cpu->env, ARM_FEATURE_VFP);
60
- }
61
62
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
63
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
64
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
65
uint64_t t;
66
uint32_t u;
67
68
- unset_feature(env, ARM_FEATURE_VFP);
69
- unset_feature(env, ARM_FEATURE_VFP3);
70
- unset_feature(env, ARM_FEATURE_VFP4);
71
-
72
t = cpu->isar.id_aa64isar1;
73
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0);
74
cpu->isar.id_aa64isar1 = t;
75
@@ -XXX,XX +XXX,XX @@ static void arm926_initfn(Object *obj)
76
77
cpu->dtb_compatible = "arm,arm926";
78
set_feature(&cpu->env, ARM_FEATURE_V5);
79
- set_feature(&cpu->env, ARM_FEATURE_VFP);
80
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
81
set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
82
cpu->midr = 0x41069265;
83
@@ -XXX,XX +XXX,XX @@ static void arm1026_initfn(Object *obj)
84
85
cpu->dtb_compatible = "arm,arm1026";
86
set_feature(&cpu->env, ARM_FEATURE_V5);
87
- set_feature(&cpu->env, ARM_FEATURE_VFP);
88
set_feature(&cpu->env, ARM_FEATURE_AUXCR);
89
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
90
set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
91
@@ -XXX,XX +XXX,XX @@ static void arm1136_r2_initfn(Object *obj)
92
93
cpu->dtb_compatible = "arm,arm1136";
94
set_feature(&cpu->env, ARM_FEATURE_V6);
95
- set_feature(&cpu->env, ARM_FEATURE_VFP);
96
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
97
set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
98
set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
99
@@ -XXX,XX +XXX,XX @@ static void arm1136_initfn(Object *obj)
100
cpu->dtb_compatible = "arm,arm1136";
101
set_feature(&cpu->env, ARM_FEATURE_V6K);
102
set_feature(&cpu->env, ARM_FEATURE_V6);
103
- set_feature(&cpu->env, ARM_FEATURE_VFP);
104
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
105
set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
106
set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
107
@@ -XXX,XX +XXX,XX @@ static void arm1176_initfn(Object *obj)
108
109
cpu->dtb_compatible = "arm,arm1176";
110
set_feature(&cpu->env, ARM_FEATURE_V6K);
111
- set_feature(&cpu->env, ARM_FEATURE_VFP);
112
set_feature(&cpu->env, ARM_FEATURE_VAPA);
113
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
114
set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
115
@@ -XXX,XX +XXX,XX @@ static void arm11mpcore_initfn(Object *obj)
116
117
cpu->dtb_compatible = "arm,arm11mpcore";
118
set_feature(&cpu->env, ARM_FEATURE_V6K);
119
- set_feature(&cpu->env, ARM_FEATURE_VFP);
120
set_feature(&cpu->env, ARM_FEATURE_VAPA);
121
set_feature(&cpu->env, ARM_FEATURE_MPIDR);
122
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
123
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
124
set_feature(&cpu->env, ARM_FEATURE_M);
125
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
126
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
127
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
128
cpu->midr = 0x410fc240; /* r0p0 */
129
cpu->pmsav7_dregion = 8;
130
cpu->isar.mvfr0 = 0x10110021;
131
@@ -XXX,XX +XXX,XX @@ static void cortex_m7_initfn(Object *obj)
132
set_feature(&cpu->env, ARM_FEATURE_M);
133
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
136
cpu->midr = 0x411fc272; /* r1p2 */
137
cpu->pmsav7_dregion = 8;
138
cpu->isar.mvfr0 = 0x10110221;
139
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
140
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
141
set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
142
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
143
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
144
cpu->midr = 0x410fd213; /* r0p3 */
145
cpu->pmsav7_dregion = 16;
146
cpu->sau_sregion = 8;
147
@@ -XXX,XX +XXX,XX @@ static void cortex_r5f_initfn(Object *obj)
148
ARMCPU *cpu = ARM_CPU(obj);
149
150
cortex_r5_initfn(obj);
151
- set_feature(&cpu->env, ARM_FEATURE_VFP3);
152
cpu->isar.mvfr0 = 0x10110221;
153
cpu->isar.mvfr1 = 0x00000011;
24
}
154
}
25
#endif
155
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
156
157
cpu->dtb_compatible = "arm,cortex-a8";
158
set_feature(&cpu->env, ARM_FEATURE_V7);
159
- set_feature(&cpu->env, ARM_FEATURE_VFP3);
160
set_feature(&cpu->env, ARM_FEATURE_NEON);
161
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
162
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
163
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
164
165
cpu->dtb_compatible = "arm,cortex-a9";
166
set_feature(&cpu->env, ARM_FEATURE_V7);
167
- set_feature(&cpu->env, ARM_FEATURE_VFP3);
168
set_feature(&cpu->env, ARM_FEATURE_NEON);
169
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
170
set_feature(&cpu->env, ARM_FEATURE_EL3);
171
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
172
173
cpu->dtb_compatible = "arm,cortex-a7";
174
set_feature(&cpu->env, ARM_FEATURE_V7VE);
175
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
176
set_feature(&cpu->env, ARM_FEATURE_NEON);
177
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
178
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
179
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
180
181
cpu->dtb_compatible = "arm,cortex-a15";
182
set_feature(&cpu->env, ARM_FEATURE_V7VE);
183
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
184
set_feature(&cpu->env, ARM_FEATURE_NEON);
185
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
186
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
187
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
27
index XXXXXXX..XXXXXXX 100644
188
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu64.c
189
--- a/target/arm/cpu64.c
29
+++ b/target/arm/cpu64.c
190
+++ b/target/arm/cpu64.c
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
191
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
31
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
192
32
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
193
cpu->dtb_compatible = "arm,cortex-a57";
33
set_feature(&cpu->env, ARM_FEATURE_CRC);
194
set_feature(&cpu->env, ARM_FEATURE_V8);
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
195
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
35
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
196
set_feature(&cpu->env, ARM_FEATURE_NEON);
36
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
197
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
37
cpu->dcz_blocksize = 7; /* 512 bytes */
198
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
199
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
200
201
cpu->dtb_compatible = "arm,cortex-a53";
202
set_feature(&cpu->env, ARM_FEATURE_V8);
203
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
204
set_feature(&cpu->env, ARM_FEATURE_NEON);
205
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
206
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
207
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
208
209
cpu->dtb_compatible = "arm,cortex-a72";
210
set_feature(&cpu->env, ARM_FEATURE_V8);
211
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
212
set_feature(&cpu->env, ARM_FEATURE_NEON);
213
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
214
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
215
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/target/arm/kvm32.c
218
+++ b/target/arm/kvm32.c
219
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
220
* bits, but a few must be tested.
221
*/
222
set_feature(&features, ARM_FEATURE_V7VE);
223
- set_feature(&features, ARM_FEATURE_VFP3);
224
set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
225
226
if (extract32(id_pfr0, 12, 4) == 1) {
227
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
228
if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
229
set_feature(&features, ARM_FEATURE_NEON);
230
}
231
- if (extract32(ahcf->isar.mvfr1, 28, 4) == 1) {
232
- /* FMAC support implies VFPv4 */
233
- set_feature(&features, ARM_FEATURE_VFP4);
234
- }
235
236
ahcf->features = features;
237
238
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
239
index XXXXXXX..XXXXXXX 100644
240
--- a/target/arm/kvm64.c
241
+++ b/target/arm/kvm64.c
242
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
243
* feature bits.
244
*/
245
set_feature(&features, ARM_FEATURE_V8);
246
- set_feature(&features, ARM_FEATURE_VFP4);
247
set_feature(&features, ARM_FEATURE_NEON);
248
set_feature(&features, ARM_FEATURE_AARCH64);
249
set_feature(&features, ARM_FEATURE_PMU);
38
--
250
--
39
2.16.2
251
2.20.1
40
252
41
253
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The integer size check was already outside of the opcode switch;
3
Those vfp instructions without extra opcode fields can
4
move the floating-point size check outside as well. Unify the
4
share a common @format for brevity.
5
size vs index adjustment between fp and integer paths.
5
6
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20200224222232.13807-16-richard.henderson@linaro.org
9
Message-id: 20180228193125.20577-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/translate-a64.c | 65 +++++++++++++++++++++++-----------------------
11
target/arm/vfp.decode | 134 ++++++++++++++++--------------------------
13
1 file changed, 32 insertions(+), 33 deletions(-)
12
1 file changed, 52 insertions(+), 82 deletions(-)
14
13
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
16
--- a/target/arm/vfp.decode
18
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/vfp.decode
19
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@
20
case 0x05: /* FMLS */
19
21
case 0x09: /* FMUL */
20
%vmov_imm 16:4 0:4
22
case 0x19: /* FMULX */
21
23
- if (size == 1) {
22
+@vfp_dnm_s ................................ vm=%vm_sp vn=%vn_sp vd=%vd_sp
24
- unallocated_encoding(s);
23
+@vfp_dnm_d ................................ vm=%vm_dp vn=%vn_dp vd=%vd_dp
25
- return;
26
- }
27
is_fp = true;
28
break;
29
default:
30
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
31
if (is_fp) {
32
/* convert insn encoded size to TCGMemOp size */
33
switch (size) {
34
- case 2: /* single precision */
35
- size = MO_32;
36
- index = h << 1 | l;
37
- rm |= (m << 4);
38
- break;
39
- case 3: /* double precision */
40
- size = MO_64;
41
- if (l || !is_q) {
42
+ case 0: /* half-precision */
43
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
44
unallocated_encoding(s);
45
return;
46
}
47
- index = h;
48
- rm |= (m << 4);
49
- break;
50
- case 0: /* half precision */
51
size = MO_16;
52
- index = h << 2 | l << 1 | m;
53
- is_fp16 = true;
54
- if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
55
- break;
56
- }
57
- /* fallthru */
58
- default: /* unallocated */
59
- unallocated_encoding(s);
60
- return;
61
- }
62
- } else {
63
- switch (size) {
64
- case 1:
65
- index = h << 2 | l << 1 | m;
66
break;
67
- case 2:
68
- index = h << 1 | l;
69
- rm |= (m << 4);
70
+ case MO_32: /* single precision */
71
+ case MO_64: /* double precision */
72
break;
73
default:
74
unallocated_encoding(s);
75
return;
76
}
77
+ } else {
78
+ switch (size) {
79
+ case MO_8:
80
+ case MO_64:
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ }
85
+
24
+
86
+ /* Given TCGMemOp size, adjust register and indexing. */
25
+@vfp_dm_ss ................................ vm=%vm_sp vd=%vd_sp
87
+ switch (size) {
26
+@vfp_dm_dd ................................ vm=%vm_dp vd=%vd_dp
88
+ case MO_16:
27
+@vfp_dm_ds ................................ vm=%vm_sp vd=%vd_dp
89
+ index = h << 2 | l << 1 | m;
28
+@vfp_dm_sd ................................ vm=%vm_dp vd=%vd_sp
90
+ break;
29
+
91
+ case MO_32:
30
# VMOV scalar to general-purpose register; note that this does
92
+ index = h << 1 | l;
31
# include some Neon cases.
93
+ rm |= m << 4;
32
VMOV_to_gp ---- 1110 u:1 1. 1 .... rt:4 1011 ... 1 0000 \
94
+ break;
33
@@ -XXX,XX +XXX,XX @@ VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \
95
+ case MO_64:
34
vn=%vn_dp
96
+ if (l || !is_q) {
35
97
+ unallocated_encoding(s);
36
VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
98
+ return;
37
-VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 \
99
+ }
38
- vn=%vn_sp
100
+ index = h;
39
+VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 vn=%vn_sp
101
+ rm |= m << 4;
40
102
+ break;
41
-VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... \
103
+ default:
42
- vm=%vm_sp
104
+ g_assert_not_reached();
43
-VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... \
105
}
44
- vm=%vm_dp
106
45
+VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... vm=%vm_sp
107
if (!fp_access_check(s)) {
46
+VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... vm=%vm_dp
47
48
# Note that the half-precision variants of VLDR and VSTR are
49
# not part of this decodetree at all because they have bits [9:8] == 0b01
50
-VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 \
51
- vd=%vd_sp
52
-VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 \
53
- vd=%vd_dp
54
+VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
55
+VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
56
57
# We split the load/store multiple up into two patterns to avoid
58
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
59
@@ -XXX,XX +XXX,XX @@ VLDM_VSTM_dp ---- 1101 0.1 l:1 rn:4 .... 1011 imm:8 \
60
vd=%vd_dp p=1 u=0 w=1
61
62
# 3-register VFP data-processing; bits [23,21:20,6] identify the operation.
63
-VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... \
64
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
65
-VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... \
66
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
67
+VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... @vfp_dnm_s
68
+VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... @vfp_dnm_d
69
70
-VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... \
71
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
72
-VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... \
73
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
74
+VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... @vfp_dnm_s
75
+VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... @vfp_dnm_d
76
77
-VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... \
78
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
79
-VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... \
80
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
81
+VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... @vfp_dnm_s
82
+VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... @vfp_dnm_d
83
84
-VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... \
85
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
86
-VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... \
87
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
88
+VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... @vfp_dnm_s
89
+VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... @vfp_dnm_d
90
91
-VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... \
92
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
93
-VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... \
94
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
95
+VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... @vfp_dnm_s
96
+VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... @vfp_dnm_d
97
98
-VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... \
99
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
100
-VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... \
101
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
102
+VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... @vfp_dnm_s
103
+VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... @vfp_dnm_d
104
105
-VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... \
106
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
107
-VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... \
108
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
109
+VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... @vfp_dnm_s
110
+VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... @vfp_dnm_d
111
112
-VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... \
113
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
114
-VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... \
115
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
116
+VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... @vfp_dnm_s
117
+VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... @vfp_dnm_d
118
119
-VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... \
120
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
121
-VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... \
122
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
123
+VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
124
+VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
125
126
VFM_sp ---- 1110 1.01 .... .... 1010 . o2:1 . 0 .... \
127
vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=1
128
@@ -XXX,XX +XXX,XX @@ VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \
129
VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \
130
vd=%vd_dp imm=%vmov_imm
131
132
-VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... \
133
- vd=%vd_sp vm=%vm_sp
134
-VMOV_reg_dp ---- 1110 1.11 0000 .... 1011 01.0 .... \
135
- vd=%vd_dp vm=%vm_dp
136
+VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... @vfp_dm_ss
137
+VMOV_reg_dp ---- 1110 1.11 0000 .... 1011 01.0 .... @vfp_dm_dd
138
139
-VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... \
140
- vd=%vd_sp vm=%vm_sp
141
-VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... \
142
- vd=%vd_dp vm=%vm_dp
143
+VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... @vfp_dm_ss
144
+VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... @vfp_dm_dd
145
146
-VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... \
147
- vd=%vd_sp vm=%vm_sp
148
-VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... \
149
- vd=%vd_dp vm=%vm_dp
150
+VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... @vfp_dm_ss
151
+VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... @vfp_dm_dd
152
153
-VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... \
154
- vd=%vd_sp vm=%vm_sp
155
-VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... \
156
- vd=%vd_dp vm=%vm_dp
157
+VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... @vfp_dm_ss
158
+VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... @vfp_dm_dd
159
160
VCMP_sp ---- 1110 1.11 010 z:1 .... 1010 e:1 1.0 .... \
161
vd=%vd_sp vm=%vm_sp
162
@@ -XXX,XX +XXX,XX @@ VCVT_f32_f16 ---- 1110 1.11 0010 .... 1010 t:1 1.0 .... \
163
VCVT_f64_f16 ---- 1110 1.11 0010 .... 1011 t:1 1.0 .... \
164
vd=%vd_dp vm=%vm_sp
165
166
-# VCVTB and VCVTT to f16: Vd format is always vd_sp; Vm format depends on size bit
167
+# VCVTB and VCVTT to f16: Vd format is always vd_sp;
168
+# Vm format depends on size bit
169
VCVT_f16_f32 ---- 1110 1.11 0011 .... 1010 t:1 1.0 .... \
170
vd=%vd_sp vm=%vm_sp
171
VCVT_f16_f64 ---- 1110 1.11 0011 .... 1011 t:1 1.0 .... \
172
vd=%vd_sp vm=%vm_dp
173
174
-VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... \
175
- vd=%vd_sp vm=%vm_sp
176
-VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... \
177
- vd=%vd_dp vm=%vm_dp
178
+VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... @vfp_dm_ss
179
+VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... @vfp_dm_dd
180
181
-VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... \
182
- vd=%vd_sp vm=%vm_sp
183
-VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... \
184
- vd=%vd_dp vm=%vm_dp
185
+VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... @vfp_dm_ss
186
+VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... @vfp_dm_dd
187
188
-VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... \
189
- vd=%vd_sp vm=%vm_sp
190
-VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... \
191
- vd=%vd_dp vm=%vm_dp
192
+VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... @vfp_dm_ss
193
+VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... @vfp_dm_dd
194
195
-# VCVT between single and double: Vm precision depends on size; Vd is its reverse
196
-VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... \
197
- vd=%vd_dp vm=%vm_sp
198
-VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... \
199
- vd=%vd_sp vm=%vm_dp
200
+# VCVT between single and double:
201
+# Vm precision depends on size; Vd is its reverse
202
+VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... @vfp_dm_ds
203
+VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... @vfp_dm_sd
204
205
# VCVT from integer to floating point: Vm always single; Vd depends on size
206
VCVT_int_sp ---- 1110 1.11 1000 .... 1010 s:1 1.0 .... \
207
@@ -XXX,XX +XXX,XX @@ VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
208
vd=%vd_dp vm=%vm_sp
209
210
# VJCVT is always dp to sp
211
-VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... \
212
- vd=%vd_sp vm=%vm_dp
213
+VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... @vfp_dm_sd
214
215
# VCVT between floating-point and fixed-point. The immediate value
216
# is in the same format as a Vm single-precision register number.
108
--
217
--
109
2.16.2
218
2.20.1
110
219
111
220
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Passing the raw o1 and o2 fields from the manual is less
4
instructive than it might be. Do the full decode and let
5
the trans_* functions pass in booleans to a helper.
2
6
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-6-richard.henderson@linaro.org
9
Message-id: 20200224222232.13807-17-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/helper.h | 9 +++++
12
target/arm/translate-vfp.inc.c | 52 ++++++++++++++++++++++++++++++----
9
target/arm/translate-a64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
13
target/arm/vfp.decode | 17 +++++------
10
target/arm/vec_helper.c | 74 +++++++++++++++++++++++++++++++++++++++++
14
2 files changed, 55 insertions(+), 14 deletions(-)
11
3 files changed, 166 insertions(+)
12
15
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
18
--- a/target/arm/translate-vfp.inc.c
16
+++ b/target/arm/helper.h
19
+++ b/target/arm/translate-vfp.inc.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(dc_zva, void, env, i64)
20
@@ -XXX,XX +XXX,XX @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
18
DEF_HELPER_FLAGS_2(neon_pmull_64_lo, TCG_CALL_NO_RWG_SE, i64, i64, i64)
21
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
19
DEF_HELPER_FLAGS_2(neon_pmull_64_hi, TCG_CALL_NO_RWG_SE, i64, i64, i64)
20
21
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s16, TCG_CALL_NO_RWG,
22
+ void, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s16, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
28
+ void, ptr, ptr, ptr, ptr, i32)
29
+
30
#ifdef TARGET_AARCH64
31
#include "helper-a64.h"
32
#endif
33
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-a64.c
36
+++ b/target/arm/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
38
vec_full_reg_size(s), gvec_op);
39
}
22
}
40
23
41
+/* Expand a 3-operand + env pointer operation using
24
-static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
42
+ * an out-of-line helper.
25
+static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
43
+ */
26
{
44
+static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
27
/*
45
+ int rn, int rm, gen_helper_gvec_3_ptr *fn)
28
* VFNMA : fd = muladd(-fd, fn, fm)
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
30
31
neon_load_reg32(vn, a->vn);
32
neon_load_reg32(vm, a->vm);
33
- if (a->o2) {
34
+ if (neg_n) {
35
/* VFNMS, VFMS */
36
gen_helper_vfp_negs(vn, vn);
37
}
38
neon_load_reg32(vd, a->vd);
39
- if (a->o1 & 1) {
40
+ if (neg_d) {
41
/* VFNMA, VFNMS */
42
gen_helper_vfp_negs(vd, vd);
43
}
44
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
45
return true;
46
}
47
48
-static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
49
+static bool trans_VFMA_sp(DisasContext *s, arg_VFMA_sp *a)
46
+{
50
+{
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
51
+ return do_vfm_sp(s, a, false, false);
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), cpu_env,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
51
+}
52
+}
52
+
53
+
53
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
54
+static bool trans_VFMS_sp(DisasContext *s, arg_VFMS_sp *a)
54
* than the 32 bit equivalent.
55
*/
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
57
clear_vec_high(s, is_q, rd);
58
}
59
60
+/* AdvSIMD three same extra
61
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
62
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
63
+ * | 0 | Q | U | 0 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
64
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
65
+ */
66
+static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
+{
55
+{
68
+ int rd = extract32(insn, 0, 5);
56
+ return do_vfm_sp(s, a, true, false);
69
+ int rn = extract32(insn, 5, 5);
70
+ int opcode = extract32(insn, 11, 4);
71
+ int rm = extract32(insn, 16, 5);
72
+ int size = extract32(insn, 22, 2);
73
+ bool u = extract32(insn, 29, 1);
74
+ bool is_q = extract32(insn, 30, 1);
75
+ int feature;
76
+
77
+ switch (u * 16 + opcode) {
78
+ case 0x10: /* SQRDMLAH (vector) */
79
+ case 0x11: /* SQRDMLSH (vector) */
80
+ if (size != 1 && size != 2) {
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ feature = ARM_FEATURE_V8_RDM;
85
+ break;
86
+ default:
87
+ unallocated_encoding(s);
88
+ return;
89
+ }
90
+ if (!arm_dc_feature(s, feature)) {
91
+ unallocated_encoding(s);
92
+ return;
93
+ }
94
+ if (!fp_access_check(s)) {
95
+ return;
96
+ }
97
+
98
+ switch (opcode) {
99
+ case 0x0: /* SQRDMLAH (vector) */
100
+ switch (size) {
101
+ case 1:
102
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
103
+ break;
104
+ case 2:
105
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
106
+ break;
107
+ default:
108
+ g_assert_not_reached();
109
+ }
110
+ return;
111
+
112
+ case 0x1: /* SQRDMLSH (vector) */
113
+ switch (size) {
114
+ case 1:
115
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
116
+ break;
117
+ case 2:
118
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
119
+ break;
120
+ default:
121
+ g_assert_not_reached();
122
+ }
123
+ return;
124
+
125
+ default:
126
+ g_assert_not_reached();
127
+ }
128
+}
57
+}
129
+
58
+
130
static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
59
+static bool trans_VFNMA_sp(DisasContext *s, arg_VFNMA_sp *a)
131
int size, int rn, int rd)
132
{
133
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
134
static const AArch64DecodeTable data_proc_simd[] = {
135
/* pattern , mask , fn */
136
{ 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
137
+ { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
138
{ 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
139
{ 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
140
{ 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
141
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/target/arm/vec_helper.c
144
+++ b/target/arm/vec_helper.c
145
@@ -XXX,XX +XXX,XX @@
146
147
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
148
149
+static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
150
+{
60
+{
151
+ uint64_t *d = vd + opr_sz;
61
+ return do_vfm_sp(s, a, false, true);
152
+ uintptr_t i;
153
+
154
+ for (i = opr_sz; i < max_sz; i += 8) {
155
+ *d++ = 0;
156
+ }
157
+}
62
+}
158
+
63
+
159
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
64
+static bool trans_VFNMS_sp(DisasContext *s, arg_VFNMS_sp *a)
160
static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
161
int16_t src2, int16_t src3)
162
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
163
return deposit32(e1, 16, 16, e2);
164
}
165
166
+void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
167
+ void *ve, uint32_t desc)
168
+{
65
+{
169
+ uintptr_t opr_sz = simd_oprsz(desc);
66
+ return do_vfm_sp(s, a, true, true);
170
+ int16_t *d = vd;
171
+ int16_t *n = vn;
172
+ int16_t *m = vm;
173
+ CPUARMState *env = ve;
174
+ uintptr_t i;
175
+
176
+ for (i = 0; i < opr_sz / 2; ++i) {
177
+ d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
178
+ }
179
+ clear_tail(d, opr_sz, simd_maxsz(desc));
180
+}
67
+}
181
+
68
+
182
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
69
+static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
183
static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
70
{
184
int16_t src2, int16_t src3)
71
/*
185
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
72
* VFNMA : fd = muladd(-fd, fn, fm)
186
return deposit32(e1, 16, 16, e2);
73
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
74
75
neon_load_reg64(vn, a->vn);
76
neon_load_reg64(vm, a->vm);
77
- if (a->o2) {
78
+ if (neg_n) {
79
/* VFNMS, VFMS */
80
gen_helper_vfp_negd(vn, vn);
81
}
82
neon_load_reg64(vd, a->vd);
83
- if (a->o1 & 1) {
84
+ if (neg_d) {
85
/* VFNMA, VFNMS */
86
gen_helper_vfp_negd(vd, vd);
87
}
88
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
89
return true;
187
}
90
}
188
91
189
+void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
92
+static bool trans_VFMA_dp(DisasContext *s, arg_VFMA_dp *a)
190
+ void *ve, uint32_t desc)
191
+{
93
+{
192
+ uintptr_t opr_sz = simd_oprsz(desc);
94
+ return do_vfm_dp(s, a, false, false);
193
+ int16_t *d = vd;
194
+ int16_t *n = vn;
195
+ int16_t *m = vm;
196
+ CPUARMState *env = ve;
197
+ uintptr_t i;
198
+
199
+ for (i = 0; i < opr_sz / 2; ++i) {
200
+ d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
201
+ }
202
+ clear_tail(d, opr_sz, simd_maxsz(desc));
203
+}
95
+}
204
+
96
+
205
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
97
+static bool trans_VFMS_dp(DisasContext *s, arg_VFMS_dp *a)
206
uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
207
int32_t src2, int32_t src3)
208
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
209
return ret;
210
}
211
212
+void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
213
+ void *ve, uint32_t desc)
214
+{
98
+{
215
+ uintptr_t opr_sz = simd_oprsz(desc);
99
+ return do_vfm_dp(s, a, true, false);
216
+ int32_t *d = vd;
217
+ int32_t *n = vn;
218
+ int32_t *m = vm;
219
+ CPUARMState *env = ve;
220
+ uintptr_t i;
221
+
222
+ for (i = 0; i < opr_sz / 4; ++i) {
223
+ d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
224
+ }
225
+ clear_tail(d, opr_sz, simd_maxsz(desc));
226
+}
100
+}
227
+
101
+
228
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
102
+static bool trans_VFNMA_dp(DisasContext *s, arg_VFNMA_dp *a)
229
uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
103
+{
230
int32_t src2, int32_t src3)
104
+ return do_vfm_dp(s, a, false, true);
231
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
105
+}
232
}
233
return ret;
234
}
235
+
106
+
236
+void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
107
+static bool trans_VFNMS_dp(DisasContext *s, arg_VFNMS_dp *a)
237
+ void *ve, uint32_t desc)
238
+{
108
+{
239
+ uintptr_t opr_sz = simd_oprsz(desc);
109
+ return do_vfm_dp(s, a, true, true);
240
+ int32_t *d = vd;
110
+}
241
+ int32_t *n = vn;
242
+ int32_t *m = vm;
243
+ CPUARMState *env = ve;
244
+ uintptr_t i;
245
+
111
+
246
+ for (i = 0; i < opr_sz / 4; ++i) {
112
static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
247
+ d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
113
{
248
+ }
114
uint32_t delta_d = 0;
249
+ clear_tail(d, opr_sz, simd_maxsz(desc));
115
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
250
+}
116
index XXXXXXX..XXXXXXX 100644
117
--- a/target/arm/vfp.decode
118
+++ b/target/arm/vfp.decode
119
@@ -XXX,XX +XXX,XX @@ VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... @vfp_dnm_d
120
VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
121
VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
122
123
-VFM_sp ---- 1110 1.01 .... .... 1010 . o2:1 . 0 .... \
124
- vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=1
125
-VFM_dp ---- 1110 1.01 .... .... 1011 . o2:1 . 0 .... \
126
- vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=1
127
-VFM_sp ---- 1110 1.10 .... .... 1010 . o2:1 . 0 .... \
128
- vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=2
129
-VFM_dp ---- 1110 1.10 .... .... 1011 . o2:1 . 0 .... \
130
- vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=2
131
+VFMA_sp ---- 1110 1.10 .... .... 1010 .0. 0 .... @vfp_dnm_s
132
+VFMS_sp ---- 1110 1.10 .... .... 1010 .1. 0 .... @vfp_dnm_s
133
+VFNMA_sp ---- 1110 1.01 .... .... 1010 .0. 0 .... @vfp_dnm_s
134
+VFNMS_sp ---- 1110 1.01 .... .... 1010 .1. 0 .... @vfp_dnm_s
135
+
136
+VFMA_dp ---- 1110 1.10 .... .... 1011 .0.0 .... @vfp_dnm_d
137
+VFMS_dp ---- 1110 1.10 .... .... 1011 .1.0 .... @vfp_dnm_d
138
+VFNMA_dp ---- 1110 1.01 .... .... 1011 .0.0 .... @vfp_dnm_d
139
+VFNMS_dp ---- 1110 1.01 .... .... 1011 .1.0 .... @vfp_dnm_d
140
141
VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \
142
vd=%vd_sp imm=%vmov_imm
251
--
143
--
252
2.16.2
144
2.20.1
253
145
254
146
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Passing the raw op field from the manual is less instructive
4
than it might be. Do the full decode and use the existing
5
helpers to perform the expansion.
6
7
Since these are v8 insns, VECLEN+VECSTRIDE are already RES0.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-5-richard.henderson@linaro.org
11
Message-id: 20200224222232.13807-18-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
target/arm/Makefile.objs | 2 +-
14
target/arm/translate-vfp.inc.c | 109 +++++++++++----------------------
9
target/arm/helper.h | 4 ++
15
target/arm/vfp-uncond.decode | 12 ++--
10
target/arm/translate-a64.c | 84 ++++++++++++++++++++++++++++++++++
16
2 files changed, 44 insertions(+), 77 deletions(-)
11
target/arm/vec_helper.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
12
4 files changed, 198 insertions(+), 1 deletion(-)
13
create mode 100644 target/arm/vec_helper.c
14
17
15
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
18
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/Makefile.objs
20
--- a/target/arm/translate-vfp.inc.c
18
+++ b/target/arm/Makefile.objs
21
+++ b/target/arm/translate-vfp.inc.c
19
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
22
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
20
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
23
return true;
21
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
22
obj-y += translate.o op_helper.o helper.o cpu.o
23
-obj-y += neon_helper.o iwmmxt_helper.o
24
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
25
obj-y += gdbstub.o
26
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
27
obj-y += crypto_helper.o
28
diff --git a/target/arm/helper.h b/target/arm/helper.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper.h
31
+++ b/target/arm/helper.h
32
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_1(neon_rbit_u8, TCG_CALL_NO_RWG_SE, i32, i32)
33
34
DEF_HELPER_3(neon_qdmulh_s16, i32, env, i32, i32)
35
DEF_HELPER_3(neon_qrdmulh_s16, i32, env, i32, i32)
36
+DEF_HELPER_4(neon_qrdmlah_s16, i32, env, i32, i32, i32)
37
+DEF_HELPER_4(neon_qrdmlsh_s16, i32, env, i32, i32, i32)
38
DEF_HELPER_3(neon_qdmulh_s32, i32, env, i32, i32)
39
DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
40
+DEF_HELPER_4(neon_qrdmlah_s32, i32, env, s32, s32, s32)
41
+DEF_HELPER_4(neon_qrdmlsh_s32, i32, env, s32, s32, s32)
42
43
DEF_HELPER_1(neon_narrow_u8, i32, i64)
44
DEF_HELPER_1(neon_narrow_u16, i32, i64)
45
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate-a64.c
48
+++ b/target/arm/translate-a64.c
49
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
50
tcg_temp_free_ptr(fpst);
51
}
24
}
52
25
53
+/* AdvSIMD scalar three same extra
26
-static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
54
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
27
-{
55
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
28
- uint32_t rd, rn, rm;
56
+ * | 0 1 | U | 1 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
29
- bool dp = a->dp;
57
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
30
- bool vmin = a->op;
58
+ */
31
- TCGv_ptr fpst;
59
+static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
32
-
60
+ uint32_t insn)
33
- if (!dc_isar_feature(aa32_vminmaxnm, s)) {
34
- return false;
35
- }
36
-
37
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
38
- return false;
39
- }
40
-
41
- /* UNDEF accesses to D16-D31 if they don't exist */
42
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
43
- ((a->vm | a->vn | a->vd) & 0x10)) {
44
- return false;
45
- }
46
-
47
- rd = a->vd;
48
- rn = a->vn;
49
- rm = a->vm;
50
-
51
- if (!vfp_access_check(s)) {
52
- return true;
53
- }
54
-
55
- fpst = get_fpstatus_ptr(0);
56
-
57
- if (dp) {
58
- TCGv_i64 frn, frm, dest;
59
-
60
- frn = tcg_temp_new_i64();
61
- frm = tcg_temp_new_i64();
62
- dest = tcg_temp_new_i64();
63
-
64
- neon_load_reg64(frn, rn);
65
- neon_load_reg64(frm, rm);
66
- if (vmin) {
67
- gen_helper_vfp_minnumd(dest, frn, frm, fpst);
68
- } else {
69
- gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
70
- }
71
- neon_store_reg64(dest, rd);
72
- tcg_temp_free_i64(frn);
73
- tcg_temp_free_i64(frm);
74
- tcg_temp_free_i64(dest);
75
- } else {
76
- TCGv_i32 frn, frm, dest;
77
-
78
- frn = tcg_temp_new_i32();
79
- frm = tcg_temp_new_i32();
80
- dest = tcg_temp_new_i32();
81
-
82
- neon_load_reg32(frn, rn);
83
- neon_load_reg32(frm, rm);
84
- if (vmin) {
85
- gen_helper_vfp_minnums(dest, frn, frm, fpst);
86
- } else {
87
- gen_helper_vfp_maxnums(dest, frn, frm, fpst);
88
- }
89
- neon_store_reg32(dest, rd);
90
- tcg_temp_free_i32(frn);
91
- tcg_temp_free_i32(frm);
92
- tcg_temp_free_i32(dest);
93
- }
94
-
95
- tcg_temp_free_ptr(fpst);
96
- return true;
97
-}
98
-
99
/*
100
* Table for converting the most common AArch32 encoding of
101
* rounding mode to arm_fprounding order (which matches the
102
@@ -XXX,XX +XXX,XX @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
103
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
104
}
105
106
+static bool trans_VMINNM_sp(DisasContext *s, arg_VMINNM_sp *a)
61
+{
107
+{
62
+ int rd = extract32(insn, 0, 5);
108
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
63
+ int rn = extract32(insn, 5, 5);
109
+ return false;
64
+ int opcode = extract32(insn, 11, 4);
65
+ int rm = extract32(insn, 16, 5);
66
+ int size = extract32(insn, 22, 2);
67
+ bool u = extract32(insn, 29, 1);
68
+ TCGv_i32 ele1, ele2, ele3;
69
+ TCGv_i64 res;
70
+ int feature;
71
+
72
+ switch (u * 16 + opcode) {
73
+ case 0x10: /* SQRDMLAH (vector) */
74
+ case 0x11: /* SQRDMLSH (vector) */
75
+ if (size != 1 && size != 2) {
76
+ unallocated_encoding(s);
77
+ return;
78
+ }
79
+ feature = ARM_FEATURE_V8_RDM;
80
+ break;
81
+ default:
82
+ unallocated_encoding(s);
83
+ return;
84
+ }
110
+ }
85
+ if (!arm_dc_feature(s, feature)) {
111
+ return do_vfp_3op_sp(s, gen_helper_vfp_minnums,
86
+ unallocated_encoding(s);
112
+ a->vd, a->vn, a->vm, false);
87
+ return;
88
+ }
89
+ if (!fp_access_check(s)) {
90
+ return;
91
+ }
92
+
93
+ /* Do a single operation on the lowest element in the vector.
94
+ * We use the standard Neon helpers and rely on 0 OP 0 == 0
95
+ * with no side effects for all these operations.
96
+ * OPTME: special-purpose helpers would avoid doing some
97
+ * unnecessary work in the helper for the 16 bit cases.
98
+ */
99
+ ele1 = tcg_temp_new_i32();
100
+ ele2 = tcg_temp_new_i32();
101
+ ele3 = tcg_temp_new_i32();
102
+
103
+ read_vec_element_i32(s, ele1, rn, 0, size);
104
+ read_vec_element_i32(s, ele2, rm, 0, size);
105
+ read_vec_element_i32(s, ele3, rd, 0, size);
106
+
107
+ switch (opcode) {
108
+ case 0x0: /* SQRDMLAH */
109
+ if (size == 1) {
110
+ gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
111
+ } else {
112
+ gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
113
+ }
114
+ break;
115
+ case 0x1: /* SQRDMLSH */
116
+ if (size == 1) {
117
+ gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
118
+ } else {
119
+ gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
120
+ }
121
+ break;
122
+ default:
123
+ g_assert_not_reached();
124
+ }
125
+ tcg_temp_free_i32(ele1);
126
+ tcg_temp_free_i32(ele2);
127
+
128
+ res = tcg_temp_new_i64();
129
+ tcg_gen_extu_i32_i64(res, ele3);
130
+ tcg_temp_free_i32(ele3);
131
+
132
+ write_fp_dreg(s, rd, res);
133
+ tcg_temp_free_i64(res);
134
+}
113
+}
135
+
114
+
136
static void handle_2misc_64(DisasContext *s, int opcode, bool u,
115
+static bool trans_VMAXNM_sp(DisasContext *s, arg_VMAXNM_sp *a)
137
TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
138
TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
139
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
140
{ 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
141
{ 0x2e000000, 0xbf208400, disas_simd_ext },
142
{ 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
143
+ { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
144
{ 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
145
{ 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
146
{ 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
147
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
148
new file mode 100644
149
index XXXXXXX..XXXXXXX
150
--- /dev/null
151
+++ b/target/arm/vec_helper.c
152
@@ -XXX,XX +XXX,XX @@
153
+/*
154
+ * ARM AdvSIMD / SVE Vector Operations
155
+ *
156
+ * Copyright (c) 2018 Linaro
157
+ *
158
+ * This library is free software; you can redistribute it and/or
159
+ * modify it under the terms of the GNU Lesser General Public
160
+ * License as published by the Free Software Foundation; either
161
+ * version 2 of the License, or (at your option) any later version.
162
+ *
163
+ * This library is distributed in the hope that it will be useful,
164
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
165
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
166
+ * Lesser General Public License for more details.
167
+ *
168
+ * You should have received a copy of the GNU Lesser General Public
169
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
170
+ */
171
+
172
+#include "qemu/osdep.h"
173
+#include "cpu.h"
174
+#include "exec/exec-all.h"
175
+#include "exec/helper-proto.h"
176
+#include "tcg/tcg-gvec-desc.h"
177
+
178
+
179
+#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
180
+
181
+/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
182
+static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
183
+ int16_t src2, int16_t src3)
184
+{
116
+{
185
+ /* Simplify:
117
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
186
+ * = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
118
+ return false;
187
+ * = ((a3 << 15) + (e1 * e2) + (1 << 14)) >> 15
188
+ */
189
+ int32_t ret = (int32_t)src1 * src2;
190
+ ret = ((int32_t)src3 << 15) + ret + (1 << 14);
191
+ ret >>= 15;
192
+ if (ret != (int16_t)ret) {
193
+ SET_QC();
194
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
195
+ }
119
+ }
196
+ return ret;
120
+ return do_vfp_3op_sp(s, gen_helper_vfp_maxnums,
121
+ a->vd, a->vn, a->vm, false);
197
+}
122
+}
198
+
123
+
199
+uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
124
+static bool trans_VMINNM_dp(DisasContext *s, arg_VMINNM_dp *a)
200
+ uint32_t src2, uint32_t src3)
201
+{
125
+{
202
+ uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
126
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
203
+ uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
127
+ return false;
204
+ return deposit32(e1, 16, 16, e2);
128
+ }
129
+ return do_vfp_3op_dp(s, gen_helper_vfp_minnumd,
130
+ a->vd, a->vn, a->vm, false);
205
+}
131
+}
206
+
132
+
207
+/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
133
+static bool trans_VMAXNM_dp(DisasContext *s, arg_VMAXNM_dp *a)
208
+static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
209
+ int16_t src2, int16_t src3)
210
+{
134
+{
211
+ /* Similarly, using subtraction:
135
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
212
+ * = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
136
+ return false;
213
+ * = ((a3 << 15) - (e1 * e2) + (1 << 14)) >> 15
214
+ */
215
+ int32_t ret = (int32_t)src1 * src2;
216
+ ret = ((int32_t)src3 << 15) - ret + (1 << 14);
217
+ ret >>= 15;
218
+ if (ret != (int16_t)ret) {
219
+ SET_QC();
220
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
221
+ }
137
+ }
222
+ return ret;
138
+ return do_vfp_3op_dp(s, gen_helper_vfp_maxnumd,
139
+ a->vd, a->vn, a->vm, false);
223
+}
140
+}
224
+
141
+
225
+uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
142
static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
226
+ uint32_t src2, uint32_t src3)
143
{
227
+{
144
/*
228
+ uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
145
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
229
+ uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
146
index XXXXXXX..XXXXXXX 100644
230
+ return deposit32(e1, 16, 16, e2);
147
--- a/target/arm/vfp-uncond.decode
231
+}
148
+++ b/target/arm/vfp-uncond.decode
149
@@ -XXX,XX +XXX,XX @@
150
%vd_dp 22:1 12:4
151
%vd_sp 12:4 22:1
152
153
+@vfp_dnm_s ................................ vm=%vm_sp vn=%vn_sp vd=%vd_sp
154
+@vfp_dnm_d ................................ vm=%vm_dp vn=%vn_dp vd=%vd_dp
232
+
155
+
233
+/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
156
VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
234
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
157
vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
235
+ int32_t src2, int32_t src3)
158
VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
236
+{
159
vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
237
+ /* Simplify similarly to int_qrdmlah_s16 above. */
160
238
+ int64_t ret = (int64_t)src1 * src2;
161
-VMINMAXNM 1111 1110 1.00 .... .... 1010 . op:1 .0 .... \
239
+ ret = ((int64_t)src3 << 31) + ret + (1 << 30);
162
- vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
240
+ ret >>= 31;
163
-VMINMAXNM 1111 1110 1.00 .... .... 1011 . op:1 .0 .... \
241
+ if (ret != (int32_t)ret) {
164
- vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
242
+ SET_QC();
165
+VMAXNM_sp 1111 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
243
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
166
+VMINNM_sp 1111 1110 1.00 .... .... 1010 .1.0 .... @vfp_dnm_s
244
+ }
245
+ return ret;
246
+}
247
+
167
+
248
+/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
168
+VMAXNM_dp 1111 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
249
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
169
+VMINNM_dp 1111 1110 1.00 .... .... 1011 .1.0 .... @vfp_dnm_d
250
+ int32_t src2, int32_t src3)
170
251
+{
171
VRINT 1111 1110 1.11 10 rm:2 .... 1010 01.0 .... \
252
+ /* Simplify similarly to int_qrdmlsh_s16 above. */
172
vm=%vm_sp vd=%vd_sp dp=0
253
+ int64_t ret = (int64_t)src1 * src2;
254
+ ret = ((int64_t)src3 << 31) - ret + (1 << 30);
255
+ ret >>= 31;
256
+ if (ret != (int32_t)ret) {
257
+ SET_QC();
258
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
259
+ }
260
+ return ret;
261
+}
262
--
173
--
263
2.16.2
174
2.20.1
264
175
265
176
diff view generated by jsdifflib
1
Add remaining easy registers to iotkit-secctl:
1
From: Guenter Roeck <linux@roeck-us.net>
2
* NSCCFG just routes its two bits out to external GPIO lines
3
* BRGINSTAT/BRGINTCLR/BRGINTEN can be dummies, because QEMU's
4
bus fabric can never report errors
5
2
3
USB ports on Xilinx Zync must be instantiated as TYPE_CHIPIDEA to work.
4
Linux expects and checks various chipidea registers, which do not exist
5
with the basic ehci emulation. This patch series fixes the problem.
6
7
Without this patch, USB ports fail to instantiate under Linux.
8
9
ci_hdrc ci_hdrc.0: doesn't support host
10
ci_hdrc ci_hdrc.0: no supported roles
11
12
With this patch, USB ports are instantiated, and it is possible
13
to boot from USB drive.
14
15
ci_hdrc ci_hdrc.0: EHCI Host Controller
16
ci_hdrc ci_hdrc.0: new USB bus registered, assigned bus number 1
17
ci_hdrc ci_hdrc.0: USB 2.0 started, EHCI 1.00
18
usb 1-1: new full-speed USB device number 2 using ci_hdrc
19
usb 1-1: not running at top speed; connect to a high speed hub
20
usb 1-1: config 1 interface 0 altsetting 0 endpoint 0x81 has invalid maxpacket 512, setting to 64
21
usb 1-1: config 1 interface 0 altsetting 0 endpoint 0x2 has invalid maxpacket 512, setting to 64
22
usb-storage 1-1:1.0: USB Mass Storage device detected
23
scsi host0: usb-storage 1-1:1.0
24
25
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
26
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
27
Message-id: 20200215122354.13706-2-linux@roeck-us.net
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180220180325.29818-18-peter.maydell@linaro.org
8
---
29
---
9
include/hw/misc/iotkit-secctl.h | 4 ++++
30
hw/arm/xilinx_zynq.c | 5 +++--
10
hw/misc/iotkit-secctl.c | 32 ++++++++++++++++++++++++++------
31
1 file changed, 3 insertions(+), 2 deletions(-)
11
2 files changed, 30 insertions(+), 6 deletions(-)
12
32
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
33
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
14
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
35
--- a/hw/arm/xilinx_zynq.c
16
+++ b/include/hw/misc/iotkit-secctl.h
36
+++ b/hw/arm/xilinx_zynq.c
17
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
18
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
38
#include "hw/loader.h"
19
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
39
#include "hw/misc/zynq-xadc.h"
20
* should RAZ/WI or bus error
40
#include "hw/ssi/ssi.h"
21
+ * + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
41
+#include "hw/usb/chipidea.h"
22
* Controlling the 2 APB PPCs in the IoTKit:
42
#include "qemu/error-report.h"
23
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
43
#include "hw/sd/sdhci.h"
24
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
44
#include "hw/char/cadence_uart.h"
25
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
45
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
26
46
zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false);
27
/*< public >*/
47
zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
28
qemu_irq sec_resp_cfg;
48
29
+ qemu_irq nsc_cfg_irq;
49
- sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
30
50
- sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
31
MemoryRegion s_regs;
51
+ sysbus_create_simple(TYPE_CHIPIDEA, 0xE0002000, pic[53 - IRQ_OFFSET]);
32
MemoryRegion ns_regs;
52
+ sysbus_create_simple(TYPE_CHIPIDEA, 0xE0003000, pic[76 - IRQ_OFFSET]);
33
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
53
34
uint32_t secppcintstat;
54
cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0));
35
uint32_t secppcinten;
55
cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1));
36
uint32_t secrespcfg;
37
+ uint32_t nsccfg;
38
+ uint32_t brginten;
39
40
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
41
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
42
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/iotkit-secctl.c
45
+++ b/hw/misc/iotkit-secctl.c
46
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
47
case A_SECRESPCFG:
48
r = s->secrespcfg;
49
break;
50
+ case A_NSCCFG:
51
+ r = s->nsccfg;
52
+ break;
53
case A_SECPPCINTSTAT:
54
r = s->secppcintstat;
55
break;
56
case A_SECPPCINTEN:
57
r = s->secppcinten;
58
break;
59
+ case A_BRGINTSTAT:
60
+ /* QEMU's bus fabric can never report errors as it doesn't buffer
61
+ * writes, so we never report bridge interrupts.
62
+ */
63
+ r = 0;
64
+ break;
65
+ case A_BRGINTEN:
66
+ r = s->brginten;
67
+ break;
68
case A_AHBNSPPCEXP0:
69
case A_AHBNSPPCEXP1:
70
case A_AHBNSPPCEXP2:
71
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
72
case A_APBSPPPCEXP3:
73
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
74
break;
75
- case A_NSCCFG:
76
case A_SECMPCINTSTATUS:
77
case A_SECMSCINTSTAT:
78
case A_SECMSCINTEN:
79
- case A_BRGINTSTAT:
80
- case A_BRGINTEN:
81
case A_NSMSCEXP:
82
qemu_log_mask(LOG_UNIMP,
83
"IoTKit SecCtl S block read: "
84
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
85
}
86
87
switch (offset) {
88
+ case A_NSCCFG:
89
+ s->nsccfg = value & 3;
90
+ qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
91
+ break;
92
case A_SECRESPCFG:
93
value &= 1;
94
s->secrespcfg = value;
95
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
96
s->secppcinten = value & 0x00f000f3;
97
foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
98
break;
99
+ case A_BRGINTCLR:
100
+ break;
101
+ case A_BRGINTEN:
102
+ s->brginten = value & 0xffff0000;
103
+ break;
104
case A_AHBNSPPCEXP0:
105
case A_AHBNSPPCEXP1:
106
case A_AHBNSPPCEXP2:
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
108
ppc = &s->apbexp[offset_to_ppc_idx(offset)];
109
iotkit_secctl_ppc_sp_write(ppc, value);
110
break;
111
- case A_NSCCFG:
112
case A_SECMSCINTCLR:
113
case A_SECMSCINTEN:
114
- case A_BRGINTCLR:
115
- case A_BRGINTEN:
116
qemu_log_mask(LOG_UNIMP,
117
"IoTKit SecCtl S block write: "
118
"unimplemented offset 0x%x\n", offset);
119
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_reset(DeviceState *dev)
120
s->secppcintstat = 0;
121
s->secppcinten = 0;
122
s->secrespcfg = 0;
123
+ s->nsccfg = 0;
124
+ s->brginten = 0;
125
126
foreach_ppc(s, iotkit_secctl_reset_ppc);
127
}
128
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
129
}
130
131
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
132
+ qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
133
134
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
135
s, "iotkit-secctl-s-regs", 0x1000);
136
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
137
VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
138
VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
139
VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
140
+ VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
141
+ VMSTATE_UINT32(brginten, IoTKitSecCtl),
142
VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
143
iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
144
VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
145
--
56
--
146
2.16.2
57
2.20.1
147
58
148
59
diff view generated by jsdifflib
1
Create an "idau" property on the armv7m container object which
1
From: Guenter Roeck <linux@roeck-us.net>
2
we can forward to the CPU object. Annoyingly, we can't use
3
object_property_add_alias() because the CPU object we want to
4
forward to doesn't exist until the armv7m container is realized.
5
2
3
Xilinx USB devices are now instantiated through TYPE_CHIPIDEA,
4
and xlnx support in the EHCI code is no longer needed.
5
6
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
7
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
8
Message-id: 20200215122354.13706-3-linux@roeck-us.net
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-6-peter.maydell@linaro.org
9
---
10
---
10
include/hw/arm/armv7m.h | 3 +++
11
hw/usb/hcd-ehci-sysbus.c | 17 -----------------
11
hw/arm/armv7m.c | 9 +++++++++
12
1 file changed, 17 deletions(-)
12
2 files changed, 12 insertions(+)
13
13
14
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
14
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armv7m.h
16
--- a/hw/usb/hcd-ehci-sysbus.c
17
+++ b/include/hw/arm/armv7m.h
17
+++ b/hw/usb/hcd-ehci-sysbus.c
18
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ehci_platform_type_info = {
19
19
.class_init = ehci_platform_class_init,
20
#include "hw/sysbus.h"
21
#include "hw/intc/armv7m_nvic.h"
22
+#include "target/arm/idau.h"
23
24
#define TYPE_BITBAND "ARM,bitband-memory"
25
#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
26
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
* + Property "memory": MemoryRegion defining the physical address space
28
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
29
* devices will be automatically layered on top of this view.)
30
+ * + Property "idau": IDAU interface (forwarded to CPU object)
31
*/
32
typedef struct ARMv7MState {
33
/*< private >*/
34
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
35
char *cpu_type;
36
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
37
MemoryRegion *board_memory;
38
+ Object *idau;
39
} ARMv7MState;
40
41
#endif
42
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/armv7m.c
45
+++ b/hw/arm/armv7m.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "sysemu/qtest.h"
48
#include "qemu/error-report.h"
49
#include "exec/address-spaces.h"
50
+#include "target/arm/idau.h"
51
52
/* Bitbanded IO. Each word corresponds to a single bit. */
53
54
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
55
56
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
57
&error_abort);
58
+ if (object_property_find(OBJECT(s->cpu), "idau", NULL)) {
59
+ object_property_set_link(OBJECT(s->cpu), s->idau, "idau", &err);
60
+ if (err != NULL) {
61
+ error_propagate(errp, err);
62
+ return;
63
+ }
64
+ }
65
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
66
if (err != NULL) {
67
error_propagate(errp, err);
68
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
69
DEFINE_PROP_STRING("cpu-type", ARMv7MState, cpu_type),
70
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
71
MemoryRegion *),
72
+ DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
73
DEFINE_PROP_END_OF_LIST(),
74
};
20
};
75
21
22
-static void ehci_xlnx_class_init(ObjectClass *oc, void *data)
23
-{
24
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
25
- DeviceClass *dc = DEVICE_CLASS(oc);
26
-
27
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
28
- sec->capsbase = 0x100;
29
- sec->opregbase = 0x140;
30
-}
31
-
32
-static const TypeInfo ehci_xlnx_type_info = {
33
- .name = "xlnx,ps7-usb",
34
- .parent = TYPE_SYS_BUS_EHCI,
35
- .class_init = ehci_xlnx_class_init,
36
-};
37
-
38
static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
39
{
40
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
41
@@ -XXX,XX +XXX,XX @@ static void ehci_sysbus_register_types(void)
42
{
43
type_register_static(&ehci_type_info);
44
type_register_static(&ehci_platform_type_info);
45
- type_register_static(&ehci_xlnx_type_info);
46
type_register_static(&ehci_exynos4210_type_info);
47
type_register_static(&ehci_tegra2_type_info);
48
type_register_static(&ehci_ppc4xx_type_info);
76
--
49
--
77
2.16.2
50
2.20.1
78
51
79
52
diff view generated by jsdifflib
1
The Arm IoT Kit includes a "security controller" which is largely a
1
From: Thomas Huth <thuth@redhat.com>
2
collection of registers for controlling the PPCs and other bits of
3
glue in the system. This commit provides the initial skeleton of the
4
device, implementing just the ID registers, and a couple of read-only
5
read-as-zero registers.
6
2
3
Old kernels from the Meego project can be used to check that Linux
4
is at least starting on these machines.
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20200225172501.29609-2-philmd@redhat.com
12
Message-Id: <20200129131920.22302-1-thuth@redhat.com>
13
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-16-peter.maydell@linaro.org
10
---
15
---
11
hw/misc/Makefile.objs | 1 +
16
MAINTAINERS | 1 +
12
include/hw/misc/iotkit-secctl.h | 39 ++++
17
tests/acceptance/machine_arm_n8x0.py | 49 ++++++++++++++++++++++++++++
13
hw/misc/iotkit-secctl.c | 448 ++++++++++++++++++++++++++++++++++++++++
18
2 files changed, 50 insertions(+)
14
default-configs/arm-softmmu.mak | 1 +
19
create mode 100644 tests/acceptance/machine_arm_n8x0.py
15
hw/misc/trace-events | 7 +
16
5 files changed, 496 insertions(+)
17
create mode 100644 include/hw/misc/iotkit-secctl.h
18
create mode 100644 hw/misc/iotkit-secctl.c
19
20
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
21
diff --git a/MAINTAINERS b/MAINTAINERS
21
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
23
--- a/MAINTAINERS
23
+++ b/hw/misc/Makefile.objs
24
+++ b/MAINTAINERS
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
25
@@ -XXX,XX +XXX,XX @@ F: hw/rtc/twl92230.c
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
26
F: include/hw/display/blizzard.h
26
27
F: include/hw/input/tsc2xxx.h
27
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
28
F: include/hw/misc/cbus.h
28
+obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
29
+F: tests/acceptance/machine_arm_n8x0.py
29
30
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
31
Palm
31
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
32
M: Andrzej Zaborowski <balrogg@gmail.com>
32
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
33
diff --git a/tests/acceptance/machine_arm_n8x0.py b/tests/acceptance/machine_arm_n8x0.py
33
new file mode 100644
34
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
--- /dev/null
36
+++ b/include/hw/misc/iotkit-secctl.h
37
+++ b/tests/acceptance/machine_arm_n8x0.py
37
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+# Functional test that boots a Linux kernel and checks the console
39
+ * ARM IoT Kit security controller
40
+#
40
+ *
41
+# Copyright (c) 2020 Red Hat, Inc.
41
+ * Copyright (c) 2018 Linaro Limited
42
+#
42
+ * Written by Peter Maydell
43
+# Author:
43
+ *
44
+# Thomas Huth <thuth@redhat.com>
44
+ * This program is free software; you can redistribute it and/or modify
45
+#
45
+ * it under the terms of the GNU General Public License version 2 or
46
+# This work is licensed under the terms of the GNU GPL, version 2 or
46
+ * (at your option) any later version.
47
+# later. See the COPYING file in the top-level directory.
47
+ */
48
+
48
+
49
+/* This is a model of the security controller which is part of the
49
+import os
50
+ * Arm IoT Kit and documented in
51
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
52
+ *
53
+ * QEMU interface:
54
+ * + sysbus MMIO region 0 is the "secure privilege control block" registers
55
+ * + sysbus MMIO region 1 is the "non-secure privilege control block" registers
56
+ */
57
+
50
+
58
+#ifndef IOTKIT_SECCTL_H
51
+from avocado import skipUnless
59
+#define IOTKIT_SECCTL_H
52
+from avocado_qemu import Test
53
+from avocado_qemu import wait_for_console_pattern
60
+
54
+
61
+#include "hw/sysbus.h"
55
+class N8x0Machine(Test):
56
+ """Boots the Linux kernel and checks that the console is operational"""
62
+
57
+
63
+#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
58
+ timeout = 90
64
+#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
65
+
59
+
66
+typedef struct IoTKitSecCtl {
60
+ def __do_test_n8x0(self):
67
+ /*< private >*/
61
+ kernel_url = ('http://stskeeps.subnetmask.net/meego-n8x0/'
68
+ SysBusDevice parent_obj;
62
+ 'meego-arm-n8x0-1.0.80.20100712.1431-'
63
+ 'vmlinuz-2.6.35~rc4-129.1-n8x0')
64
+ kernel_hash = 'e9d5ab8d7548923a0061b6fbf601465e479ed269'
65
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
69
+
66
+
70
+ /*< public >*/
67
+ self.vm.set_console(console_index=1)
68
+ self.vm.add_args('-kernel', kernel_path,
69
+ '-append', 'printk.time=0 console=ttyS1')
70
+ self.vm.launch()
71
+ wait_for_console_pattern(self, 'TSC2005 driver initializing')
71
+
72
+
72
+ MemoryRegion s_regs;
73
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
73
+ MemoryRegion ns_regs;
74
+ def test_n800(self):
74
+} IoTKitSecCtl;
75
+ """
76
+ :avocado: tags=arch:arm
77
+ :avocado: tags=machine:n800
78
+ """
79
+ self.__do_test_n8x0()
75
+
80
+
76
+#endif
81
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
77
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
82
+ def test_n810(self):
78
new file mode 100644
83
+ """
79
index XXXXXXX..XXXXXXX
84
+ :avocado: tags=arch:arm
80
--- /dev/null
85
+ :avocado: tags=machine:n810
81
+++ b/hw/misc/iotkit-secctl.c
86
+ """
82
@@ -XXX,XX +XXX,XX @@
87
+ self.__do_test_n8x0()
83
+/*
84
+ * Arm IoT Kit security controller
85
+ *
86
+ * Copyright (c) 2018 Linaro Limited
87
+ * Written by Peter Maydell
88
+ *
89
+ * This program is free software; you can redistribute it and/or modify
90
+ * it under the terms of the GNU General Public License version 2 or
91
+ * (at your option) any later version.
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qapi/error.h"
97
+#include "trace.h"
98
+#include "hw/sysbus.h"
99
+#include "hw/registerfields.h"
100
+#include "hw/misc/iotkit-secctl.h"
101
+
102
+/* Registers in the secure privilege control block */
103
+REG32(SECRESPCFG, 0x10)
104
+REG32(NSCCFG, 0x14)
105
+REG32(SECMPCINTSTATUS, 0x1c)
106
+REG32(SECPPCINTSTAT, 0x20)
107
+REG32(SECPPCINTCLR, 0x24)
108
+REG32(SECPPCINTEN, 0x28)
109
+REG32(SECMSCINTSTAT, 0x30)
110
+REG32(SECMSCINTCLR, 0x34)
111
+REG32(SECMSCINTEN, 0x38)
112
+REG32(BRGINTSTAT, 0x40)
113
+REG32(BRGINTCLR, 0x44)
114
+REG32(BRGINTEN, 0x48)
115
+REG32(AHBNSPPC0, 0x50)
116
+REG32(AHBNSPPCEXP0, 0x60)
117
+REG32(AHBNSPPCEXP1, 0x64)
118
+REG32(AHBNSPPCEXP2, 0x68)
119
+REG32(AHBNSPPCEXP3, 0x6c)
120
+REG32(APBNSPPC0, 0x70)
121
+REG32(APBNSPPC1, 0x74)
122
+REG32(APBNSPPCEXP0, 0x80)
123
+REG32(APBNSPPCEXP1, 0x84)
124
+REG32(APBNSPPCEXP2, 0x88)
125
+REG32(APBNSPPCEXP3, 0x8c)
126
+REG32(AHBSPPPC0, 0x90)
127
+REG32(AHBSPPPCEXP0, 0xa0)
128
+REG32(AHBSPPPCEXP1, 0xa4)
129
+REG32(AHBSPPPCEXP2, 0xa8)
130
+REG32(AHBSPPPCEXP3, 0xac)
131
+REG32(APBSPPPC0, 0xb0)
132
+REG32(APBSPPPC1, 0xb4)
133
+REG32(APBSPPPCEXP0, 0xc0)
134
+REG32(APBSPPPCEXP1, 0xc4)
135
+REG32(APBSPPPCEXP2, 0xc8)
136
+REG32(APBSPPPCEXP3, 0xcc)
137
+REG32(NSMSCEXP, 0xd0)
138
+REG32(PID4, 0xfd0)
139
+REG32(PID5, 0xfd4)
140
+REG32(PID6, 0xfd8)
141
+REG32(PID7, 0xfdc)
142
+REG32(PID0, 0xfe0)
143
+REG32(PID1, 0xfe4)
144
+REG32(PID2, 0xfe8)
145
+REG32(PID3, 0xfec)
146
+REG32(CID0, 0xff0)
147
+REG32(CID1, 0xff4)
148
+REG32(CID2, 0xff8)
149
+REG32(CID3, 0xffc)
150
+
151
+/* Registers in the non-secure privilege control block */
152
+REG32(AHBNSPPPC0, 0x90)
153
+REG32(AHBNSPPPCEXP0, 0xa0)
154
+REG32(AHBNSPPPCEXP1, 0xa4)
155
+REG32(AHBNSPPPCEXP2, 0xa8)
156
+REG32(AHBNSPPPCEXP3, 0xac)
157
+REG32(APBNSPPPC0, 0xb0)
158
+REG32(APBNSPPPC1, 0xb4)
159
+REG32(APBNSPPPCEXP0, 0xc0)
160
+REG32(APBNSPPPCEXP1, 0xc4)
161
+REG32(APBNSPPPCEXP2, 0xc8)
162
+REG32(APBNSPPPCEXP3, 0xcc)
163
+/* PID and CID registers are also present in the NS block */
164
+
165
+static const uint8_t iotkit_secctl_s_idregs[] = {
166
+ 0x04, 0x00, 0x00, 0x00,
167
+ 0x52, 0xb8, 0x0b, 0x00,
168
+ 0x0d, 0xf0, 0x05, 0xb1,
169
+};
170
+
171
+static const uint8_t iotkit_secctl_ns_idregs[] = {
172
+ 0x04, 0x00, 0x00, 0x00,
173
+ 0x53, 0xb8, 0x0b, 0x00,
174
+ 0x0d, 0xf0, 0x05, 0xb1,
175
+};
176
+
177
+static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
178
+ uint64_t *pdata,
179
+ unsigned size, MemTxAttrs attrs)
180
+{
181
+ uint64_t r;
182
+ uint32_t offset = addr & ~0x3;
183
+
184
+ switch (offset) {
185
+ case A_AHBNSPPC0:
186
+ case A_AHBSPPPC0:
187
+ r = 0;
188
+ break;
189
+ case A_SECRESPCFG:
190
+ case A_NSCCFG:
191
+ case A_SECMPCINTSTATUS:
192
+ case A_SECPPCINTSTAT:
193
+ case A_SECPPCINTEN:
194
+ case A_SECMSCINTSTAT:
195
+ case A_SECMSCINTEN:
196
+ case A_BRGINTSTAT:
197
+ case A_BRGINTEN:
198
+ case A_AHBNSPPCEXP0:
199
+ case A_AHBNSPPCEXP1:
200
+ case A_AHBNSPPCEXP2:
201
+ case A_AHBNSPPCEXP3:
202
+ case A_APBNSPPC0:
203
+ case A_APBNSPPC1:
204
+ case A_APBNSPPCEXP0:
205
+ case A_APBNSPPCEXP1:
206
+ case A_APBNSPPCEXP2:
207
+ case A_APBNSPPCEXP3:
208
+ case A_AHBSPPPCEXP0:
209
+ case A_AHBSPPPCEXP1:
210
+ case A_AHBSPPPCEXP2:
211
+ case A_AHBSPPPCEXP3:
212
+ case A_APBSPPPC0:
213
+ case A_APBSPPPC1:
214
+ case A_APBSPPPCEXP0:
215
+ case A_APBSPPPCEXP1:
216
+ case A_APBSPPPCEXP2:
217
+ case A_APBSPPPCEXP3:
218
+ case A_NSMSCEXP:
219
+ qemu_log_mask(LOG_UNIMP,
220
+ "IoTKit SecCtl S block read: "
221
+ "unimplemented offset 0x%x\n", offset);
222
+ r = 0;
223
+ break;
224
+ case A_PID4:
225
+ case A_PID5:
226
+ case A_PID6:
227
+ case A_PID7:
228
+ case A_PID0:
229
+ case A_PID1:
230
+ case A_PID2:
231
+ case A_PID3:
232
+ case A_CID0:
233
+ case A_CID1:
234
+ case A_CID2:
235
+ case A_CID3:
236
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
237
+ break;
238
+ case A_SECPPCINTCLR:
239
+ case A_SECMSCINTCLR:
240
+ case A_BRGINTCLR:
241
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ "IotKit SecCtl S block read: write-only offset 0x%x\n",
243
+ offset);
244
+ r = 0;
245
+ break;
246
+ default:
247
+ qemu_log_mask(LOG_GUEST_ERROR,
248
+ "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
249
+ r = 0;
250
+ break;
251
+ }
252
+
253
+ if (size != 4) {
254
+ /* None of our registers are access-sensitive, so just pull the right
255
+ * byte out of the word read result.
256
+ */
257
+ r = extract32(r, (addr & 3) * 8, size * 8);
258
+ }
259
+
260
+ trace_iotkit_secctl_s_read(offset, r, size);
261
+ *pdata = r;
262
+ return MEMTX_OK;
263
+}
264
+
265
+static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
266
+ uint64_t value,
267
+ unsigned size, MemTxAttrs attrs)
268
+{
269
+ uint32_t offset = addr;
270
+
271
+ trace_iotkit_secctl_s_write(offset, value, size);
272
+
273
+ if (size != 4) {
274
+ /* Byte and halfword writes are ignored */
275
+ qemu_log_mask(LOG_GUEST_ERROR,
276
+ "IotKit SecCtl S block write: bad size, ignored\n");
277
+ return MEMTX_OK;
278
+ }
279
+
280
+ switch (offset) {
281
+ case A_SECRESPCFG:
282
+ case A_NSCCFG:
283
+ case A_SECPPCINTCLR:
284
+ case A_SECPPCINTEN:
285
+ case A_SECMSCINTCLR:
286
+ case A_SECMSCINTEN:
287
+ case A_BRGINTCLR:
288
+ case A_BRGINTEN:
289
+ case A_AHBNSPPCEXP0:
290
+ case A_AHBNSPPCEXP1:
291
+ case A_AHBNSPPCEXP2:
292
+ case A_AHBNSPPCEXP3:
293
+ case A_APBNSPPC0:
294
+ case A_APBNSPPC1:
295
+ case A_APBNSPPCEXP0:
296
+ case A_APBNSPPCEXP1:
297
+ case A_APBNSPPCEXP2:
298
+ case A_APBNSPPCEXP3:
299
+ case A_AHBSPPPCEXP0:
300
+ case A_AHBSPPPCEXP1:
301
+ case A_AHBSPPPCEXP2:
302
+ case A_AHBSPPPCEXP3:
303
+ case A_APBSPPPC0:
304
+ case A_APBSPPPC1:
305
+ case A_APBSPPPCEXP0:
306
+ case A_APBSPPPCEXP1:
307
+ case A_APBSPPPCEXP2:
308
+ case A_APBSPPPCEXP3:
309
+ qemu_log_mask(LOG_UNIMP,
310
+ "IoTKit SecCtl S block write: "
311
+ "unimplemented offset 0x%x\n", offset);
312
+ break;
313
+ case A_SECMPCINTSTATUS:
314
+ case A_SECPPCINTSTAT:
315
+ case A_SECMSCINTSTAT:
316
+ case A_BRGINTSTAT:
317
+ case A_AHBNSPPC0:
318
+ case A_AHBSPPPC0:
319
+ case A_NSMSCEXP:
320
+ case A_PID4:
321
+ case A_PID5:
322
+ case A_PID6:
323
+ case A_PID7:
324
+ case A_PID0:
325
+ case A_PID1:
326
+ case A_PID2:
327
+ case A_PID3:
328
+ case A_CID0:
329
+ case A_CID1:
330
+ case A_CID2:
331
+ case A_CID3:
332
+ qemu_log_mask(LOG_GUEST_ERROR,
333
+ "IoTKit SecCtl S block write: "
334
+ "read-only offset 0x%x\n", offset);
335
+ break;
336
+ default:
337
+ qemu_log_mask(LOG_GUEST_ERROR,
338
+ "IotKit SecCtl S block write: bad offset 0x%x\n",
339
+ offset);
340
+ break;
341
+ }
342
+
343
+ return MEMTX_OK;
344
+}
345
+
346
+static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
347
+ uint64_t *pdata,
348
+ unsigned size, MemTxAttrs attrs)
349
+{
350
+ uint64_t r;
351
+ uint32_t offset = addr & ~0x3;
352
+
353
+ switch (offset) {
354
+ case A_AHBNSPPPC0:
355
+ r = 0;
356
+ break;
357
+ case A_AHBNSPPPCEXP0:
358
+ case A_AHBNSPPPCEXP1:
359
+ case A_AHBNSPPPCEXP2:
360
+ case A_AHBNSPPPCEXP3:
361
+ case A_APBNSPPPC0:
362
+ case A_APBNSPPPC1:
363
+ case A_APBNSPPPCEXP0:
364
+ case A_APBNSPPPCEXP1:
365
+ case A_APBNSPPPCEXP2:
366
+ case A_APBNSPPPCEXP3:
367
+ qemu_log_mask(LOG_UNIMP,
368
+ "IoTKit SecCtl NS block read: "
369
+ "unimplemented offset 0x%x\n", offset);
370
+ break;
371
+ case A_PID4:
372
+ case A_PID5:
373
+ case A_PID6:
374
+ case A_PID7:
375
+ case A_PID0:
376
+ case A_PID1:
377
+ case A_PID2:
378
+ case A_PID3:
379
+ case A_CID0:
380
+ case A_CID1:
381
+ case A_CID2:
382
+ case A_CID3:
383
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
384
+ break;
385
+ default:
386
+ qemu_log_mask(LOG_GUEST_ERROR,
387
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
388
+ offset);
389
+ r = 0;
390
+ break;
391
+ }
392
+
393
+ if (size != 4) {
394
+ /* None of our registers are access-sensitive, so just pull the right
395
+ * byte out of the word read result.
396
+ */
397
+ r = extract32(r, (addr & 3) * 8, size * 8);
398
+ }
399
+
400
+ trace_iotkit_secctl_ns_read(offset, r, size);
401
+ *pdata = r;
402
+ return MEMTX_OK;
403
+}
404
+
405
+static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
406
+ uint64_t value,
407
+ unsigned size, MemTxAttrs attrs)
408
+{
409
+ uint32_t offset = addr;
410
+
411
+ trace_iotkit_secctl_ns_write(offset, value, size);
412
+
413
+ if (size != 4) {
414
+ /* Byte and halfword writes are ignored */
415
+ qemu_log_mask(LOG_GUEST_ERROR,
416
+ "IotKit SecCtl NS block write: bad size, ignored\n");
417
+ return MEMTX_OK;
418
+ }
419
+
420
+ switch (offset) {
421
+ case A_AHBNSPPPCEXP0:
422
+ case A_AHBNSPPPCEXP1:
423
+ case A_AHBNSPPPCEXP2:
424
+ case A_AHBNSPPPCEXP3:
425
+ case A_APBNSPPPC0:
426
+ case A_APBNSPPPC1:
427
+ case A_APBNSPPPCEXP0:
428
+ case A_APBNSPPPCEXP1:
429
+ case A_APBNSPPPCEXP2:
430
+ case A_APBNSPPPCEXP3:
431
+ qemu_log_mask(LOG_UNIMP,
432
+ "IoTKit SecCtl NS block write: "
433
+ "unimplemented offset 0x%x\n", offset);
434
+ break;
435
+ case A_AHBNSPPPC0:
436
+ case A_PID4:
437
+ case A_PID5:
438
+ case A_PID6:
439
+ case A_PID7:
440
+ case A_PID0:
441
+ case A_PID1:
442
+ case A_PID2:
443
+ case A_PID3:
444
+ case A_CID0:
445
+ case A_CID1:
446
+ case A_CID2:
447
+ case A_CID3:
448
+ qemu_log_mask(LOG_GUEST_ERROR,
449
+ "IoTKit SecCtl NS block write: "
450
+ "read-only offset 0x%x\n", offset);
451
+ break;
452
+ default:
453
+ qemu_log_mask(LOG_GUEST_ERROR,
454
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
455
+ offset);
456
+ break;
457
+ }
458
+
459
+ return MEMTX_OK;
460
+}
461
+
462
+static const MemoryRegionOps iotkit_secctl_s_ops = {
463
+ .read_with_attrs = iotkit_secctl_s_read,
464
+ .write_with_attrs = iotkit_secctl_s_write,
465
+ .endianness = DEVICE_LITTLE_ENDIAN,
466
+ .valid.min_access_size = 1,
467
+ .valid.max_access_size = 4,
468
+ .impl.min_access_size = 1,
469
+ .impl.max_access_size = 4,
470
+};
471
+
472
+static const MemoryRegionOps iotkit_secctl_ns_ops = {
473
+ .read_with_attrs = iotkit_secctl_ns_read,
474
+ .write_with_attrs = iotkit_secctl_ns_write,
475
+ .endianness = DEVICE_LITTLE_ENDIAN,
476
+ .valid.min_access_size = 1,
477
+ .valid.max_access_size = 4,
478
+ .impl.min_access_size = 1,
479
+ .impl.max_access_size = 4,
480
+};
481
+
482
+static void iotkit_secctl_reset(DeviceState *dev)
483
+{
484
+
485
+}
486
+
487
+static void iotkit_secctl_init(Object *obj)
488
+{
489
+ IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
490
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
491
+
492
+ memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
+ s, "iotkit-secctl-s-regs", 0x1000);
494
+ memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
495
+ s, "iotkit-secctl-ns-regs", 0x1000);
496
+ sysbus_init_mmio(sbd, &s->s_regs);
497
+ sysbus_init_mmio(sbd, &s->ns_regs);
498
+}
499
+
500
+static const VMStateDescription iotkit_secctl_vmstate = {
501
+ .name = "iotkit-secctl",
502
+ .version_id = 1,
503
+ .minimum_version_id = 1,
504
+ .fields = (VMStateField[]) {
505
+ VMSTATE_END_OF_LIST()
506
+ }
507
+};
508
+
509
+static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
510
+{
511
+ DeviceClass *dc = DEVICE_CLASS(klass);
512
+
513
+ dc->vmsd = &iotkit_secctl_vmstate;
514
+ dc->reset = iotkit_secctl_reset;
515
+}
516
+
517
+static const TypeInfo iotkit_secctl_info = {
518
+ .name = TYPE_IOTKIT_SECCTL,
519
+ .parent = TYPE_SYS_BUS_DEVICE,
520
+ .instance_size = sizeof(IoTKitSecCtl),
521
+ .instance_init = iotkit_secctl_init,
522
+ .class_init = iotkit_secctl_class_init,
523
+};
524
+
525
+static void iotkit_secctl_register_types(void)
526
+{
527
+ type_register_static(&iotkit_secctl_info);
528
+}
529
+
530
+type_init(iotkit_secctl_register_types);
531
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
532
index XXXXXXX..XXXXXXX 100644
533
--- a/default-configs/arm-softmmu.mak
534
+++ b/default-configs/arm-softmmu.mak
535
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
536
CONFIG_MPS2_SCC=y
537
538
CONFIG_TZ_PPC=y
539
+CONFIG_IOTKIT_SECCTL=y
540
541
CONFIG_VERSATILE_PCI=y
542
CONFIG_VERSATILE_I2C=y
543
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
544
index XXXXXXX..XXXXXXX 100644
545
--- a/hw/misc/trace-events
546
+++ b/hw/misc/trace-events
547
@@ -XXX,XX +XXX,XX @@ tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
548
tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
549
tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
550
tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
551
+
552
+# hw/misc/iotkit-secctl.c
553
+iotkit_secctl_s_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs read: offset 0x%x data 0x%" PRIx64 " size %u"
554
+iotkit_secctl_s_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs write: offset 0x%x data 0x%" PRIx64 " size %u"
555
+iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u"
556
+iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u"
557
+iotkit_secctl_reset(void) "IoTKit SecCtl: reset"
558
--
88
--
559
2.16.2
89
2.20.1
560
90
561
91
diff view generated by jsdifflib
1
The MPS2 AN505 FPGA image includes a "FPGA control block"
1
From: Thomas Huth <thuth@redhat.com>
2
which is a small set of registers handling LEDs, buttons
3
and some counters.
4
2
3
There is a kernel and initrd available on github which we can use
4
for testing this machine.
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20200225172501.29609-3-philmd@redhat.com
12
Message-Id: <20200131170233.14584-1-thuth@redhat.com>
13
[PMD: Renamed test method, moved description from class to method]
14
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-14-peter.maydell@linaro.org
8
---
16
---
9
hw/misc/Makefile.objs | 1 +
17
MAINTAINERS | 1 +
10
include/hw/misc/mps2-fpgaio.h | 43 ++++++++++
18
tests/acceptance/machine_arm_integratorcp.py | 43 ++++++++++++++++++++
11
hw/misc/mps2-fpgaio.c | 176 ++++++++++++++++++++++++++++++++++++++++
19
2 files changed, 44 insertions(+)
12
default-configs/arm-softmmu.mak | 1 +
20
create mode 100644 tests/acceptance/machine_arm_integratorcp.py
13
hw/misc/trace-events | 6 ++
14
5 files changed, 227 insertions(+)
15
create mode 100644 include/hw/misc/mps2-fpgaio.h
16
create mode 100644 hw/misc/mps2-fpgaio.c
17
21
18
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
22
diff --git a/MAINTAINERS b/MAINTAINERS
19
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/Makefile.objs
24
--- a/MAINTAINERS
21
+++ b/hw/misc/Makefile.objs
25
+++ b/MAINTAINERS
22
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
26
@@ -XXX,XX +XXX,XX @@ S: Maintained
23
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
27
F: hw/arm/integratorcp.c
24
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
28
F: hw/misc/arm_integrator_debug.c
25
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
29
F: include/hw/misc/arm_integrator_debug.h
26
+obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
30
+F: tests/acceptance/machine_arm_integratorcp.py
27
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
31
28
32
MCIMX6UL EVK / i.MX6ul
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
33
M: Peter Maydell <peter.maydell@linaro.org>
30
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
34
diff --git a/tests/acceptance/machine_arm_integratorcp.py b/tests/acceptance/machine_arm_integratorcp.py
31
new file mode 100644
35
new file mode 100644
32
index XXXXXXX..XXXXXXX
36
index XXXXXXX..XXXXXXX
33
--- /dev/null
37
--- /dev/null
34
+++ b/include/hw/misc/mps2-fpgaio.h
38
+++ b/tests/acceptance/machine_arm_integratorcp.py
35
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@
36
+/*
40
+# Functional test that boots a Linux kernel and checks the console
37
+ * ARM MPS2 FPGAIO emulation
41
+#
38
+ *
42
+# Copyright (c) 2020 Red Hat, Inc.
39
+ * Copyright (c) 2018 Linaro Limited
43
+#
40
+ * Written by Peter Maydell
44
+# Author:
41
+ *
45
+# Thomas Huth <thuth@redhat.com>
42
+ * This program is free software; you can redistribute it and/or modify
46
+#
43
+ * it under the terms of the GNU General Public License version 2 or
47
+# This work is licensed under the terms of the GNU GPL, version 2 or
44
+ * (at your option) any later version.
48
+# later. See the COPYING file in the top-level directory.
45
+ */
46
+
49
+
47
+/* This is a model of the FPGAIO register block in the AN505
50
+import os
48
+ * FPGA image for the MPS2 dev board; it is documented in the
49
+ * application note:
50
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
51
+ *
52
+ * QEMU interface:
53
+ * + sysbus MMIO region 0: the register bank
54
+ */
55
+
51
+
56
+#ifndef MPS2_FPGAIO_H
52
+from avocado import skipUnless
57
+#define MPS2_FPGAIO_H
53
+from avocado_qemu import Test
54
+from avocado_qemu import wait_for_console_pattern
58
+
55
+
59
+#include "hw/sysbus.h"
56
+class IntegratorMachine(Test):
60
+
57
+
61
+#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
58
+ timeout = 90
62
+#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO)
63
+
59
+
64
+typedef struct {
60
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
65
+ /*< private >*/
61
+ def test_integratorcp_console(self):
66
+ SysBusDevice parent_obj;
62
+ """
63
+ Boots the Linux kernel and checks that the console is operational
64
+ :avocado: tags=arch:arm
65
+ :avocado: tags=machine:integratorcp
66
+ """
67
+ kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/'
68
+ 'arm-test/kernel/zImage.integrator')
69
+ kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468'
70
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
67
+
71
+
68
+ /*< public >*/
72
+ initrd_url = ('https://github.com/zayac/qemu-arm/raw/master/'
69
+ MemoryRegion iomem;
73
+ 'arm-test/kernel/arm_root.img')
74
+ initrd_hash = 'b51e4154285bf784e017a37586428332d8c7bd8b'
75
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
70
+
76
+
71
+ uint32_t led0;
77
+ self.vm.set_console()
72
+ uint32_t prescale;
78
+ self.vm.add_args('-kernel', kernel_path,
73
+ uint32_t misc;
79
+ '-initrd', initrd_path,
74
+
80
+ '-append', 'printk.time=0 console=ttyAMA0')
75
+ uint32_t prescale_clk;
81
+ self.vm.launch()
76
+} MPS2FPGAIO;
82
+ wait_for_console_pattern(self, 'Log in as root')
77
+
78
+#endif
79
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
80
new file mode 100644
81
index XXXXXXX..XXXXXXX
82
--- /dev/null
83
+++ b/hw/misc/mps2-fpgaio.c
84
@@ -XXX,XX +XXX,XX @@
85
+/*
86
+ * ARM MPS2 AN505 FPGAIO emulation
87
+ *
88
+ * Copyright (c) 2018 Linaro Limited
89
+ * Written by Peter Maydell
90
+ *
91
+ * This program is free software; you can redistribute it and/or modify
92
+ * it under the terms of the GNU General Public License version 2 or
93
+ * (at your option) any later version.
94
+ */
95
+
96
+/* This is a model of the "FPGA system control and I/O" block found
97
+ * in the AN505 FPGA image for the MPS2 devboard.
98
+ * It is documented in AN505:
99
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
100
+ */
101
+
102
+#include "qemu/osdep.h"
103
+#include "qemu/log.h"
104
+#include "qapi/error.h"
105
+#include "trace.h"
106
+#include "hw/sysbus.h"
107
+#include "hw/registerfields.h"
108
+#include "hw/misc/mps2-fpgaio.h"
109
+
110
+REG32(LED0, 0)
111
+REG32(BUTTON, 8)
112
+REG32(CLK1HZ, 0x10)
113
+REG32(CLK100HZ, 0x14)
114
+REG32(COUNTER, 0x18)
115
+REG32(PRESCALE, 0x1c)
116
+REG32(PSCNTR, 0x20)
117
+REG32(MISC, 0x4c)
118
+
119
+static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
120
+{
121
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
122
+ uint64_t r;
123
+
124
+ switch (offset) {
125
+ case A_LED0:
126
+ r = s->led0;
127
+ break;
128
+ case A_BUTTON:
129
+ /* User-pressable board buttons. We don't model that, so just return
130
+ * zeroes.
131
+ */
132
+ r = 0;
133
+ break;
134
+ case A_PRESCALE:
135
+ r = s->prescale;
136
+ break;
137
+ case A_MISC:
138
+ r = s->misc;
139
+ break;
140
+ case A_CLK1HZ:
141
+ case A_CLK100HZ:
142
+ case A_COUNTER:
143
+ case A_PSCNTR:
144
+ /* These are all upcounters of various frequencies. */
145
+ qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
146
+ r = 0;
147
+ break;
148
+ default:
149
+ qemu_log_mask(LOG_GUEST_ERROR,
150
+ "MPS2 FPGAIO read: bad offset %x\n", (int) offset);
151
+ r = 0;
152
+ break;
153
+ }
154
+
155
+ trace_mps2_fpgaio_read(offset, r, size);
156
+ return r;
157
+}
158
+
159
+static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
160
+ unsigned size)
161
+{
162
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
163
+
164
+ trace_mps2_fpgaio_write(offset, value, size);
165
+
166
+ switch (offset) {
167
+ case A_LED0:
168
+ /* LED bits [1:0] control board LEDs. We don't currently have
169
+ * a mechanism for displaying this graphically, so use a trace event.
170
+ */
171
+ trace_mps2_fpgaio_leds(value & 0x02 ? '*' : '.',
172
+ value & 0x01 ? '*' : '.');
173
+ s->led0 = value & 0x3;
174
+ break;
175
+ case A_PRESCALE:
176
+ s->prescale = value;
177
+ break;
178
+ case A_MISC:
179
+ /* These are control bits for some of the other devices on the
180
+ * board (SPI, CLCD, etc). We don't implement that yet, so just
181
+ * make the bits read as written.
182
+ */
183
+ qemu_log_mask(LOG_UNIMP,
184
+ "MPS2 FPGAIO: MISC control bits unimplemented\n");
185
+ s->misc = value;
186
+ break;
187
+ default:
188
+ qemu_log_mask(LOG_GUEST_ERROR,
189
+ "MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
190
+ break;
191
+ }
192
+}
193
+
194
+static const MemoryRegionOps mps2_fpgaio_ops = {
195
+ .read = mps2_fpgaio_read,
196
+ .write = mps2_fpgaio_write,
197
+ .endianness = DEVICE_LITTLE_ENDIAN,
198
+};
199
+
200
+static void mps2_fpgaio_reset(DeviceState *dev)
201
+{
202
+ MPS2FPGAIO *s = MPS2_FPGAIO(dev);
203
+
204
+ trace_mps2_fpgaio_reset();
205
+ s->led0 = 0;
206
+ s->prescale = 0;
207
+ s->misc = 0;
208
+}
209
+
210
+static void mps2_fpgaio_init(Object *obj)
211
+{
212
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
213
+ MPS2FPGAIO *s = MPS2_FPGAIO(obj);
214
+
215
+ memory_region_init_io(&s->iomem, obj, &mps2_fpgaio_ops, s,
216
+ "mps2-fpgaio", 0x1000);
217
+ sysbus_init_mmio(sbd, &s->iomem);
218
+}
219
+
220
+static const VMStateDescription mps2_fpgaio_vmstate = {
221
+ .name = "mps2-fpgaio",
222
+ .version_id = 1,
223
+ .minimum_version_id = 1,
224
+ .fields = (VMStateField[]) {
225
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
226
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
227
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
228
+ VMSTATE_END_OF_LIST()
229
+ }
230
+};
231
+
232
+static Property mps2_fpgaio_properties[] = {
233
+ /* Frequency of the prescale counter */
234
+ DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
235
+ DEFINE_PROP_END_OF_LIST(),
236
+};
237
+
238
+static void mps2_fpgaio_class_init(ObjectClass *klass, void *data)
239
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
242
+ dc->vmsd = &mps2_fpgaio_vmstate;
243
+ dc->reset = mps2_fpgaio_reset;
244
+ dc->props = mps2_fpgaio_properties;
245
+}
246
+
247
+static const TypeInfo mps2_fpgaio_info = {
248
+ .name = TYPE_MPS2_FPGAIO,
249
+ .parent = TYPE_SYS_BUS_DEVICE,
250
+ .instance_size = sizeof(MPS2FPGAIO),
251
+ .instance_init = mps2_fpgaio_init,
252
+ .class_init = mps2_fpgaio_class_init,
253
+};
254
+
255
+static void mps2_fpgaio_register_types(void)
256
+{
257
+ type_register_static(&mps2_fpgaio_info);
258
+}
259
+
260
+type_init(mps2_fpgaio_register_types);
261
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
262
index XXXXXXX..XXXXXXX 100644
263
--- a/default-configs/arm-softmmu.mak
264
+++ b/default-configs/arm-softmmu.mak
265
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
266
CONFIG_CMSDK_APB_TIMER=y
267
CONFIG_CMSDK_APB_UART=y
268
269
+CONFIG_MPS2_FPGAIO=y
270
CONFIG_MPS2_SCC=y
271
272
CONFIG_VERSATILE_PCI=y
273
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
274
index XXXXXXX..XXXXXXX 100644
275
--- a/hw/misc/trace-events
276
+++ b/hw/misc/trace-events
277
@@ -XXX,XX +XXX,XX @@ mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2,
278
mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32
279
mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32
280
281
+# hw/misc/mps2_fpgaio.c
282
+mps2_fpgaio_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
283
+mps2_fpgaio_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
284
+mps2_fpgaio_reset(void) "MPS2 FPGAIO: reset"
285
+mps2_fpgaio_leds(char led1, char led0) "MPS2 FPGAIO LEDs: %c%c"
286
+
287
# hw/misc/msf2-sysreg.c
288
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
289
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
290
--
83
--
291
2.16.2
84
2.20.1
292
85
293
86
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Initial commit of the ZynqMP RTC device.
3
As we want to re-use this code, extract it as a new function.
4
Since we are using the PL011 serial console, add a Avocado tag
5
to ease filtering of tests.
4
6
5
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20200225172501.29609-4-philmd@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
12
---
9
hw/timer/Makefile.objs | 1 +
13
tests/acceptance/machine_arm_integratorcp.py | 18 +++++++++++-------
10
include/hw/timer/xlnx-zynqmp-rtc.h | 84 +++++++++++++++
14
1 file changed, 11 insertions(+), 7 deletions(-)
11
hw/timer/xlnx-zynqmp-rtc.c | 214 +++++++++++++++++++++++++++++++++++++
12
3 files changed, 299 insertions(+)
13
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
14
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
15
15
16
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
16
diff --git a/tests/acceptance/machine_arm_integratorcp.py b/tests/acceptance/machine_arm_integratorcp.py
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/Makefile.objs
18
--- a/tests/acceptance/machine_arm_integratorcp.py
19
+++ b/hw/timer/Makefile.objs
19
+++ b/tests/acceptance/machine_arm_integratorcp.py
20
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_epit.o
20
@@ -XXX,XX +XXX,XX @@ class IntegratorMachine(Test):
21
common-obj-$(CONFIG_IMX) += imx_gpt.o
21
22
common-obj-$(CONFIG_LM32) += lm32_timer.o
22
timeout = 90
23
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
23
24
+common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
24
- @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
25
25
- def test_integratorcp_console(self):
26
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
26
- """
27
obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
27
- Boots the Linux kernel and checks that the console is operational
28
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
28
- :avocado: tags=arch:arm
29
new file mode 100644
29
- :avocado: tags=machine:integratorcp
30
index XXXXXXX..XXXXXXX
30
- """
31
--- /dev/null
31
+ def boot_integratorcp(self):
32
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
32
kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/'
33
@@ -XXX,XX +XXX,XX @@
33
'arm-test/kernel/zImage.integrator')
34
+/*
34
kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468'
35
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
35
@@ -XXX,XX +XXX,XX @@ class IntegratorMachine(Test):
36
+ *
36
'-initrd', initrd_path,
37
+ * Copyright (c) 2017 Xilinx Inc.
37
'-append', 'printk.time=0 console=ttyAMA0')
38
+ *
38
self.vm.launch()
39
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
40
+ *
41
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ * of this software and associated documentation files (the "Software"), to deal
43
+ * in the Software without restriction, including without limitation the rights
44
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ * copies of the Software, and to permit persons to whom the Software is
46
+ * furnished to do so, subject to the following conditions:
47
+ *
48
+ * The above copyright notice and this permission notice shall be included in
49
+ * all copies or substantial portions of the Software.
50
+ *
51
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ * THE SOFTWARE.
58
+ */
59
+
39
+
60
+#include "hw/register.h"
40
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
61
+
41
+ def test_integratorcp_console(self):
62
+#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
42
+ """
63
+
43
+ Boots the Linux kernel and checks that the console is operational
64
+#define XLNX_ZYNQMP_RTC(obj) \
44
+ :avocado: tags=arch:arm
65
+ OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
45
+ :avocado: tags=machine:integratorcp
66
+
46
+ :avocado: tags=device:pl011
67
+REG32(SET_TIME_WRITE, 0x0)
47
+ """
68
+REG32(SET_TIME_READ, 0x4)
48
+ self.boot_integratorcp()
69
+REG32(CALIB_WRITE, 0x8)
49
wait_for_console_pattern(self, 'Log in as root')
70
+ FIELD(CALIB_WRITE, FRACTION_EN, 20, 1)
71
+ FIELD(CALIB_WRITE, FRACTION_DATA, 16, 4)
72
+ FIELD(CALIB_WRITE, MAX_TICK, 0, 16)
73
+REG32(CALIB_READ, 0xc)
74
+ FIELD(CALIB_READ, FRACTION_EN, 20, 1)
75
+ FIELD(CALIB_READ, FRACTION_DATA, 16, 4)
76
+ FIELD(CALIB_READ, MAX_TICK, 0, 16)
77
+REG32(CURRENT_TIME, 0x10)
78
+REG32(CURRENT_TICK, 0x14)
79
+ FIELD(CURRENT_TICK, VALUE, 0, 16)
80
+REG32(ALARM, 0x18)
81
+REG32(RTC_INT_STATUS, 0x20)
82
+ FIELD(RTC_INT_STATUS, ALARM, 1, 1)
83
+ FIELD(RTC_INT_STATUS, SECONDS, 0, 1)
84
+REG32(RTC_INT_MASK, 0x24)
85
+ FIELD(RTC_INT_MASK, ALARM, 1, 1)
86
+ FIELD(RTC_INT_MASK, SECONDS, 0, 1)
87
+REG32(RTC_INT_EN, 0x28)
88
+ FIELD(RTC_INT_EN, ALARM, 1, 1)
89
+ FIELD(RTC_INT_EN, SECONDS, 0, 1)
90
+REG32(RTC_INT_DIS, 0x2c)
91
+ FIELD(RTC_INT_DIS, ALARM, 1, 1)
92
+ FIELD(RTC_INT_DIS, SECONDS, 0, 1)
93
+REG32(ADDR_ERROR, 0x30)
94
+ FIELD(ADDR_ERROR, STATUS, 0, 1)
95
+REG32(ADDR_ERROR_INT_MASK, 0x34)
96
+ FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
97
+REG32(ADDR_ERROR_INT_EN, 0x38)
98
+ FIELD(ADDR_ERROR_INT_EN, MASK, 0, 1)
99
+REG32(ADDR_ERROR_INT_DIS, 0x3c)
100
+ FIELD(ADDR_ERROR_INT_DIS, MASK, 0, 1)
101
+REG32(CONTROL, 0x40)
102
+ FIELD(CONTROL, BATTERY_DISABLE, 31, 1)
103
+ FIELD(CONTROL, OSC_CNTRL, 24, 4)
104
+ FIELD(CONTROL, SLVERR_ENABLE, 0, 1)
105
+REG32(SAFETY_CHK, 0x50)
106
+
107
+#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
108
+
109
+typedef struct XlnxZynqMPRTC {
110
+ SysBusDevice parent_obj;
111
+ MemoryRegion iomem;
112
+ qemu_irq irq_rtc_int;
113
+ qemu_irq irq_addr_error_int;
114
+
115
+ uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
116
+ RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
117
+} XlnxZynqMPRTC;
118
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/hw/timer/xlnx-zynqmp-rtc.c
123
@@ -XXX,XX +XXX,XX @@
124
+/*
125
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
126
+ *
127
+ * Copyright (c) 2017 Xilinx Inc.
128
+ *
129
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
130
+ *
131
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
132
+ * of this software and associated documentation files (the "Software"), to deal
133
+ * in the Software without restriction, including without limitation the rights
134
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
135
+ * copies of the Software, and to permit persons to whom the Software is
136
+ * furnished to do so, subject to the following conditions:
137
+ *
138
+ * The above copyright notice and this permission notice shall be included in
139
+ * all copies or substantial portions of the Software.
140
+ *
141
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
142
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
143
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
144
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
145
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
146
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
147
+ * THE SOFTWARE.
148
+ */
149
+
150
+#include "qemu/osdep.h"
151
+#include "hw/sysbus.h"
152
+#include "hw/register.h"
153
+#include "qemu/bitops.h"
154
+#include "qemu/log.h"
155
+#include "hw/timer/xlnx-zynqmp-rtc.h"
156
+
157
+#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
158
+#define XLNX_ZYNQMP_RTC_ERR_DEBUG 0
159
+#endif
160
+
161
+static void rtc_int_update_irq(XlnxZynqMPRTC *s)
162
+{
163
+ bool pending = s->regs[R_RTC_INT_STATUS] & ~s->regs[R_RTC_INT_MASK];
164
+ qemu_set_irq(s->irq_rtc_int, pending);
165
+}
166
+
167
+static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
168
+{
169
+ bool pending = s->regs[R_ADDR_ERROR] & ~s->regs[R_ADDR_ERROR_INT_MASK];
170
+ qemu_set_irq(s->irq_addr_error_int, pending);
171
+}
172
+
173
+static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
174
+{
175
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
176
+ rtc_int_update_irq(s);
177
+}
178
+
179
+static uint64_t rtc_int_en_prew(RegisterInfo *reg, uint64_t val64)
180
+{
181
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
182
+
183
+ s->regs[R_RTC_INT_MASK] &= (uint32_t) ~val64;
184
+ rtc_int_update_irq(s);
185
+ return 0;
186
+}
187
+
188
+static uint64_t rtc_int_dis_prew(RegisterInfo *reg, uint64_t val64)
189
+{
190
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
191
+
192
+ s->regs[R_RTC_INT_MASK] |= (uint32_t) val64;
193
+ rtc_int_update_irq(s);
194
+ return 0;
195
+}
196
+
197
+static void addr_error_postw(RegisterInfo *reg, uint64_t val64)
198
+{
199
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
200
+ addr_error_int_update_irq(s);
201
+}
202
+
203
+static uint64_t addr_error_int_en_prew(RegisterInfo *reg, uint64_t val64)
204
+{
205
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
206
+
207
+ s->regs[R_ADDR_ERROR_INT_MASK] &= (uint32_t) ~val64;
208
+ addr_error_int_update_irq(s);
209
+ return 0;
210
+}
211
+
212
+static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
213
+{
214
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
215
+
216
+ s->regs[R_ADDR_ERROR_INT_MASK] |= (uint32_t) val64;
217
+ addr_error_int_update_irq(s);
218
+ return 0;
219
+}
220
+
221
+static const RegisterAccessInfo rtc_regs_info[] = {
222
+ { .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
223
+ },{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
224
+ .ro = 0xffffffff,
225
+ },{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
226
+ },{ .name = "CALIB_READ", .addr = A_CALIB_READ,
227
+ .ro = 0x1fffff,
228
+ },{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
229
+ .ro = 0xffffffff,
230
+ },{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
231
+ .ro = 0xffff,
232
+ },{ .name = "ALARM", .addr = A_ALARM,
233
+ },{ .name = "RTC_INT_STATUS", .addr = A_RTC_INT_STATUS,
234
+ .w1c = 0x3,
235
+ .post_write = rtc_int_status_postw,
236
+ },{ .name = "RTC_INT_MASK", .addr = A_RTC_INT_MASK,
237
+ .reset = 0x3,
238
+ .ro = 0x3,
239
+ },{ .name = "RTC_INT_EN", .addr = A_RTC_INT_EN,
240
+ .pre_write = rtc_int_en_prew,
241
+ },{ .name = "RTC_INT_DIS", .addr = A_RTC_INT_DIS,
242
+ .pre_write = rtc_int_dis_prew,
243
+ },{ .name = "ADDR_ERROR", .addr = A_ADDR_ERROR,
244
+ .w1c = 0x1,
245
+ .post_write = addr_error_postw,
246
+ },{ .name = "ADDR_ERROR_INT_MASK", .addr = A_ADDR_ERROR_INT_MASK,
247
+ .reset = 0x1,
248
+ .ro = 0x1,
249
+ },{ .name = "ADDR_ERROR_INT_EN", .addr = A_ADDR_ERROR_INT_EN,
250
+ .pre_write = addr_error_int_en_prew,
251
+ },{ .name = "ADDR_ERROR_INT_DIS", .addr = A_ADDR_ERROR_INT_DIS,
252
+ .pre_write = addr_error_int_dis_prew,
253
+ },{ .name = "CONTROL", .addr = A_CONTROL,
254
+ .reset = 0x1000000,
255
+ .rsvd = 0x70fffffe,
256
+ },{ .name = "SAFETY_CHK", .addr = A_SAFETY_CHK,
257
+ }
258
+};
259
+
260
+static void rtc_reset(DeviceState *dev)
261
+{
262
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(dev);
263
+ unsigned int i;
264
+
265
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
266
+ register_reset(&s->regs_info[i]);
267
+ }
268
+
269
+ rtc_int_update_irq(s);
270
+ addr_error_int_update_irq(s);
271
+}
272
+
273
+static const MemoryRegionOps rtc_ops = {
274
+ .read = register_read_memory,
275
+ .write = register_write_memory,
276
+ .endianness = DEVICE_LITTLE_ENDIAN,
277
+ .valid = {
278
+ .min_access_size = 4,
279
+ .max_access_size = 4,
280
+ },
281
+};
282
+
283
+static void rtc_init(Object *obj)
284
+{
285
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
286
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
287
+ RegisterInfoArray *reg_array;
288
+
289
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
290
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
291
+ reg_array =
292
+ register_init_block32(DEVICE(obj), rtc_regs_info,
293
+ ARRAY_SIZE(rtc_regs_info),
294
+ s->regs_info, s->regs,
295
+ &rtc_ops,
296
+ XLNX_ZYNQMP_RTC_ERR_DEBUG,
297
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
298
+ memory_region_add_subregion(&s->iomem,
299
+ 0x0,
300
+ &reg_array->mem);
301
+ sysbus_init_mmio(sbd, &s->iomem);
302
+ sysbus_init_irq(sbd, &s->irq_rtc_int);
303
+ sysbus_init_irq(sbd, &s->irq_addr_error_int);
304
+}
305
+
306
+static const VMStateDescription vmstate_rtc = {
307
+ .name = TYPE_XLNX_ZYNQMP_RTC,
308
+ .version_id = 1,
309
+ .minimum_version_id = 1,
310
+ .fields = (VMStateField[]) {
311
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
312
+ VMSTATE_END_OF_LIST(),
313
+ }
314
+};
315
+
316
+static void rtc_class_init(ObjectClass *klass, void *data)
317
+{
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
319
+
320
+ dc->reset = rtc_reset;
321
+ dc->vmsd = &vmstate_rtc;
322
+}
323
+
324
+static const TypeInfo rtc_info = {
325
+ .name = TYPE_XLNX_ZYNQMP_RTC,
326
+ .parent = TYPE_SYS_BUS_DEVICE,
327
+ .instance_size = sizeof(XlnxZynqMPRTC),
328
+ .class_init = rtc_class_init,
329
+ .instance_init = rtc_init,
330
+};
331
+
332
+static void rtc_register_types(void)
333
+{
334
+ type_register_static(&rtc_info);
335
+}
336
+
337
+type_init(rtc_register_types)
338
--
50
--
339
2.16.2
51
2.20.1
340
52
341
53
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
3
Add a test that verifies the Tux logo is displayed on the framebuffer.
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
We simply follow the OpenCV "Template Matching with Multiple Objects"
6
tutorial, replacing Lionel Messi by Tux:
7
https://docs.opencv.org/4.2.0/d4/dc6/tutorial_py_template_matching.html
8
9
When OpenCV and NumPy are installed, this test can be run using:
10
11
$ AVOCADO_ALLOW_UNTRUSTED_CODE=hmmm \
12
avocado --show=app,framebuffer run -t device:framebuffer \
13
tests/acceptance/machine_arm_integratorcp.py
14
JOB ID : 8c46b0f8269242e87d738247883ea2a470df949e
15
JOB LOG : avocado/job-results/job-2020-01-31T21.38-8c46b0f/job.log
16
(1/1) tests/acceptance/machine_arm_integratorcp.py:IntegratorMachine.test_framebuffer_tux_logo:
17
framebuffer: found Tux at position [x, y] = (0, 0)
18
PASS (3.96 s)
19
RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
20
JOB TIME : 4.23 s
21
22
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
24
Message-id: 20200225172501.29609-5-philmd@redhat.com
25
Message-Id: <20200131211102.29612-3-f4bug@amsat.org>
26
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
28
---
8
include/hw/arm/xlnx-zynqmp.h | 2 ++
29
tests/acceptance/machine_arm_integratorcp.py | 52 ++++++++++++++++++++
9
hw/arm/xlnx-zynqmp.c | 14 ++++++++++++++
30
1 file changed, 52 insertions(+)
10
2 files changed, 16 insertions(+)
11
31
12
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
32
diff --git a/tests/acceptance/machine_arm_integratorcp.py b/tests/acceptance/machine_arm_integratorcp.py
13
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/xlnx-zynqmp.h
34
--- a/tests/acceptance/machine_arm_integratorcp.py
15
+++ b/include/hw/arm/xlnx-zynqmp.h
35
+++ b/tests/acceptance/machine_arm_integratorcp.py
16
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
17
#include "hw/dma/xlnx_dpdma.h"
37
# later. See the COPYING file in the top-level directory.
18
#include "hw/display/xlnx_dp.h"
38
19
#include "hw/intc/xlnx-zynqmp-ipi.h"
39
import os
20
+#include "hw/timer/xlnx-zynqmp-rtc.h"
40
+import logging
21
41
22
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
42
from avocado import skipUnless
23
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
43
from avocado_qemu import Test
24
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState {
44
from avocado_qemu import wait_for_console_pattern
25
XlnxDPState dp;
45
26
XlnxDPDMAState dpdma;
27
XlnxZynqMPIPI ipi;
28
+ XlnxZynqMPRTC rtc;
29
30
char *boot_cpu;
31
ARMCPU *boot_cpu_ptr;
32
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/xlnx-zynqmp.c
35
+++ b/hw/arm/xlnx-zynqmp.c
36
@@ -XXX,XX +XXX,XX @@
37
#define IPI_ADDR 0xFF300000
38
#define IPI_IRQ 64
39
40
+#define RTC_ADDR 0xffa60000
41
+#define RTC_IRQ 26
42
+
46
+
43
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
47
+NUMPY_AVAILABLE = True
44
48
+try:
45
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
49
+ import numpy as np
46
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
50
+except ImportError:
47
51
+ NUMPY_AVAILABLE = False
48
object_initialize(&s->ipi, sizeof(s->ipi), TYPE_XLNX_ZYNQMP_IPI);
49
qdev_set_parent_bus(DEVICE(&s->ipi), sysbus_get_default());
50
+
52
+
51
+ object_initialize(&s->rtc, sizeof(s->rtc), TYPE_XLNX_ZYNQMP_RTC);
53
+CV2_AVAILABLE = True
52
+ qdev_set_parent_bus(DEVICE(&s->rtc), sysbus_get_default());
54
+try:
53
}
55
+ import cv2
54
56
+except ImportError:
55
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
57
+ CV2_AVAILABLE = False
56
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
57
}
58
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi), 0, IPI_ADDR);
59
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi), 0, gic_spi[IPI_IRQ]);
60
+
58
+
61
+ object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
59
+
62
+ if (err) {
60
class IntegratorMachine(Test):
63
+ error_propagate(errp, err);
61
64
+ return;
62
timeout = 90
65
+ }
63
@@ -XXX,XX +XXX,XX @@ class IntegratorMachine(Test):
66
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
64
"""
67
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
65
self.boot_integratorcp()
68
}
66
wait_for_console_pattern(self, 'Log in as root')
69
67
+
70
static Property xlnx_zynqmp_props[] = {
68
+ @skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed')
69
+ @skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed')
70
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
71
+ def test_framebuffer_tux_logo(self):
72
+ """
73
+ Boot Linux and verify the Tux logo is displayed on the framebuffer.
74
+ :avocado: tags=arch:arm
75
+ :avocado: tags=machine:integratorcp
76
+ :avocado: tags=device:pl110
77
+ :avocado: tags=device:framebuffer
78
+ """
79
+ screendump_path = os.path.join(self.workdir, "screendump.pbm")
80
+ tuxlogo_url = ('https://github.com/torvalds/linux/raw/v2.6.12/'
81
+ 'drivers/video/logo/logo_linux_vga16.ppm')
82
+ tuxlogo_hash = '3991c2ddbd1ddaecda7601f8aafbcf5b02dc86af'
83
+ tuxlogo_path = self.fetch_asset(tuxlogo_url, asset_hash=tuxlogo_hash)
84
+
85
+ self.boot_integratorcp()
86
+ framebuffer_ready = 'Console: switching to colour frame buffer device'
87
+ wait_for_console_pattern(self, framebuffer_ready)
88
+ self.vm.command('human-monitor-command', command_line='stop')
89
+ self.vm.command('human-monitor-command',
90
+ command_line='screendump %s' % screendump_path)
91
+ logger = logging.getLogger('framebuffer')
92
+
93
+ cpu_count = 1
94
+ match_threshold = 0.92
95
+ screendump_bgr = cv2.imread(screendump_path)
96
+ screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY)
97
+ result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 0),
98
+ cv2.TM_CCOEFF_NORMED)
99
+ loc = np.where(result >= match_threshold)
100
+ tux_count = 0
101
+ for tux_count, pt in enumerate(zip(*loc[::-1]), start=1):
102
+ logger.debug('found Tux at position [x, y] = %s', pt)
103
+ self.assertGreaterEqual(tux_count, cpu_count)
71
--
104
--
72
2.16.2
105
2.20.1
73
106
74
107
diff view generated by jsdifflib
Deleted patch
1
Add a function load_ramdisk_as() which behaves like the existing
2
load_ramdisk() but allows the caller to specify the AddressSpace
3
to use. This matches the pattern we have already for various
4
other loader functions.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-2-peter.maydell@linaro.org
10
---
11
include/hw/loader.h | 12 +++++++++++-
12
hw/core/loader.c | 8 +++++++-
13
2 files changed, 18 insertions(+), 2 deletions(-)
14
15
diff --git a/include/hw/loader.h b/include/hw/loader.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/loader.h
18
+++ b/include/hw/loader.h
19
@@ -XXX,XX +XXX,XX @@ int load_uimage(const char *filename, hwaddr *ep,
20
void *translate_opaque);
21
22
/**
23
- * load_ramdisk:
24
+ * load_ramdisk_as:
25
* @filename: Path to the ramdisk image
26
* @addr: Memory address to load the ramdisk to
27
* @max_sz: Maximum allowed ramdisk size (for non-u-boot ramdisks)
28
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
29
+ * is used if nothing is supplied here.
30
*
31
* Load a ramdisk image with U-Boot header to the specified memory
32
* address.
33
*
34
* Returns the size of the loaded image on success, -1 otherwise.
35
*/
36
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
37
+ AddressSpace *as);
38
+
39
+/**
40
+ * load_ramdisk:
41
+ * Same as load_ramdisk_as(), but doesn't allow the caller to specify
42
+ * an AddressSpace.
43
+ */
44
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
45
46
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
47
diff --git a/hw/core/loader.c b/hw/core/loader.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/core/loader.c
50
+++ b/hw/core/loader.c
51
@@ -XXX,XX +XXX,XX @@ int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
52
53
/* Load a ramdisk. */
54
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
55
+{
56
+ return load_ramdisk_as(filename, addr, max_sz, NULL);
57
+}
58
+
59
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
60
+ AddressSpace *as)
61
{
62
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
63
- NULL, NULL, NULL);
64
+ NULL, NULL, as);
65
}
66
67
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
68
--
69
2.16.2
70
71
diff view generated by jsdifflib
Deleted patch
1
Instead of loading kernels, device trees, and the like to
2
the system address space, use the CPU's address space. This
3
is important if we're trying to load the file to memory or
4
via an alias memory region that is provided by an SoC
5
object and thus not mapped into the system address space.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-3-peter.maydell@linaro.org
11
---
12
hw/arm/boot.c | 119 +++++++++++++++++++++++++++++++++++++---------------------
13
1 file changed, 76 insertions(+), 43 deletions(-)
14
15
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/boot.c
18
+++ b/hw/arm/boot.c
19
@@ -XXX,XX +XXX,XX @@
20
#define ARM64_TEXT_OFFSET_OFFSET 8
21
#define ARM64_MAGIC_OFFSET 56
22
23
+static AddressSpace *arm_boot_address_space(ARMCPU *cpu,
24
+ const struct arm_boot_info *info)
25
+{
26
+ /* Return the address space to use for bootloader reads and writes.
27
+ * We prefer the secure address space if the CPU has it and we're
28
+ * going to boot the guest into it.
29
+ */
30
+ int asidx;
31
+ CPUState *cs = CPU(cpu);
32
+
33
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3) && info->secure_boot) {
34
+ asidx = ARMASIdx_S;
35
+ } else {
36
+ asidx = ARMASIdx_NS;
37
+ }
38
+
39
+ return cpu_get_address_space(cs, asidx);
40
+}
41
+
42
typedef enum {
43
FIXUP_NONE = 0, /* do nothing */
44
FIXUP_TERMINATOR, /* end of insns */
45
@@ -XXX,XX +XXX,XX @@ static const ARMInsnFixup smpboot[] = {
46
};
47
48
static void write_bootloader(const char *name, hwaddr addr,
49
- const ARMInsnFixup *insns, uint32_t *fixupcontext)
50
+ const ARMInsnFixup *insns, uint32_t *fixupcontext,
51
+ AddressSpace *as)
52
{
53
/* Fix up the specified bootloader fragment and write it into
54
* guest memory using rom_add_blob_fixed(). fixupcontext is
55
@@ -XXX,XX +XXX,XX @@ static void write_bootloader(const char *name, hwaddr addr,
56
code[i] = tswap32(insn);
57
}
58
59
- rom_add_blob_fixed(name, code, len * sizeof(uint32_t), addr);
60
+ rom_add_blob_fixed_as(name, code, len * sizeof(uint32_t), addr, as);
61
62
g_free(code);
63
}
64
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
65
const struct arm_boot_info *info)
66
{
67
uint32_t fixupcontext[FIXUP_MAX];
68
+ AddressSpace *as = arm_boot_address_space(cpu, info);
69
70
fixupcontext[FIXUP_GIC_CPU_IF] = info->gic_cpu_if_addr;
71
fixupcontext[FIXUP_BOOTREG] = info->smp_bootreg_addr;
72
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
73
}
74
75
write_bootloader("smpboot", info->smp_loader_start,
76
- smpboot, fixupcontext);
77
+ smpboot, fixupcontext, as);
78
}
79
80
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
81
const struct arm_boot_info *info,
82
hwaddr mvbar_addr)
83
{
84
+ AddressSpace *as = arm_boot_address_space(cpu, info);
85
int n;
86
uint32_t mvbar_blob[] = {
87
/* mvbar_addr: secure monitor vectors
88
@@ -XXX,XX +XXX,XX @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
89
for (n = 0; n < ARRAY_SIZE(mvbar_blob); n++) {
90
mvbar_blob[n] = tswap32(mvbar_blob[n]);
91
}
92
- rom_add_blob_fixed("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
93
- mvbar_addr);
94
+ rom_add_blob_fixed_as("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
95
+ mvbar_addr, as);
96
97
for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
98
board_setup_blob[n] = tswap32(board_setup_blob[n]);
99
}
100
- rom_add_blob_fixed("board-setup", board_setup_blob,
101
- sizeof(board_setup_blob), info->board_setup_addr);
102
+ rom_add_blob_fixed_as("board-setup", board_setup_blob,
103
+ sizeof(board_setup_blob), info->board_setup_addr, as);
104
}
105
106
static void default_reset_secondary(ARMCPU *cpu,
107
const struct arm_boot_info *info)
108
{
109
+ AddressSpace *as = arm_boot_address_space(cpu, info);
110
CPUState *cs = CPU(cpu);
111
112
- address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
113
+ address_space_stl_notdirty(as, info->smp_bootreg_addr,
114
0, MEMTXATTRS_UNSPECIFIED, NULL);
115
cpu_set_pc(cs, info->smp_loader_start);
116
}
117
@@ -XXX,XX +XXX,XX @@ static inline bool have_dtb(const struct arm_boot_info *info)
118
}
119
120
#define WRITE_WORD(p, value) do { \
121
- address_space_stl_notdirty(&address_space_memory, p, value, \
122
+ address_space_stl_notdirty(as, p, value, \
123
MEMTXATTRS_UNSPECIFIED, NULL); \
124
p += 4; \
125
} while (0)
126
127
-static void set_kernel_args(const struct arm_boot_info *info)
128
+static void set_kernel_args(const struct arm_boot_info *info, AddressSpace *as)
129
{
130
int initrd_size = info->initrd_size;
131
hwaddr base = info->loader_start;
132
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
133
int cmdline_size;
134
135
cmdline_size = strlen(info->kernel_cmdline);
136
- cpu_physical_memory_write(p + 8, info->kernel_cmdline,
137
- cmdline_size + 1);
138
+ address_space_write(as, p + 8, MEMTXATTRS_UNSPECIFIED,
139
+ (const uint8_t *)info->kernel_cmdline,
140
+ cmdline_size + 1);
141
cmdline_size = (cmdline_size >> 2) + 1;
142
WRITE_WORD(p, cmdline_size + 2);
143
WRITE_WORD(p, 0x54410009);
144
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
145
atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
146
WRITE_WORD(p, (atag_board_len + 8) >> 2);
147
WRITE_WORD(p, 0x414f4d50);
148
- cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
149
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
150
+ atag_board_buf, atag_board_len);
151
p += atag_board_len;
152
}
153
/* ATAG_END */
154
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
155
WRITE_WORD(p, 0);
156
}
157
158
-static void set_kernel_args_old(const struct arm_boot_info *info)
159
+static void set_kernel_args_old(const struct arm_boot_info *info,
160
+ AddressSpace *as)
161
{
162
hwaddr p;
163
const char *s;
164
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info)
165
}
166
s = info->kernel_cmdline;
167
if (s) {
168
- cpu_physical_memory_write(p, s, strlen(s) + 1);
169
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
170
+ (const uint8_t *)s, strlen(s) + 1);
171
} else {
172
WRITE_WORD(p, 0);
173
}
174
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
175
* @addr: the address to load the image at
176
* @binfo: struct describing the boot environment
177
* @addr_limit: upper limit of the available memory area at @addr
178
+ * @as: address space to load image to
179
*
180
* Load a device tree supplied by the machine or by the user with the
181
* '-dtb' command line option, and put it at offset @addr in target
182
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
183
* Note: Must not be called unless have_dtb(binfo) is true.
184
*/
185
static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
186
- hwaddr addr_limit)
187
+ hwaddr addr_limit, AddressSpace *as)
188
{
189
void *fdt = NULL;
190
int size, rc;
191
@@ -XXX,XX +XXX,XX @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
192
/* Put the DTB into the memory map as a ROM image: this will ensure
193
* the DTB is copied again upon reset, even if addr points into RAM.
194
*/
195
- rom_add_blob_fixed("dtb", fdt, size, addr);
196
+ rom_add_blob_fixed_as("dtb", fdt, size, addr, as);
197
198
g_free(fdt);
199
200
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
201
}
202
203
if (cs == first_cpu) {
204
+ AddressSpace *as = arm_boot_address_space(cpu, info);
205
+
206
cpu_set_pc(cs, info->loader_start);
207
208
if (!have_dtb(info)) {
209
if (old_param) {
210
- set_kernel_args_old(info);
211
+ set_kernel_args_old(info, as);
212
} else {
213
- set_kernel_args(info);
214
+ set_kernel_args(info, as);
215
}
216
}
217
} else {
218
@@ -XXX,XX +XXX,XX @@ static int do_arm_linux_init(Object *obj, void *opaque)
219
220
static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
221
uint64_t *lowaddr, uint64_t *highaddr,
222
- int elf_machine)
223
+ int elf_machine, AddressSpace *as)
224
{
225
bool elf_is64;
226
union {
227
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
228
}
229
}
230
231
- ret = load_elf(info->kernel_filename, NULL, NULL,
232
- pentry, lowaddr, highaddr, big_endian, elf_machine,
233
- 1, data_swab);
234
+ ret = load_elf_as(info->kernel_filename, NULL, NULL,
235
+ pentry, lowaddr, highaddr, big_endian, elf_machine,
236
+ 1, data_swab, as);
237
if (ret <= 0) {
238
/* The header loaded but the image didn't */
239
exit(1);
240
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
241
}
242
243
static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
244
- hwaddr *entry)
245
+ hwaddr *entry, AddressSpace *as)
246
{
247
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
248
uint8_t *buffer;
249
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
250
}
251
252
*entry = mem_base + kernel_load_offset;
253
- rom_add_blob_fixed(filename, buffer, size, *entry);
254
+ rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
255
256
g_free(buffer);
257
258
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
259
ARMCPU *cpu = n->cpu;
260
struct arm_boot_info *info =
261
container_of(n, struct arm_boot_info, load_kernel_notifier);
262
+ AddressSpace *as = arm_boot_address_space(cpu, info);
263
264
/* The board code is not supposed to set secure_board_setup unless
265
* running its code in secure mode is actually possible, and KVM
266
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
267
* the kernel is supposed to be loaded by the bootloader), copy the
268
* DTB to the base of RAM for the bootloader to pick up.
269
*/
270
- if (load_dtb(info->loader_start, info, 0) < 0) {
271
+ if (load_dtb(info->loader_start, info, 0, as) < 0) {
272
exit(1);
273
}
274
}
275
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
276
277
/* Assume that raw images are linux kernels, and ELF images are not. */
278
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
279
- &elf_high_addr, elf_machine);
280
+ &elf_high_addr, elf_machine, as);
281
if (kernel_size > 0 && have_dtb(info)) {
282
/* If there is still some room left at the base of RAM, try and put
283
* the DTB there like we do for images loaded with -bios or -pflash.
284
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
285
if (elf_low_addr < info->loader_start) {
286
elf_low_addr = 0;
287
}
288
- if (load_dtb(info->loader_start, info, elf_low_addr) < 0) {
289
+ if (load_dtb(info->loader_start, info, elf_low_addr, as) < 0) {
290
exit(1);
291
}
292
}
293
}
294
entry = elf_entry;
295
if (kernel_size < 0) {
296
- kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
297
- &is_linux, NULL, NULL);
298
+ kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL,
299
+ &is_linux, NULL, NULL, as);
300
}
301
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
302
kernel_size = load_aarch64_image(info->kernel_filename,
303
- info->loader_start, &entry);
304
+ info->loader_start, &entry, as);
305
is_linux = 1;
306
} else if (kernel_size < 0) {
307
/* 32-bit ARM */
308
entry = info->loader_start + KERNEL_LOAD_ADDR;
309
- kernel_size = load_image_targphys(info->kernel_filename, entry,
310
- info->ram_size - KERNEL_LOAD_ADDR);
311
+ kernel_size = load_image_targphys_as(info->kernel_filename, entry,
312
+ info->ram_size - KERNEL_LOAD_ADDR,
313
+ as);
314
is_linux = 1;
315
}
316
if (kernel_size < 0) {
317
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
318
uint32_t fixupcontext[FIXUP_MAX];
319
320
if (info->initrd_filename) {
321
- initrd_size = load_ramdisk(info->initrd_filename,
322
- info->initrd_start,
323
- info->ram_size -
324
- info->initrd_start);
325
+ initrd_size = load_ramdisk_as(info->initrd_filename,
326
+ info->initrd_start,
327
+ info->ram_size - info->initrd_start,
328
+ as);
329
if (initrd_size < 0) {
330
- initrd_size = load_image_targphys(info->initrd_filename,
331
- info->initrd_start,
332
- info->ram_size -
333
- info->initrd_start);
334
+ initrd_size = load_image_targphys_as(info->initrd_filename,
335
+ info->initrd_start,
336
+ info->ram_size -
337
+ info->initrd_start,
338
+ as);
339
}
340
if (initrd_size < 0) {
341
error_report("could not load initrd '%s'",
342
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
343
344
/* Place the DTB after the initrd in memory with alignment. */
345
dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size, align);
346
- if (load_dtb(dtb_start, info, 0) < 0) {
347
+ if (load_dtb(dtb_start, info, 0, as) < 0) {
348
exit(1);
349
}
350
fixupcontext[FIXUP_ARGPTR] = dtb_start;
351
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
352
fixupcontext[FIXUP_ENTRYPOINT] = entry;
353
354
write_bootloader("bootloader", info->loader_start,
355
- primary_loader, fixupcontext);
356
+ primary_loader, fixupcontext, as);
357
358
if (info->nb_cpus > 1) {
359
info->write_secondary_boot(cpu, info);
360
--
361
2.16.2
362
363
diff view generated by jsdifflib
Deleted patch
1
Instead of loading guest images to the system address space, use the
2
CPU's address space. This is important if we're trying to load the
3
file to memory or via an alias memory region that is provided by an
4
SoC object and thus not mapped into the system address space.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-4-peter.maydell@linaro.org
10
---
11
hw/arm/armv7m.c | 17 ++++++++++++++---
12
1 file changed, 14 insertions(+), 3 deletions(-)
13
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armv7m.c
17
+++ b/hw/arm/armv7m.c
18
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
19
uint64_t entry;
20
uint64_t lowaddr;
21
int big_endian;
22
+ AddressSpace *as;
23
+ int asidx;
24
+ CPUState *cs = CPU(cpu);
25
26
#ifdef TARGET_WORDS_BIGENDIAN
27
big_endian = 1;
28
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
29
exit(1);
30
}
31
32
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
33
+ asidx = ARMASIdx_S;
34
+ } else {
35
+ asidx = ARMASIdx_NS;
36
+ }
37
+ as = cpu_get_address_space(cs, asidx);
38
+
39
if (kernel_filename) {
40
- image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
41
- NULL, big_endian, EM_ARM, 1, 0);
42
+ image_size = load_elf_as(kernel_filename, NULL, NULL, &entry, &lowaddr,
43
+ NULL, big_endian, EM_ARM, 1, 0, as);
44
if (image_size < 0) {
45
- image_size = load_image_targphys(kernel_filename, 0, mem_size);
46
+ image_size = load_image_targphys_as(kernel_filename, 0,
47
+ mem_size, as);
48
lowaddr = 0;
49
}
50
if (image_size < 0) {
51
--
52
2.16.2
53
54
diff view generated by jsdifflib
1
The Cortex-M33 allows the system to specify the reset value of the
1
We missed an instance of using FIELD_EX32 on a 64-bit ID
2
secure Vector Table Offset Register (VTOR) by asserting config
2
register, in isar_feature_aa64_pmu_8_4(). Fix it.
3
signals. In particular, guest images for the MPS2 AN505 board rely
4
on the MPS2's initial VTOR being correct for that board.
5
Implement a QEMU property so board and SoC code can set the reset
6
value to the correct value.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-7-peter.maydell@linaro.org
7
Message-id: 20200224172846.13053-2-peter.maydell@linaro.org
11
---
8
---
12
target/arm/cpu.h | 3 +++
9
target/arm/cpu.h | 4 ++--
13
target/arm/cpu.c | 18 ++++++++++++++----
10
1 file changed, 2 insertions(+), 2 deletions(-)
14
2 files changed, 17 insertions(+), 4 deletions(-)
15
11
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
14
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
15
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
16
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id)
21
*/
17
22
uint32_t psci_conduit;
18
static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id)
23
24
+ /* For v8M, initial value of the Secure VTOR */
25
+ uint32_t init_svtor;
26
+
27
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
28
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
29
*/
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
35
uint32_t initial_msp; /* Loaded from 0x0 */
36
uint32_t initial_pc; /* Loaded from 0x4 */
37
uint8_t *rom;
38
+ uint32_t vecbase;
39
40
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
41
env->v7m.secure = true;
42
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
43
/* Unlike A/R profile, M profile defines the reset LR value */
44
env->regs[14] = 0xffffffff;
45
46
- /* Load the initial SP and PC from the vector table at address 0 */
47
- rom = rom_ptr(0);
48
+ env->v7m.vecbase[M_REG_S] = cpu->init_svtor & 0xffffff80;
49
+
50
+ /* Load the initial SP and PC from offset 0 and 4 in the vector table */
51
+ vecbase = env->v7m.vecbase[env->v7m.secure];
52
+ rom = rom_ptr(vecbase);
53
if (rom) {
54
/* Address zero is covered by ROM which hasn't yet been
55
* copied into physical memory.
56
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
57
* it got copied into memory. In the latter case, rom_ptr
58
* will return a NULL pointer and we should use ldl_phys instead.
59
*/
60
- initial_msp = ldl_phys(s->as, 0);
61
- initial_pc = ldl_phys(s->as, 4);
62
+ initial_msp = ldl_phys(s->as, vecbase);
63
+ initial_pc = ldl_phys(s->as, vecbase + 4);
64
}
65
66
env->regs[13] = initial_msp & 0xFFFFFFFC;
67
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_pmsav7_dregion_property =
68
pmsav7_dregion,
69
qdev_prop_uint32, uint32_t);
70
71
+/* M profile: initial value of the Secure VTOR */
72
+static Property arm_cpu_initsvtor_property =
73
+ DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
74
+
75
static void arm_cpu_post_init(Object *obj)
76
{
19
{
77
ARMCPU *cpu = ARM_CPU(obj);
20
- return FIELD_EX32(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 &&
78
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
21
- FIELD_EX32(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
79
qdev_prop_allow_set_link_before_realize,
22
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 &&
80
OBJ_PROP_LINK_UNREF_ON_RELEASE,
23
+ FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
81
&error_abort);
24
}
82
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
25
83
+ &error_abort);
26
/*
84
}
85
86
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
87
--
27
--
88
2.16.2
28
2.20.1
89
29
90
30
diff view generated by jsdifflib
Deleted patch
1
Add a Cortex-M33 definition. The M33 is an M profile CPU
2
which implements the ARM v8M architecture, including the
3
M profile Security Extension.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-9-peter.maydell@linaro.org
8
---
9
target/arm/cpu.c | 31 +++++++++++++++++++++++++++++++
10
1 file changed, 31 insertions(+)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
17
cpu->id_isar5 = 0x00000000;
18
}
19
20
+static void cortex_m33_initfn(Object *obj)
21
+{
22
+ ARMCPU *cpu = ARM_CPU(obj);
23
+
24
+ set_feature(&cpu->env, ARM_FEATURE_V8);
25
+ set_feature(&cpu->env, ARM_FEATURE_M);
26
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
27
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
28
+ cpu->midr = 0x410fd213; /* r0p3 */
29
+ cpu->pmsav7_dregion = 16;
30
+ cpu->sau_sregion = 8;
31
+ cpu->id_pfr0 = 0x00000030;
32
+ cpu->id_pfr1 = 0x00000210;
33
+ cpu->id_dfr0 = 0x00200000;
34
+ cpu->id_afr0 = 0x00000000;
35
+ cpu->id_mmfr0 = 0x00101F40;
36
+ cpu->id_mmfr1 = 0x00000000;
37
+ cpu->id_mmfr2 = 0x01000000;
38
+ cpu->id_mmfr3 = 0x00000000;
39
+ cpu->id_isar0 = 0x01101110;
40
+ cpu->id_isar1 = 0x02212000;
41
+ cpu->id_isar2 = 0x20232232;
42
+ cpu->id_isar3 = 0x01111131;
43
+ cpu->id_isar4 = 0x01310132;
44
+ cpu->id_isar5 = 0x00000000;
45
+ cpu->clidr = 0x00000000;
46
+ cpu->ctr = 0x8000c000;
47
+}
48
+
49
static void arm_v7m_class_init(ObjectClass *oc, void *data)
50
{
51
CPUClass *cc = CPU_CLASS(oc);
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
53
.class_init = arm_v7m_class_init },
54
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
55
.class_init = arm_v7m_class_init },
56
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
57
+ .class_init = arm_v7m_class_init },
58
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
59
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
60
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
61
--
62
2.16.2
63
64
diff view generated by jsdifflib
Deleted patch
1
Move the definition of the struct for the unimplemented-device
2
from unimp.c to unimp.h, so that users can embed the struct
3
in their own device structs if they prefer.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-10-peter.maydell@linaro.org
9
---
10
include/hw/misc/unimp.h | 10 ++++++++++
11
hw/misc/unimp.c | 10 ----------
12
2 files changed, 10 insertions(+), 10 deletions(-)
13
14
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/unimp.h
17
+++ b/include/hw/misc/unimp.h
18
@@ -XXX,XX +XXX,XX @@
19
20
#define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
21
22
+#define UNIMPLEMENTED_DEVICE(obj) \
23
+ OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
24
+
25
+typedef struct {
26
+ SysBusDevice parent_obj;
27
+ MemoryRegion iomem;
28
+ char *name;
29
+ uint64_t size;
30
+} UnimplementedDeviceState;
31
+
32
/**
33
* create_unimplemented_device: create and map a dummy device
34
* @name: name of the device for debug logging
35
diff --git a/hw/misc/unimp.c b/hw/misc/unimp.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/unimp.c
38
+++ b/hw/misc/unimp.c
39
@@ -XXX,XX +XXX,XX @@
40
#include "qemu/log.h"
41
#include "qapi/error.h"
42
43
-#define UNIMPLEMENTED_DEVICE(obj) \
44
- OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
45
-
46
-typedef struct {
47
- SysBusDevice parent_obj;
48
- MemoryRegion iomem;
49
- char *name;
50
- uint64_t size;
51
-} UnimplementedDeviceState;
52
-
53
static uint64_t unimp_read(void *opaque, hwaddr offset, unsigned size)
54
{
55
UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque);
56
--
57
2.16.2
58
59
diff view generated by jsdifflib
Deleted patch
1
The function qdev_init_gpio_in_named() passes the DeviceState pointer
2
as the opaque data pointor for the irq handler function. Usually
3
this is what you want, but in some cases it would be helpful to use
4
some other data pointer.
5
1
6
Add a new function qdev_init_gpio_in_named_with_opaque() which allows
7
the caller to specify the data pointer they want.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180220180325.29818-12-peter.maydell@linaro.org
13
---
14
include/hw/qdev-core.h | 30 ++++++++++++++++++++++++++++--
15
hw/core/qdev.c | 8 +++++---
16
2 files changed, 33 insertions(+), 5 deletions(-)
17
18
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/qdev-core.h
21
+++ b/include/hw/qdev-core.h
22
@@ -XXX,XX +XXX,XX @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
23
/* GPIO inputs also double as IRQ sinks. */
24
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
25
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
26
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
27
- const char *name, int n);
28
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
29
const char *name, int n);
30
+/**
31
+ * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines
32
+ * for the specified device
33
+ *
34
+ * @dev: Device to create input GPIOs for
35
+ * @handler: Function to call when GPIO line value is set
36
+ * @opaque: Opaque data pointer to pass to @handler
37
+ * @name: Name of the GPIO input (must be unique for this device)
38
+ * @n: Number of GPIO lines in this input set
39
+ */
40
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
41
+ qemu_irq_handler handler,
42
+ void *opaque,
43
+ const char *name, int n);
44
+
45
+/**
46
+ * qdev_init_gpio_in_named: create an array of input GPIO lines
47
+ * for the specified device
48
+ *
49
+ * Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer
50
+ * passed to the handler is @dev (which is the most commonly desired behaviour).
51
+ */
52
+static inline void qdev_init_gpio_in_named(DeviceState *dev,
53
+ qemu_irq_handler handler,
54
+ const char *name, int n)
55
+{
56
+ qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n);
57
+}
58
59
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
60
const char *name);
61
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/core/qdev.c
64
+++ b/hw/core/qdev.c
65
@@ -XXX,XX +XXX,XX @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
66
return ngl;
67
}
68
69
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
70
- const char *name, int n)
71
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
72
+ qemu_irq_handler handler,
73
+ void *opaque,
74
+ const char *name, int n)
75
{
76
int i;
77
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
78
79
assert(gpio_list->num_out == 0 || !name);
80
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
81
- dev, n);
82
+ opaque, n);
83
84
if (!name) {
85
name = "unnamed-gpio-in";
86
--
87
2.16.2
88
89
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The v8.3-RCPC extension implements three new load instructions
2
which provide slightly weaker consistency guarantees than the
3
existing load-acquire operations. For QEMU we choose to simply
4
implement them with a full LDAQ barrier.
2
5
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-7-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200224172846.13053-3-peter.maydell@linaro.org
7
---
9
---
8
target/arm/translate-a64.c | 29 +++++++++++++++++++++++++++++
10
target/arm/cpu.h | 5 +++++
9
1 file changed, 29 insertions(+)
11
linux-user/elfload.c | 1 +
12
target/arm/cpu64.c | 1 +
13
target/arm/translate-a64.c | 24 ++++++++++++++++++++++++
14
4 files changed, 31 insertions(+)
10
15
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id)
21
FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
22
}
23
24
+static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id)
25
+{
26
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0;
27
+}
28
+
29
/*
30
* Feature tests for "does this exist in either 32-bit or 64-bit?"
31
*/
32
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/linux-user/elfload.c
35
+++ b/linux-user/elfload.c
36
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
37
GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
38
GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
39
GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
40
+ GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
41
42
return hwcaps;
43
}
44
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/cpu64.c
47
+++ b/target/arm/cpu64.c
48
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
49
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
50
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
51
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
52
+ t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 1); /* ARMv8.3-RCPC */
53
cpu->isar.id_aa64isar1 = t;
54
55
t = cpu->isar.id_aa64pfr0;
11
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
56
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
12
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-a64.c
58
--- a/target/arm/translate-a64.c
14
+++ b/target/arm/translate-a64.c
59
+++ b/target/arm/translate-a64.c
15
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
60
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
16
case 0x19: /* FMULX */
61
int rs = extract32(insn, 16, 5);
17
is_fp = true;
62
int rn = extract32(insn, 5, 5);
63
int o3_opc = extract32(insn, 12, 4);
64
+ bool r = extract32(insn, 22, 1);
65
+ bool a = extract32(insn, 23, 1);
66
TCGv_i64 tcg_rs, clean_addr;
67
AtomicThreeOpFn *fn;
68
69
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
70
case 010: /* SWP */
71
fn = tcg_gen_atomic_xchg_i64;
18
break;
72
break;
19
+ case 0x1d: /* SQRDMLAH */
73
+ case 014: /* LDAPR, LDAPRH, LDAPRB */
20
+ case 0x1f: /* SQRDMLSH */
74
+ if (!dc_isar_feature(aa64_rcpc_8_3, s) ||
21
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
75
+ rs != 31 || a != 1 || r != 0) {
22
+ unallocated_encoding(s);
76
+ unallocated_encoding(s);
23
+ return;
77
+ return;
24
+ }
78
+ }
25
+ break;
79
+ break;
26
default:
80
default:
27
unallocated_encoding(s);
81
unallocated_encoding(s);
28
return;
82
return;
29
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
83
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
30
tcg_op, tcg_idx);
84
gen_check_sp_alignment(s);
31
}
85
}
32
break;
86
clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
33
+ case 0x1d: /* SQRDMLAH */
87
+
34
+ read_vec_element_i32(s, tcg_res, rd, pass,
88
+ if (o3_opc == 014) {
35
+ is_scalar ? size : MO_32);
89
+ /*
36
+ if (size == 1) {
90
+ * LDAPR* are a special case because they are a simple load, not a
37
+ gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
91
+ * fetch-and-do-something op.
38
+ tcg_op, tcg_idx, tcg_res);
92
+ * The architectural consistency requirements here are weaker than
39
+ } else {
93
+ * full load-acquire (we only need "load-acquire processor consistent"),
40
+ gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
94
+ * but we choose to implement them as full LDAQ.
41
+ tcg_op, tcg_idx, tcg_res);
95
+ */
42
+ }
96
+ do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false,
43
+ break;
97
+ true, rt, disas_ldst_compute_iss_sf(size, false, 0), true);
44
+ case 0x1f: /* SQRDMLSH */
98
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
45
+ read_vec_element_i32(s, tcg_res, rd, pass,
99
+ return;
46
+ is_scalar ? size : MO_32);
100
+ }
47
+ if (size == 1) {
101
+
48
+ gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
102
tcg_rs = read_cpu_reg(s, rs, true);
49
+ tcg_op, tcg_idx, tcg_res);
103
50
+ } else {
104
if (o3_opc == 1) { /* LDCLR */
51
+ gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
52
+ tcg_op, tcg_idx, tcg_res);
53
+ }
54
+ break;
55
default:
56
g_assert_not_reached();
57
}
58
--
105
--
59
2.16.2
106
2.20.1
60
107
61
108
diff view generated by jsdifflib
1
Add a model of the TrustZone peripheral protection controller (PPC),
1
The v8.4-RCPC extension implements some new instructions:
2
which is used to gate transactions to non-TZ-aware peripherals so
2
* LDAPUR, LDAPURB, LDAPURH, LDAPRSB, LDAPRSH, LDAPRSW
3
that secure software can configure them to not be accessible to
3
* STLUR, STLURB, STLURH
4
non-secure software.
4
5
These are all in a new subgroup of encodings that sits below the
6
top-level "Loads and Stores" group in the Arm ARM.
7
8
The STLUR* instructions have standard store-release semantics; the
9
LDAPUR* have Load-AcquirePC semantics, but (as with LDAPR*) we choose
10
to implement them as the slightly stronger Load-Acquire.
5
11
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-15-peter.maydell@linaro.org
14
Message-id: 20200224172846.13053-4-peter.maydell@linaro.org
9
---
15
---
10
hw/misc/Makefile.objs | 2 +
16
target/arm/cpu.h | 5 +++
11
include/hw/misc/tz-ppc.h | 101 ++++++++++++++
17
linux-user/elfload.c | 1 +
12
hw/misc/tz-ppc.c | 302 ++++++++++++++++++++++++++++++++++++++++
18
target/arm/cpu64.c | 2 +-
13
default-configs/arm-softmmu.mak | 2 +
19
target/arm/translate-a64.c | 90 ++++++++++++++++++++++++++++++++++++++
14
hw/misc/trace-events | 11 ++
20
4 files changed, 97 insertions(+), 1 deletion(-)
15
5 files changed, 418 insertions(+)
16
create mode 100644 include/hw/misc/tz-ppc.h
17
create mode 100644 hw/misc/tz-ppc.c
18
21
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
24
--- a/target/arm/cpu.h
22
+++ b/hw/misc/Makefile.objs
25
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
26
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id)
24
obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
27
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0;
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
28
}
26
29
27
+obj-$(CONFIG_TZ_PPC) += tz-ppc.o
30
+static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
28
+
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
30
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
31
obj-$(CONFIG_AUX) += auxbus.o
32
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/tz-ppc.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * ARM TrustZone peripheral protection controller emulation
40
+ *
41
+ * Copyright (c) 2018 Linaro Limited
42
+ * Written by Peter Maydell
43
+ *
44
+ * This program is free software; you can redistribute it and/or modify
45
+ * it under the terms of the GNU General Public License version 2 or
46
+ * (at your option) any later version.
47
+ */
48
+
49
+/* This is a model of the TrustZone peripheral protection controller (PPC).
50
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
51
+ * (DDI 0571G):
52
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
53
+ *
54
+ * The PPC sits in front of peripherals and allows secure software to
55
+ * configure it to either pass through or reject transactions.
56
+ * Rejected transactions may be configured to either be aborted, or to
57
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
58
+ *
59
+ * The PPC has no register interface -- it is configured purely by a
60
+ * collection of input signals from other hardware in the system. Typically
61
+ * they are either hardwired or exposed in an ad-hoc register interface by
62
+ * the SoC that uses the PPC.
63
+ *
64
+ * This QEMU model can be used to model either the AHB5 or APB4 TZ PPC,
65
+ * since the only difference between them is that the AHB version has a
66
+ * "default" port which has no security checks applied. In QEMU the default
67
+ * port can be emulated simply by wiring its downstream devices directly
68
+ * into the parent address space, since the PPC does not need to intercept
69
+ * transactions there.
70
+ *
71
+ * In the hardware, selection of which downstream port to use is done by
72
+ * the user's decode logic asserting one of the hsel[] signals. In QEMU,
73
+ * we provide 16 MMIO regions, one per port, and the user maps these into
74
+ * the desired addresses to implement the address decode.
75
+ *
76
+ * QEMU interface:
77
+ * + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
78
+ * of each of the 16 ports of the PPC
79
+ * + Property "port[0..15]": MemoryRegion defining the downstream device(s)
80
+ * for each of the 16 ports of the PPC
81
+ * + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
82
+ * accessible to NonSecure transactions
83
+ * + Named GPIO inputs "cfg_ap[0..15]": set to 1 if the port should be
84
+ * accessible to non-privileged transactions
85
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
86
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
87
+ * + Named GPIO input "irq_enable": set to 1 to enable interrupts
88
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
89
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
90
+ * + Property "NONSEC_MASK": if a bit is set in this mask then accesses to
91
+ * the associated port do not have the TZ security check performed. (This
92
+ * corresponds to the hardware allowing this to be set as a Verilog
93
+ * parameter.)
94
+ */
95
+
96
+#ifndef TZ_PPC_H
97
+#define TZ_PPC_H
98
+
99
+#include "hw/sysbus.h"
100
+
101
+#define TYPE_TZ_PPC "tz-ppc"
102
+#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC)
103
+
104
+#define TZ_NUM_PORTS 16
105
+
106
+typedef struct TZPPC TZPPC;
107
+
108
+typedef struct TZPPCPort {
109
+ TZPPC *ppc;
110
+ MemoryRegion upstream;
111
+ AddressSpace downstream_as;
112
+ MemoryRegion *downstream;
113
+} TZPPCPort;
114
+
115
+struct TZPPC {
116
+ /*< private >*/
117
+ SysBusDevice parent_obj;
118
+
119
+ /*< public >*/
120
+
121
+ /* State: these just track the values of our input signals */
122
+ bool cfg_nonsec[TZ_NUM_PORTS];
123
+ bool cfg_ap[TZ_NUM_PORTS];
124
+ bool cfg_sec_resp;
125
+ bool irq_enable;
126
+ bool irq_clear;
127
+ /* State: are we asserting irq ? */
128
+ bool irq_status;
129
+
130
+ qemu_irq irq;
131
+
132
+ /* Properties */
133
+ uint32_t nonsec_mask;
134
+
135
+ TZPPCPort port[TZ_NUM_PORTS];
136
+};
137
+
138
+#endif
139
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
140
new file mode 100644
141
index XXXXXXX..XXXXXXX
142
--- /dev/null
143
+++ b/hw/misc/tz-ppc.c
144
@@ -XXX,XX +XXX,XX @@
145
+/*
146
+ * ARM TrustZone peripheral protection controller emulation
147
+ *
148
+ * Copyright (c) 2018 Linaro Limited
149
+ * Written by Peter Maydell
150
+ *
151
+ * This program is free software; you can redistribute it and/or modify
152
+ * it under the terms of the GNU General Public License version 2 or
153
+ * (at your option) any later version.
154
+ */
155
+
156
+#include "qemu/osdep.h"
157
+#include "qemu/log.h"
158
+#include "qapi/error.h"
159
+#include "trace.h"
160
+#include "hw/sysbus.h"
161
+#include "hw/registerfields.h"
162
+#include "hw/misc/tz-ppc.h"
163
+
164
+static void tz_ppc_update_irq(TZPPC *s)
165
+{
31
+{
166
+ bool level = s->irq_status && s->irq_enable;
32
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2;
167
+
168
+ trace_tz_ppc_update_irq(level);
169
+ qemu_set_irq(s->irq, level);
170
+}
33
+}
171
+
34
+
172
+static void tz_ppc_cfg_nonsec(void *opaque, int n, int level)
35
/*
36
* Feature tests for "does this exist in either 32-bit or 64-bit?"
37
*/
38
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/linux-user/elfload.c
41
+++ b/linux-user/elfload.c
42
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
43
GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
44
GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
45
GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
46
+ GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC);
47
48
return hwcaps;
49
}
50
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/cpu64.c
53
+++ b/target/arm/cpu64.c
54
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
55
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
56
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
57
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
58
- t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 1); /* ARMv8.3-RCPC */
59
+ t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */
60
cpu->isar.id_aa64isar1 = t;
61
62
t = cpu->isar.id_aa64pfr0;
63
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-a64.c
66
+++ b/target/arm/translate-a64.c
67
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
68
}
69
}
70
71
+/*
72
+ * LDAPR/STLR (unscaled immediate)
73
+ *
74
+ * 31 30 24 22 21 12 10 5 0
75
+ * +------+-------------+-----+---+--------+-----+----+-----+
76
+ * | size | 0 1 1 0 0 1 | opc | 0 | imm9 | 0 0 | Rn | Rt |
77
+ * +------+-------------+-----+---+--------+-----+----+-----+
78
+ *
79
+ * Rt: source or destination register
80
+ * Rn: base register
81
+ * imm9: unscaled immediate offset
82
+ * opc: 00: STLUR*, 01/10/11: various LDAPUR*
83
+ * size: size of load/store
84
+ */
85
+static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
173
+{
86
+{
174
+ TZPPC *s = TZ_PPC(opaque);
87
+ int rt = extract32(insn, 0, 5);
88
+ int rn = extract32(insn, 5, 5);
89
+ int offset = sextract32(insn, 12, 9);
90
+ int opc = extract32(insn, 22, 2);
91
+ int size = extract32(insn, 30, 2);
92
+ TCGv_i64 clean_addr, dirty_addr;
93
+ bool is_store = false;
94
+ bool is_signed = false;
95
+ bool extend = false;
96
+ bool iss_sf;
175
+
97
+
176
+ assert(n < TZ_NUM_PORTS);
98
+ if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
177
+ trace_tz_ppc_cfg_nonsec(n, level);
99
+ unallocated_encoding(s);
178
+ s->cfg_nonsec[n] = level;
100
+ return;
179
+}
180
+
181
+static void tz_ppc_cfg_ap(void *opaque, int n, int level)
182
+{
183
+ TZPPC *s = TZ_PPC(opaque);
184
+
185
+ assert(n < TZ_NUM_PORTS);
186
+ trace_tz_ppc_cfg_ap(n, level);
187
+ s->cfg_ap[n] = level;
188
+}
189
+
190
+static void tz_ppc_cfg_sec_resp(void *opaque, int n, int level)
191
+{
192
+ TZPPC *s = TZ_PPC(opaque);
193
+
194
+ trace_tz_ppc_cfg_sec_resp(level);
195
+ s->cfg_sec_resp = level;
196
+}
197
+
198
+static void tz_ppc_irq_enable(void *opaque, int n, int level)
199
+{
200
+ TZPPC *s = TZ_PPC(opaque);
201
+
202
+ trace_tz_ppc_irq_enable(level);
203
+ s->irq_enable = level;
204
+ tz_ppc_update_irq(s);
205
+}
206
+
207
+static void tz_ppc_irq_clear(void *opaque, int n, int level)
208
+{
209
+ TZPPC *s = TZ_PPC(opaque);
210
+
211
+ trace_tz_ppc_irq_clear(level);
212
+
213
+ s->irq_clear = level;
214
+ if (level) {
215
+ s->irq_status = false;
216
+ tz_ppc_update_irq(s);
217
+ }
218
+}
219
+
220
+static bool tz_ppc_check(TZPPC *s, int n, MemTxAttrs attrs)
221
+{
222
+ /* Check whether to allow an access to port n; return true if
223
+ * the check passes, and false if the transaction must be blocked.
224
+ * If the latter, the caller must check cfg_sec_resp to determine
225
+ * whether to abort or RAZ/WI the transaction.
226
+ * The checks are:
227
+ * + nonsec_mask suppresses any check of the secure attribute
228
+ * + otherwise, block if cfg_nonsec is 1 and transaction is secure,
229
+ * or if cfg_nonsec is 0 and transaction is non-secure
230
+ * + block if transaction is usermode and cfg_ap is 0
231
+ */
232
+ if ((attrs.secure == s->cfg_nonsec[n] && !(s->nonsec_mask & (1 << n))) ||
233
+ (attrs.user && !s->cfg_ap[n])) {
234
+ /* Block the transaction. */
235
+ if (!s->irq_clear) {
236
+ /* Note that holding irq_clear high suppresses interrupts */
237
+ s->irq_status = true;
238
+ tz_ppc_update_irq(s);
239
+ }
240
+ return false;
241
+ }
242
+ return true;
243
+}
244
+
245
+static MemTxResult tz_ppc_read(void *opaque, hwaddr addr, uint64_t *pdata,
246
+ unsigned size, MemTxAttrs attrs)
247
+{
248
+ TZPPCPort *p = opaque;
249
+ TZPPC *s = p->ppc;
250
+ int n = p - s->port;
251
+ AddressSpace *as = &p->downstream_as;
252
+ uint64_t data;
253
+ MemTxResult res;
254
+
255
+ if (!tz_ppc_check(s, n, attrs)) {
256
+ trace_tz_ppc_read_blocked(n, addr, attrs.secure, attrs.user);
257
+ if (s->cfg_sec_resp) {
258
+ return MEMTX_ERROR;
259
+ } else {
260
+ *pdata = 0;
261
+ return MEMTX_OK;
262
+ }
263
+ }
101
+ }
264
+
102
+
265
+ switch (size) {
103
+ switch (opc) {
266
+ case 1:
104
+ case 0: /* STLURB */
267
+ data = address_space_ldub(as, addr, attrs, &res);
105
+ is_store = true;
268
+ break;
106
+ break;
269
+ case 2:
107
+ case 1: /* LDAPUR* */
270
+ data = address_space_lduw_le(as, addr, attrs, &res);
271
+ break;
108
+ break;
272
+ case 4:
109
+ case 2: /* LDAPURS* 64-bit variant */
273
+ data = address_space_ldl_le(as, addr, attrs, &res);
110
+ if (size == 3) {
111
+ unallocated_encoding(s);
112
+ return;
113
+ }
114
+ is_signed = true;
274
+ break;
115
+ break;
275
+ case 8:
116
+ case 3: /* LDAPURS* 32-bit variant */
276
+ data = address_space_ldq_le(as, addr, attrs, &res);
117
+ if (size > 1) {
118
+ unallocated_encoding(s);
119
+ return;
120
+ }
121
+ is_signed = true;
122
+ extend = true; /* zero-extend 32->64 after signed load */
277
+ break;
123
+ break;
278
+ default:
124
+ default:
279
+ g_assert_not_reached();
125
+ g_assert_not_reached();
280
+ }
126
+ }
281
+ *pdata = data;
282
+ return res;
283
+}
284
+
127
+
285
+static MemTxResult tz_ppc_write(void *opaque, hwaddr addr, uint64_t val,
128
+ iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
286
+ unsigned size, MemTxAttrs attrs)
287
+{
288
+ TZPPCPort *p = opaque;
289
+ TZPPC *s = p->ppc;
290
+ AddressSpace *as = &p->downstream_as;
291
+ int n = p - s->port;
292
+ MemTxResult res;
293
+
129
+
294
+ if (!tz_ppc_check(s, n, attrs)) {
130
+ if (rn == 31) {
295
+ trace_tz_ppc_write_blocked(n, addr, attrs.secure, attrs.user);
131
+ gen_check_sp_alignment(s);
296
+ if (s->cfg_sec_resp) {
297
+ return MEMTX_ERROR;
298
+ } else {
299
+ return MEMTX_OK;
300
+ }
301
+ }
132
+ }
302
+
133
+
303
+ switch (size) {
134
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
304
+ case 1:
135
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
305
+ address_space_stb(as, addr, val, attrs, &res);
136
+ clean_addr = clean_data_tbi(s, dirty_addr);
306
+ break;
307
+ case 2:
308
+ address_space_stw_le(as, addr, val, attrs, &res);
309
+ break;
310
+ case 4:
311
+ address_space_stl_le(as, addr, val, attrs, &res);
312
+ break;
313
+ case 8:
314
+ address_space_stq_le(as, addr, val, attrs, &res);
315
+ break;
316
+ default:
317
+ g_assert_not_reached();
318
+ }
319
+ return res;
320
+}
321
+
137
+
322
+static const MemoryRegionOps tz_ppc_ops = {
138
+ if (is_store) {
323
+ .read_with_attrs = tz_ppc_read,
139
+ /* Store-Release semantics */
324
+ .write_with_attrs = tz_ppc_write,
140
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
325
+ .endianness = DEVICE_LITTLE_ENDIAN,
141
+ do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt, iss_sf, true);
326
+};
142
+ } else {
327
+
143
+ /*
328
+static void tz_ppc_reset(DeviceState *dev)
144
+ * Load-AcquirePC semantics; we implement as the slightly more
329
+{
145
+ * restrictive Load-Acquire.
330
+ TZPPC *s = TZ_PPC(dev);
146
+ */
331
+
147
+ do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, is_signed, extend,
332
+ trace_tz_ppc_reset();
148
+ true, rt, iss_sf, true);
333
+ s->cfg_sec_resp = false;
149
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
334
+ memset(s->cfg_nonsec, 0, sizeof(s->cfg_nonsec));
335
+ memset(s->cfg_ap, 0, sizeof(s->cfg_ap));
336
+}
337
+
338
+static void tz_ppc_init(Object *obj)
339
+{
340
+ DeviceState *dev = DEVICE(obj);
341
+ TZPPC *s = TZ_PPC(obj);
342
+
343
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_nonsec, "cfg_nonsec", TZ_NUM_PORTS);
344
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_ap, "cfg_ap", TZ_NUM_PORTS);
345
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_sec_resp, "cfg_sec_resp", 1);
346
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_enable, "irq_enable", 1);
347
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_clear, "irq_clear", 1);
348
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
349
+}
350
+
351
+static void tz_ppc_realize(DeviceState *dev, Error **errp)
352
+{
353
+ Object *obj = OBJECT(dev);
354
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
355
+ TZPPC *s = TZ_PPC(dev);
356
+ int i;
357
+
358
+ /* We can't create the upstream end of the port until realize,
359
+ * as we don't know the size of the MR used as the downstream until then.
360
+ */
361
+ for (i = 0; i < TZ_NUM_PORTS; i++) {
362
+ TZPPCPort *port = &s->port[i];
363
+ char *name;
364
+ uint64_t size;
365
+
366
+ if (!port->downstream) {
367
+ continue;
368
+ }
369
+
370
+ name = g_strdup_printf("tz-ppc-port[%d]", i);
371
+
372
+ port->ppc = s;
373
+ address_space_init(&port->downstream_as, port->downstream, name);
374
+
375
+ size = memory_region_size(port->downstream);
376
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
377
+ port, name, size);
378
+ sysbus_init_mmio(sbd, &port->upstream);
379
+ g_free(name);
380
+ }
150
+ }
381
+}
151
+}
382
+
152
+
383
+static const VMStateDescription tz_ppc_vmstate = {
153
/* Load/store register (all forms) */
384
+ .name = "tz-ppc",
154
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
385
+ .version_id = 1,
155
{
386
+ .minimum_version_id = 1,
156
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
387
+ .fields = (VMStateField[]) {
157
case 0x0d: /* AdvSIMD load/store single structure */
388
+ VMSTATE_BOOL_ARRAY(cfg_nonsec, TZPPC, 16),
158
disas_ldst_single_struct(s, insn);
389
+ VMSTATE_BOOL_ARRAY(cfg_ap, TZPPC, 16),
159
break;
390
+ VMSTATE_BOOL(cfg_sec_resp, TZPPC),
160
+ case 0x19: /* LDAPR/STLR (unscaled immediate) */
391
+ VMSTATE_BOOL(irq_enable, TZPPC),
161
+ if (extract32(insn, 10, 2) != 0 ||
392
+ VMSTATE_BOOL(irq_clear, TZPPC),
162
+ extract32(insn, 21, 1) != 0) {
393
+ VMSTATE_BOOL(irq_status, TZPPC),
163
+ unallocated_encoding(s);
394
+ VMSTATE_END_OF_LIST()
164
+ break;
395
+ }
165
+ }
396
+};
166
+ disas_ldst_ldapr_stlr(s, insn);
397
+
167
+ break;
398
+#define DEFINE_PORT(N) \
168
default:
399
+ DEFINE_PROP_LINK("port[" #N "]", TZPPC, port[N].downstream, \
169
unallocated_encoding(s);
400
+ TYPE_MEMORY_REGION, MemoryRegion *)
170
break;
401
+
402
+static Property tz_ppc_properties[] = {
403
+ DEFINE_PROP_UINT32("NONSEC_MASK", TZPPC, nonsec_mask, 0),
404
+ DEFINE_PORT(0),
405
+ DEFINE_PORT(1),
406
+ DEFINE_PORT(2),
407
+ DEFINE_PORT(3),
408
+ DEFINE_PORT(4),
409
+ DEFINE_PORT(5),
410
+ DEFINE_PORT(6),
411
+ DEFINE_PORT(7),
412
+ DEFINE_PORT(8),
413
+ DEFINE_PORT(9),
414
+ DEFINE_PORT(10),
415
+ DEFINE_PORT(11),
416
+ DEFINE_PORT(12),
417
+ DEFINE_PORT(13),
418
+ DEFINE_PORT(14),
419
+ DEFINE_PORT(15),
420
+ DEFINE_PROP_END_OF_LIST(),
421
+};
422
+
423
+static void tz_ppc_class_init(ObjectClass *klass, void *data)
424
+{
425
+ DeviceClass *dc = DEVICE_CLASS(klass);
426
+
427
+ dc->realize = tz_ppc_realize;
428
+ dc->vmsd = &tz_ppc_vmstate;
429
+ dc->reset = tz_ppc_reset;
430
+ dc->props = tz_ppc_properties;
431
+}
432
+
433
+static const TypeInfo tz_ppc_info = {
434
+ .name = TYPE_TZ_PPC,
435
+ .parent = TYPE_SYS_BUS_DEVICE,
436
+ .instance_size = sizeof(TZPPC),
437
+ .instance_init = tz_ppc_init,
438
+ .class_init = tz_ppc_class_init,
439
+};
440
+
441
+static void tz_ppc_register_types(void)
442
+{
443
+ type_register_static(&tz_ppc_info);
444
+}
445
+
446
+type_init(tz_ppc_register_types);
447
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
448
index XXXXXXX..XXXXXXX 100644
449
--- a/default-configs/arm-softmmu.mak
450
+++ b/default-configs/arm-softmmu.mak
451
@@ -XXX,XX +XXX,XX @@ CONFIG_CMSDK_APB_UART=y
452
CONFIG_MPS2_FPGAIO=y
453
CONFIG_MPS2_SCC=y
454
455
+CONFIG_TZ_PPC=y
456
+
457
CONFIG_VERSATILE_PCI=y
458
CONFIG_VERSATILE_I2C=y
459
460
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
461
index XXXXXXX..XXXXXXX 100644
462
--- a/hw/misc/trace-events
463
+++ b/hw/misc/trace-events
464
@@ -XXX,XX +XXX,XX @@ mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch=%d co
465
mos6522_set_sr_int(void) "set sr_int"
466
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
467
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
468
+
469
+# hw/misc/tz-ppc.c
470
+tz_ppc_reset(void) "TZ PPC: reset"
471
+tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
472
+tz_ppc_cfg_ap(int n, int level) "TZ PPC: cfg_ap[%d] = %d"
473
+tz_ppc_cfg_sec_resp(int level) "TZ PPC: cfg_sec_resp = %d"
474
+tz_ppc_irq_enable(int level) "TZ PPC: int_enable = %d"
475
+tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
476
+tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
477
+tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
478
+tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
479
--
171
--
480
2.16.2
172
2.20.1
481
173
482
174
diff view generated by jsdifflib
1
The IoTKit Security Controller includes various registers
1
The ARMv8.3-CCIDX extension makes the CCSIDR_EL1 system ID registers
2
that expose to software the controls for the Peripheral
2
have a format that uses the full 64 bit width of the register, and
3
Protection Controllers in the system. Implement these.
3
adds a new CCSIDR2 register so AArch32 can get at the high 32 bits.
4
5
QEMU doesn't implement caches, so we just treat these ID registers as
6
opaque values that are set to the correct constant values for each
7
CPU. The only thing we need to do is allow 64-bit values in our
8
cssidr[] array and provide the CCSIDR2 accessors.
9
10
We don't set the CCIDX field in our 'max' CPU because the CCSIDR
11
constant values we use are the same as the ones used by the
12
Cortex-A57 and they are in the old 32-bit format. This means
13
that the extra regdef added here is unused currently, but it
14
means that whenever in the future we add a CPU that does need
15
the new 64-bit format it will just work when we set the cssidr
16
values and the ID registers for it.
4
17
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-17-peter.maydell@linaro.org
20
Message-id: 20200224182626.29252-1-peter.maydell@linaro.org
8
---
21
---
9
include/hw/misc/iotkit-secctl.h | 64 +++++++++-
22
target/arm/cpu.h | 17 ++++++++++++++++-
10
hw/misc/iotkit-secctl.c | 270 +++++++++++++++++++++++++++++++++++++---
23
target/arm/helper.c | 19 +++++++++++++++++++
11
2 files changed, 315 insertions(+), 19 deletions(-)
24
2 files changed, 35 insertions(+), 1 deletion(-)
12
25
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
28
--- a/target/arm/cpu.h
16
+++ b/include/hw/misc/iotkit-secctl.h
29
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
18
* QEMU interface:
31
/* The elements of this array are the CCSIDR values for each cache,
19
* + sysbus MMIO region 0 is the "secure privilege control block" registers
32
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
20
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
33
*/
21
+ * + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
34
- uint32_t ccsidr[16];
22
+ * should RAZ/WI or bus error
35
+ uint64_t ccsidr[16];
23
+ * Controlling the 2 APB PPCs in the IoTKit:
36
uint64_t reset_cbar;
24
+ * + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
37
uint32_t reset_auxcr;
25
+ * + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
38
bool reset_hivecs;
26
+ * + named GPIO outputs apb_ppc{0,1}_irq_enable
39
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id)
27
+ * + named GPIO outputs apb_ppc{0,1}_irq_clear
40
return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0;
28
+ * + named GPIO inputs apb_ppc{0,1}_irq_status
41
}
29
+ * Controlling each of the 4 expansion APB PPCs which a system using the IoTKit
42
30
+ * might provide:
43
+static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id)
31
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
32
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
33
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
34
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
35
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
36
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
37
+ * might provide:
38
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
39
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
40
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
41
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
42
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
43
*/
44
45
#ifndef IOTKIT_SECCTL_H
46
@@ -XXX,XX +XXX,XX @@
47
#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
48
#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
49
50
-typedef struct IoTKitSecCtl {
51
+#define IOTS_APB_PPC0_NUM_PORTS 3
52
+#define IOTS_APB_PPC1_NUM_PORTS 1
53
+#define IOTS_PPC_NUM_PORTS 16
54
+#define IOTS_NUM_APB_PPC 2
55
+#define IOTS_NUM_APB_EXP_PPC 4
56
+#define IOTS_NUM_AHB_EXP_PPC 4
57
+
58
+typedef struct IoTKitSecCtl IoTKitSecCtl;
59
+
60
+/* State and IRQ lines relating to a PPC. For the
61
+ * PPCs in the IoTKit not all the IRQ lines are used.
62
+ */
63
+typedef struct IoTKitSecCtlPPC {
64
+ qemu_irq nonsec[IOTS_PPC_NUM_PORTS];
65
+ qemu_irq ap[IOTS_PPC_NUM_PORTS];
66
+ qemu_irq irq_enable;
67
+ qemu_irq irq_clear;
68
+
69
+ uint32_t ns;
70
+ uint32_t sp;
71
+ uint32_t nsp;
72
+
73
+ /* Number of ports actually present */
74
+ int numports;
75
+ /* Offset of this PPC's interrupt bits in SECPPCINTSTAT */
76
+ int irq_bit_offset;
77
+ IoTKitSecCtl *parent;
78
+} IoTKitSecCtlPPC;
79
+
80
+struct IoTKitSecCtl {
81
/*< private >*/
82
SysBusDevice parent_obj;
83
84
/*< public >*/
85
+ qemu_irq sec_resp_cfg;
86
87
MemoryRegion s_regs;
88
MemoryRegion ns_regs;
89
-} IoTKitSecCtl;
90
+
91
+ uint32_t secppcintstat;
92
+ uint32_t secppcinten;
93
+ uint32_t secrespcfg;
94
+
95
+ IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
96
+ IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
97
+ IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
98
+};
99
100
#endif
101
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/misc/iotkit-secctl.c
104
+++ b/hw/misc/iotkit-secctl.c
105
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
106
0x0d, 0xf0, 0x05, 0xb1,
107
};
108
109
+/* The register sets for the various PPCs (AHB internal, APB internal,
110
+ * AHB expansion, APB expansion) are all set up so that they are
111
+ * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
112
+ * 0, 1, 2, 3 of that type, so we can convert a register address offset
113
+ * into an an index into a PPC array easily.
114
+ */
115
+static inline int offset_to_ppc_idx(uint32_t offset)
116
+{
44
+{
117
+ return extract32(offset, 2, 2);
45
+ return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0;
118
+}
46
+}
119
+
47
+
120
+typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
48
/*
121
+
49
* 64-bit feature tests via id registers.
122
+static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
50
*/
51
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
52
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2;
53
}
54
55
+static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
123
+{
56
+{
124
+ int i;
57
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
125
+
126
+ for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
127
+ fn(&s->apb[i]);
128
+ }
129
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
130
+ fn(&s->apbexp[i]);
131
+ }
132
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
133
+ fn(&s->ahbexp[i]);
134
+ }
135
+}
58
+}
136
+
59
+
137
static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
60
/*
138
uint64_t *pdata,
61
* Feature tests for "does this exist in either 32-bit or 64-bit?"
139
unsigned size, MemTxAttrs attrs)
62
*/
140
{
63
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_pmu_8_4(const ARMISARegisters *id)
141
uint64_t r;
64
return isar_feature_aa64_pmu_8_4(id) || isar_feature_aa32_pmu_8_4(id);
142
uint32_t offset = addr & ~0x3;
143
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
144
145
switch (offset) {
146
case A_AHBNSPPC0:
147
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
148
r = 0;
149
break;
150
case A_SECRESPCFG:
151
- case A_NSCCFG:
152
- case A_SECMPCINTSTATUS:
153
+ r = s->secrespcfg;
154
+ break;
155
case A_SECPPCINTSTAT:
156
+ r = s->secppcintstat;
157
+ break;
158
case A_SECPPCINTEN:
159
- case A_SECMSCINTSTAT:
160
- case A_SECMSCINTEN:
161
- case A_BRGINTSTAT:
162
- case A_BRGINTEN:
163
+ r = s->secppcinten;
164
+ break;
165
case A_AHBNSPPCEXP0:
166
case A_AHBNSPPCEXP1:
167
case A_AHBNSPPCEXP2:
168
case A_AHBNSPPCEXP3:
169
+ r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
170
+ break;
171
case A_APBNSPPC0:
172
case A_APBNSPPC1:
173
+ r = s->apb[offset_to_ppc_idx(offset)].ns;
174
+ break;
175
case A_APBNSPPCEXP0:
176
case A_APBNSPPCEXP1:
177
case A_APBNSPPCEXP2:
178
case A_APBNSPPCEXP3:
179
+ r = s->apbexp[offset_to_ppc_idx(offset)].ns;
180
+ break;
181
case A_AHBSPPPCEXP0:
182
case A_AHBSPPPCEXP1:
183
case A_AHBSPPPCEXP2:
184
case A_AHBSPPPCEXP3:
185
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
186
+ break;
187
case A_APBSPPPC0:
188
case A_APBSPPPC1:
189
+ r = s->apb[offset_to_ppc_idx(offset)].sp;
190
+ break;
191
case A_APBSPPPCEXP0:
192
case A_APBSPPPCEXP1:
193
case A_APBSPPPCEXP2:
194
case A_APBSPPPCEXP3:
195
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
196
+ break;
197
+ case A_NSCCFG:
198
+ case A_SECMPCINTSTATUS:
199
+ case A_SECMSCINTSTAT:
200
+ case A_SECMSCINTEN:
201
+ case A_BRGINTSTAT:
202
+ case A_BRGINTEN:
203
case A_NSMSCEXP:
204
qemu_log_mask(LOG_UNIMP,
205
"IoTKit SecCtl S block read: "
206
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
207
return MEMTX_OK;
208
}
65
}
209
66
210
+static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
67
+static inline bool isar_feature_any_ccidx(const ARMISARegisters *id)
211
+{
68
+{
212
+ int i;
69
+ return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id);
213
+
214
+ for (i = 0; i < ppc->numports; i++) {
215
+ bool v;
216
+
217
+ if (extract32(ppc->ns, i, 1)) {
218
+ v = extract32(ppc->nsp, i, 1);
219
+ } else {
220
+ v = extract32(ppc->sp, i, 1);
221
+ }
222
+ qemu_set_irq(ppc->ap[i], v);
223
+ }
224
+}
70
+}
225
+
71
+
226
+static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
72
/*
73
* Forward to the above feature tests given an ARMCPU pointer.
74
*/
75
diff --git a/target/arm/helper.c b/target/arm/helper.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/helper.c
78
+++ b/target/arm/helper.c
79
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo predinv_reginfo[] = {
80
REGINFO_SENTINEL
81
};
82
83
+static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri)
227
+{
84
+{
228
+ int i;
85
+ /* Read the high 32 bits of the current CCSIDR */
229
+
86
+ return extract64(ccsidr_read(env, ri), 32, 32);
230
+ ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
231
+ for (i = 0; i < ppc->numports; i++) {
232
+ qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
233
+ }
234
+ iotkit_secctl_update_ppc_ap(ppc);
235
+}
87
+}
236
+
88
+
237
+static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
89
+static const ARMCPRegInfo ccsidr2_reginfo[] = {
238
+{
90
+ { .name = "CCSIDR2", .state = ARM_CP_STATE_BOTH,
239
+ ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
91
+ .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 2,
240
+ iotkit_secctl_update_ppc_ap(ppc);
92
+ .access = PL1_R,
241
+}
93
+ .accessfn = access_aa64_tid2,
94
+ .readfn = ccsidr2_read, .type = ARM_CP_NO_RAW },
95
+ REGINFO_SENTINEL
96
+};
242
+
97
+
243
+static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
98
static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
244
+{
99
bool isread)
245
+ ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
246
+ iotkit_secctl_update_ppc_ap(ppc);
247
+}
248
+
249
+static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
250
+{
251
+ uint32_t value = ppc->parent->secppcintstat;
252
+
253
+ qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
254
+}
255
+
256
+static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
257
+{
258
+ uint32_t value = ppc->parent->secppcinten;
259
+
260
+ qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
261
+}
262
+
263
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
264
uint64_t value,
265
unsigned size, MemTxAttrs attrs)
266
{
100
{
267
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
101
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
268
uint32_t offset = addr;
102
define_arm_cp_regs(cpu, predinv_reginfo);
269
+ IoTKitSecCtlPPC *ppc;
103
}
270
104
271
trace_iotkit_secctl_s_write(offset, value, size);
105
+ if (cpu_isar_feature(any_ccidx, cpu)) {
272
106
+ define_arm_cp_regs(cpu, ccsidr2_reginfo);
273
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
274
275
switch (offset) {
276
case A_SECRESPCFG:
277
- case A_NSCCFG:
278
+ value &= 1;
279
+ s->secrespcfg = value;
280
+ qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
281
+ break;
282
case A_SECPPCINTCLR:
283
+ value &= 0x00f000f3;
284
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
285
+ break;
286
case A_SECPPCINTEN:
287
- case A_SECMSCINTCLR:
288
- case A_SECMSCINTEN:
289
- case A_BRGINTCLR:
290
- case A_BRGINTEN:
291
+ s->secppcinten = value & 0x00f000f3;
292
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
293
+ break;
294
case A_AHBNSPPCEXP0:
295
case A_AHBNSPPCEXP1:
296
case A_AHBNSPPCEXP2:
297
case A_AHBNSPPCEXP3:
298
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
299
+ iotkit_secctl_ppc_ns_write(ppc, value);
300
+ break;
301
case A_APBNSPPC0:
302
case A_APBNSPPC1:
303
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
304
+ iotkit_secctl_ppc_ns_write(ppc, value);
305
+ break;
306
case A_APBNSPPCEXP0:
307
case A_APBNSPPCEXP1:
308
case A_APBNSPPCEXP2:
309
case A_APBNSPPCEXP3:
310
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
311
+ iotkit_secctl_ppc_ns_write(ppc, value);
312
+ break;
313
case A_AHBSPPPCEXP0:
314
case A_AHBSPPPCEXP1:
315
case A_AHBSPPPCEXP2:
316
case A_AHBSPPPCEXP3:
317
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
318
+ iotkit_secctl_ppc_sp_write(ppc, value);
319
+ break;
320
case A_APBSPPPC0:
321
case A_APBSPPPC1:
322
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
323
+ iotkit_secctl_ppc_sp_write(ppc, value);
324
+ break;
325
case A_APBSPPPCEXP0:
326
case A_APBSPPPCEXP1:
327
case A_APBSPPPCEXP2:
328
case A_APBSPPPCEXP3:
329
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
330
+ iotkit_secctl_ppc_sp_write(ppc, value);
331
+ break;
332
+ case A_NSCCFG:
333
+ case A_SECMSCINTCLR:
334
+ case A_SECMSCINTEN:
335
+ case A_BRGINTCLR:
336
+ case A_BRGINTEN:
337
qemu_log_mask(LOG_UNIMP,
338
"IoTKit SecCtl S block write: "
339
"unimplemented offset 0x%x\n", offset);
340
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
341
uint64_t *pdata,
342
unsigned size, MemTxAttrs attrs)
343
{
344
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
345
uint64_t r;
346
uint32_t offset = addr & ~0x3;
347
348
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
349
case A_AHBNSPPPCEXP1:
350
case A_AHBNSPPPCEXP2:
351
case A_AHBNSPPPCEXP3:
352
+ r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
353
+ break;
354
case A_APBNSPPPC0:
355
case A_APBNSPPPC1:
356
+ r = s->apb[offset_to_ppc_idx(offset)].nsp;
357
+ break;
358
case A_APBNSPPPCEXP0:
359
case A_APBNSPPPCEXP1:
360
case A_APBNSPPPCEXP2:
361
case A_APBNSPPPCEXP3:
362
- qemu_log_mask(LOG_UNIMP,
363
- "IoTKit SecCtl NS block read: "
364
- "unimplemented offset 0x%x\n", offset);
365
+ r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
366
break;
367
case A_PID4:
368
case A_PID5:
369
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
370
uint64_t value,
371
unsigned size, MemTxAttrs attrs)
372
{
373
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
374
uint32_t offset = addr;
375
+ IoTKitSecCtlPPC *ppc;
376
377
trace_iotkit_secctl_ns_write(offset, value, size);
378
379
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
380
case A_AHBNSPPPCEXP1:
381
case A_AHBNSPPPCEXP2:
382
case A_AHBNSPPPCEXP3:
383
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
384
+ iotkit_secctl_ppc_nsp_write(ppc, value);
385
+ break;
386
case A_APBNSPPPC0:
387
case A_APBNSPPPC1:
388
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
389
+ iotkit_secctl_ppc_nsp_write(ppc, value);
390
+ break;
391
case A_APBNSPPPCEXP0:
392
case A_APBNSPPPCEXP1:
393
case A_APBNSPPPCEXP2:
394
case A_APBNSPPPCEXP3:
395
- qemu_log_mask(LOG_UNIMP,
396
- "IoTKit SecCtl NS block write: "
397
- "unimplemented offset 0x%x\n", offset);
398
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
399
+ iotkit_secctl_ppc_nsp_write(ppc, value);
400
break;
401
case A_AHBNSPPPC0:
402
case A_PID4:
403
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_secctl_ns_ops = {
404
.impl.max_access_size = 4,
405
};
406
407
+static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
408
+{
409
+ ppc->ns = 0;
410
+ ppc->sp = 0;
411
+ ppc->nsp = 0;
412
+}
413
+
414
static void iotkit_secctl_reset(DeviceState *dev)
415
{
416
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
417
418
+ s->secppcintstat = 0;
419
+ s->secppcinten = 0;
420
+ s->secrespcfg = 0;
421
+
422
+ foreach_ppc(s, iotkit_secctl_reset_ppc);
423
+}
424
+
425
+static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
426
+{
427
+ IoTKitSecCtlPPC *ppc = opaque;
428
+ IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
429
+ int irqbit = ppc->irq_bit_offset + n;
430
+
431
+ s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
432
+}
433
+
434
+static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
435
+ IoTKitSecCtlPPC *ppc,
436
+ const char *name,
437
+ int numports,
438
+ int irq_bit_offset)
439
+{
440
+ char *gpioname;
441
+ DeviceState *dev = DEVICE(s);
442
+
443
+ ppc->numports = numports;
444
+ ppc->irq_bit_offset = irq_bit_offset;
445
+ ppc->parent = s;
446
+
447
+ gpioname = g_strdup_printf("%s_nonsec", name);
448
+ qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
449
+ g_free(gpioname);
450
+ gpioname = g_strdup_printf("%s_ap", name);
451
+ qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
452
+ g_free(gpioname);
453
+ gpioname = g_strdup_printf("%s_irq_enable", name);
454
+ qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_irq_clear", name);
457
+ qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
458
+ g_free(gpioname);
459
+ gpioname = g_strdup_printf("%s_irq_status", name);
460
+ qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
461
+ ppc, gpioname, 1);
462
+ g_free(gpioname);
463
}
464
465
static void iotkit_secctl_init(Object *obj)
466
{
467
IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
468
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
469
+ DeviceState *dev = DEVICE(obj);
470
+ int i;
471
+
472
+ iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
473
+ IOTS_APB_PPC0_NUM_PORTS, 0);
474
+ iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
475
+ IOTS_APB_PPC1_NUM_PORTS, 1);
476
+
477
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
478
+ IoTKitSecCtlPPC *ppc = &s->apbexp[i];
479
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
480
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
481
+ g_free(ppcname);
482
+ }
483
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
484
+ IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
485
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
486
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
487
+ g_free(ppcname);
488
+ }
107
+ }
489
+
108
+
490
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
109
#ifndef CONFIG_USER_ONLY
491
110
/*
492
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
111
* Register redirections and aliases must be done last,
493
s, "iotkit-secctl-s-regs", 0x1000);
494
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
495
sysbus_init_mmio(sbd, &s->ns_regs);
496
}
497
498
+static const VMStateDescription iotkit_secctl_ppc_vmstate = {
499
+ .name = "iotkit-secctl-ppc",
500
+ .version_id = 1,
501
+ .minimum_version_id = 1,
502
+ .fields = (VMStateField[]) {
503
+ VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
504
+ VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
505
+ VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
506
+ VMSTATE_END_OF_LIST()
507
+ }
508
+};
509
+
510
static const VMStateDescription iotkit_secctl_vmstate = {
511
.name = "iotkit-secctl",
512
.version_id = 1,
513
.minimum_version_id = 1,
514
.fields = (VMStateField[]) {
515
+ VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
516
+ VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
517
+ VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
518
+ VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
519
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
520
+ VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
521
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
522
+ VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
523
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
524
VMSTATE_END_OF_LIST()
525
}
526
};
527
--
112
--
528
2.16.2
113
2.20.1
529
114
530
115
diff view generated by jsdifflib
1
In some board or SoC models it is necessary to split a qemu_irq line
1
In our KVM GICv2 realize function, we try to cope with old kernels
2
so that one input can feed multiple outputs. We currently have
2
that don't provide the device control API (KVM_CAP_DEVICE_CTRL): we
3
qemu_irq_split() for this, but that has several deficiencies:
3
try to use the device control, and if that fails we fall back to
4
* it can only handle splitting a line into two
4
assuming that the kernel has the old style KVM_CREATE_IRQCHIP and
5
* it unavoidably leaks memory, so it can't be used
5
that it will provide a GICv2.
6
in a device that can be deleted
7
6
8
Implement a qdev device that encapsulates splitting of IRQs, with a
7
This doesn't cater for the possibility of a kernel and hardware which
9
configurable number of outputs. (This is in some ways the inverse of
8
only provide a GICv3, which is very common now. On that setup we
10
the TYPE_OR_IRQ device.)
9
will abort() later on in kvm_arm_pmu_set_irq() when we try to wire up
10
an interrupt to the GIC we failed to create:
11
12
qemu-system-aarch64: PMU: KVM_SET_DEVICE_ATTR: Invalid argument
13
qemu-system-aarch64: failed to set irq for PMU
14
Aborted
15
16
If the kernel advertises KVM_CAP_DEVICE_CTRL we should trust it if it
17
says it can't create a GICv2, rather than assuming it has one. We
18
can then produce a more helpful error message including a hint about
19
the most probable reason for the failure.
20
21
If the kernel doesn't advertise KVM_CAP_DEVICE_CTRL then it is truly
22
ancient by this point but we might as well still fall back to a
23
KVM_CREATE_IRQCHIP GICv2.
24
25
With this patch then the user misconfiguration which previously
26
caused an abort now prints:
27
qemu-system-aarch64: Initialization of device kvm-arm-gic failed: error creating in-kernel VGIC: No such device
28
Perhaps the host CPU does not support GICv2?
11
29
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Message-id: 20180220180325.29818-13-peter.maydell@linaro.org
32
Reviewed-by: Andrew Jones <drjones@redhat.com>
33
Tested-by: Andrew Jones <drjones@redhat.com>
34
Message-id: 20200225182435.1131-1-peter.maydell@linaro.org
15
---
35
---
16
hw/core/Makefile.objs | 1 +
36
hw/intc/arm_gic_kvm.c | 9 +++++++++
17
include/hw/core/split-irq.h | 57 +++++++++++++++++++++++++++++
37
1 file changed, 9 insertions(+)
18
include/hw/irq.h | 4 +-
19
hw/core/split-irq.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
20
4 files changed, 150 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/core/split-irq.h
22
create mode 100644 hw/core/split-irq.c
23
38
24
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
39
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
25
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/core/Makefile.objs
41
--- a/hw/intc/arm_gic_kvm.c
27
+++ b/hw/core/Makefile.objs
42
+++ b/hw/intc/arm_gic_kvm.c
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_FITLOADER) += loader-fit.o
43
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
29
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
44
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true,
30
common-obj-$(CONFIG_SOFTMMU) += register.o
45
&error_abort);
31
common-obj-$(CONFIG_SOFTMMU) += or-irq.o
46
}
32
+common-obj-$(CONFIG_SOFTMMU) += split-irq.o
47
+ } else if (kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) {
33
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
48
+ error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
34
49
+ error_append_hint(errp,
35
obj-$(CONFIG_SOFTMMU) += generic-loader.o
50
+ "Perhaps the host CPU does not support GICv2?\n");
36
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
51
} else if (ret != -ENODEV && ret != -ENOTSUP) {
37
new file mode 100644
52
+ /*
38
index XXXXXXX..XXXXXXX
53
+ * Very ancient kernel without KVM_CAP_DEVICE_CTRL: assume that
39
--- /dev/null
54
+ * ENODEV or ENOTSUP mean "can't create GICv2 with KVM_CREATE_DEVICE",
40
+++ b/include/hw/core/split-irq.h
55
+ * and that we will get a GICv2 via KVM_CREATE_IRQCHIP.
41
@@ -XXX,XX +XXX,XX @@
56
+ */
42
+/*
57
error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
43
+ * IRQ splitter device.
58
return;
44
+ *
59
}
45
+ * Copyright (c) 2018 Linaro Limited.
46
+ * Written by Peter Maydell
47
+ *
48
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
49
+ * of this software and associated documentation files (the "Software"), to deal
50
+ * in the Software without restriction, including without limitation the rights
51
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52
+ * copies of the Software, and to permit persons to whom the Software is
53
+ * furnished to do so, subject to the following conditions:
54
+ *
55
+ * The above copyright notice and this permission notice shall be included in
56
+ * all copies or substantial portions of the Software.
57
+ *
58
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
61
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64
+ * THE SOFTWARE.
65
+ */
66
+
67
+/* This is a simple device which has one GPIO input line and multiple
68
+ * GPIO output lines. Any change on the input line is forwarded to all
69
+ * of the outputs.
70
+ *
71
+ * QEMU interface:
72
+ * + one unnamed GPIO input: the input line
73
+ * + N unnamed GPIO outputs: the output lines
74
+ * + QOM property "num-lines": sets the number of output lines
75
+ */
76
+#ifndef HW_SPLIT_IRQ_H
77
+#define HW_SPLIT_IRQ_H
78
+
79
+#include "hw/irq.h"
80
+#include "hw/sysbus.h"
81
+#include "qom/object.h"
82
+
83
+#define TYPE_SPLIT_IRQ "split-irq"
84
+
85
+#define MAX_SPLIT_LINES 16
86
+
87
+typedef struct SplitIRQ SplitIRQ;
88
+
89
+#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ)
90
+
91
+struct SplitIRQ {
92
+ DeviceState parent_obj;
93
+
94
+ qemu_irq out_irq[MAX_SPLIT_LINES];
95
+ uint16_t num_lines;
96
+};
97
+
98
+#endif
99
diff --git a/include/hw/irq.h b/include/hw/irq.h
100
index XXXXXXX..XXXXXXX 100644
101
--- a/include/hw/irq.h
102
+++ b/include/hw/irq.h
103
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
104
/* Returns a new IRQ with opposite polarity. */
105
qemu_irq qemu_irq_invert(qemu_irq irq);
106
107
-/* Returns a new IRQ which feeds into both the passed IRQs */
108
+/* Returns a new IRQ which feeds into both the passed IRQs.
109
+ * It's probably better to use the TYPE_SPLIT_IRQ device instead.
110
+ */
111
qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
112
113
/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
114
diff --git a/hw/core/split-irq.c b/hw/core/split-irq.c
115
new file mode 100644
116
index XXXXXXX..XXXXXXX
117
--- /dev/null
118
+++ b/hw/core/split-irq.c
119
@@ -XXX,XX +XXX,XX @@
120
+/*
121
+ * IRQ splitter device.
122
+ *
123
+ * Copyright (c) 2018 Linaro Limited.
124
+ * Written by Peter Maydell
125
+ *
126
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
127
+ * of this software and associated documentation files (the "Software"), to deal
128
+ * in the Software without restriction, including without limitation the rights
129
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
130
+ * copies of the Software, and to permit persons to whom the Software is
131
+ * furnished to do so, subject to the following conditions:
132
+ *
133
+ * The above copyright notice and this permission notice shall be included in
134
+ * all copies or substantial portions of the Software.
135
+ *
136
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
137
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
138
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
139
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
140
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
141
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
142
+ * THE SOFTWARE.
143
+ */
144
+
145
+#include "qemu/osdep.h"
146
+#include "hw/core/split-irq.h"
147
+#include "qapi/error.h"
148
+
149
+static void split_irq_handler(void *opaque, int n, int level)
150
+{
151
+ SplitIRQ *s = SPLIT_IRQ(opaque);
152
+ int i;
153
+
154
+ for (i = 0; i < s->num_lines; i++) {
155
+ qemu_set_irq(s->out_irq[i], level);
156
+ }
157
+}
158
+
159
+static void split_irq_init(Object *obj)
160
+{
161
+ qdev_init_gpio_in(DEVICE(obj), split_irq_handler, 1);
162
+}
163
+
164
+static void split_irq_realize(DeviceState *dev, Error **errp)
165
+{
166
+ SplitIRQ *s = SPLIT_IRQ(dev);
167
+
168
+ if (s->num_lines < 1 || s->num_lines >= MAX_SPLIT_LINES) {
169
+ error_setg(errp,
170
+ "IRQ splitter number of lines %d is not between 1 and %d",
171
+ s->num_lines, MAX_SPLIT_LINES);
172
+ return;
173
+ }
174
+
175
+ qdev_init_gpio_out(dev, s->out_irq, s->num_lines);
176
+}
177
+
178
+static Property split_irq_properties[] = {
179
+ DEFINE_PROP_UINT16("num-lines", SplitIRQ, num_lines, 1),
180
+ DEFINE_PROP_END_OF_LIST(),
181
+};
182
+
183
+static void split_irq_class_init(ObjectClass *klass, void *data)
184
+{
185
+ DeviceClass *dc = DEVICE_CLASS(klass);
186
+
187
+ /* No state to reset or migrate */
188
+ dc->props = split_irq_properties;
189
+ dc->realize = split_irq_realize;
190
+
191
+ /* Reason: Needs to be wired up to work */
192
+ dc->user_creatable = false;
193
+}
194
+
195
+static const TypeInfo split_irq_type_info = {
196
+ .name = TYPE_SPLIT_IRQ,
197
+ .parent = TYPE_DEVICE,
198
+ .instance_size = sizeof(SplitIRQ),
199
+ .instance_init = split_irq_init,
200
+ .class_init = split_irq_class_init,
201
+};
202
+
203
+static void split_irq_register_types(void)
204
+{
205
+ type_register_static(&split_irq_type_info);
206
+}
207
+
208
+type_init(split_irq_register_types)
209
--
60
--
210
2.16.2
61
2.20.1
211
62
212
63
diff view generated by jsdifflib