1
Ten arm-related bug fixes for 2.12...
1
Arm pullreq for the 2.12 codefreeze...
2
2
3
thanks
3
thanks
4
-- PMM
4
-- PMM
5
5
6
The following changes since commit 4c2c1015905fa1d616750dfe024b4c0b35875950:
6
The following changes since commit b39b61e410022f96ceb53d4381d25cba5126ac44:
7
7
8
Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20180323' into staging (2018-03-23 10:20:54 +0000)
8
memory: fix flatview_access_valid RCU read lock/unlock imbalance (2018-03-09 15:55:20 +0000)
9
9
10
are available in the Git repository at:
10
are available in the Git repository at:
11
11
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180323
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180309
13
13
14
for you to fetch changes up to 548f514cf89dd9ab39c0cb4c063097bccf141fdd:
14
for you to fetch changes up to 076a0fc32a73a9b960e0f73f04a531bc1bd94308:
15
15
16
target/arm: Always set FAR to a known unknown value for debug exceptions (2018-03-23 18:26:46 +0000)
16
MAINTAINERS: Add entries for SD (SDHCI, SDBus, SDCard) (2018-03-09 17:09:45 +0000)
17
17
18
----------------------------------------------------------------
18
----------------------------------------------------------------
19
target-arm queue:
19
target-arm queue:
20
* arm/translate-a64: don't lose interrupts after unmasking via write to DAIF
20
* i.MX: Add i.MX7 SOC implementation and i.MX7 Sabre board
21
* sdhci: fix incorrect use of Error *
21
* Report the correct core count in A53 L2CTLR on the ZynqMP board
22
* hw/intc/arm_gicv3: Fix secure-GIC NS ICC_PMR and ICC_RPR accesses
22
* linux-user: preliminary SVE support work (signal handling)
23
* hw/arm/bcm2836: Use the Cortex-A7 instead of Cortex-A15
23
* hw/arm/boot: fix memory leak in case of error loading ELF file
24
* i.MX: Support serial RS-232 break properly
24
* hw/arm/boot: avoid reading off end of buffer if passed very
25
* mach-virt: Set VM's SMBIOS system version to mc->name
25
small image file
26
* target/arm: Honour MDCR_EL2.TDE when routing exceptions due to BKPT/BRK
26
* hw/arm: Use more CONFIG switches for the object files
27
* target/arm: Factor out code to calculate FSR for debug exceptions
27
* target/arm: Add "-cpu max" support
28
* target/arm: Set FSR for BKPT, BRK when raising exception
28
* hw/arm/virt: Support -machine gic-version=max
29
* target/arm: Always set FAR to a known unknown value for debug exceptions
29
* hw/sd: improve debug tracing
30
* hw/sd: sdcard: Add the Tuning Command (CMD 19)
31
* MAINTAINERS: add Philippe as odd-fixes maintainer for SD
30
32
31
----------------------------------------------------------------
33
----------------------------------------------------------------
32
Paolo Bonzini (1):
34
Alistair Francis (2):
33
sdhci: fix incorrect use of Error *
35
target/arm: Add a core count property
36
hw/arm: Set the core count for Xilinx's ZynqMP
37
38
Andrey Smirnov (3):
39
pci: Add support for Designware IP block
40
i.MX: Add i.MX7 SOC implementation.
41
Implement support for i.MX7 Sabre board
42
43
Marc-André Lureau (2):
44
arm: fix load ELF error leak
45
arm: avoid heap-buffer-overflow in load_aarch64_image
34
46
35
Peter Maydell (6):
47
Peter Maydell (6):
36
hw/intc/arm_gicv3: Fix secure-GIC NS ICC_PMR and ICC_RPR accesses
48
target/arm: Query host CPU features on-demand at instance init
37
hw/arm/bcm2836: Use the Cortex-A7 instead of Cortex-A15
49
target/arm: Move definition of 'host' cpu type into cpu.c
38
target/arm: Honour MDCR_EL2.TDE when routing exceptions due to BKPT/BRK
50
target/arm: Add "-cpu max" support
39
target/arm: Factor out code to calculate FSR for debug exceptions
51
target/arm: Make 'any' CPU just an alias for 'max'
40
target/arm: Set FSR for BKPT, BRK when raising exception
52
hw/arm/virt: Add "max" to the list of CPU types "virt" supports
41
target/arm: Always set FAR to a known unknown value for debug exceptions
53
hw/arm/virt: Support -machine gic-version=max
42
54
43
Trent Piepho (1):
55
Philippe Mathieu-Daudé (6):
44
i.MX: Support serial RS-232 break properly
56
sdcard: Do not trace CMD55, except when we already expect an ACMD
57
sdcard: Display command name when tracing CMD/ACMD
58
sdcard: Display which protocol is used when tracing (SD or SPI)
59
sdcard: Add the Tuning Command (CMD19)
60
sdhci: Fix a typo in comment
61
MAINTAINERS: Add entries for SD (SDHCI, SDBus, SDCard)
45
62
46
Victor Kamensky (1):
63
Richard Henderson (5):
47
arm/translate-a64: treat DISAS_UPDATE as variant of DISAS_EXIT
64
linux-user: Implement aarch64 PR_SVE_SET/GET_VL
65
aarch64-linux-user: Split out helpers for guest signal handling
66
aarch64-linux-user: Remove struct target_aux_context
67
aarch64-linux-user: Add support for EXTRA signal frame records
68
aarch64-linux-user: Add support for SVE signal frame records
48
69
49
Wei Huang (1):
70
Thomas Huth (1):
50
mach-virt: Set VM's SMBIOS system version to mc->name
71
hw/arm: Use more CONFIG switches for the object files
51
72
52
include/hw/arm/virt.h | 1 +
73
hw/arm/Makefile.objs | 31 +-
53
include/hw/char/imx_serial.h | 1 +
74
hw/pci-host/Makefile.objs | 2 +
54
target/arm/helper.h | 1 +
75
hw/sd/Makefile.objs | 2 +-
55
target/arm/internals.h | 25 +++++++++++++++++++++++++
76
hw/sd/sdmmc-internal.h | 24 ++
56
hw/arm/bcm2836.c | 2 +-
77
include/hw/arm/fsl-imx7.h | 222 +++++++++++
57
hw/arm/raspi.c | 2 +-
78
include/hw/pci-host/designware.h | 102 +++++
58
hw/arm/virt.c | 8 +++++++-
79
include/hw/pci/pci_ids.h | 2 +
59
hw/char/imx_serial.c | 5 ++++-
80
linux-user/aarch64/target_syscall.h | 3 +
60
hw/intc/arm_gicv3_cpuif.c | 6 +++---
81
target/arm/cpu-qom.h | 2 +
61
hw/sd/sdhci.c | 4 ++--
82
target/arm/cpu.h | 11 +
62
target/arm/helper.c | 1 -
83
target/arm/kvm_arm.h | 35 +-
63
target/arm/op_helper.c | 33 ++++++++++++++++++++++-----------
84
hw/arm/boot.c | 4 +-
64
target/arm/translate-a64.c | 21 ++++++++++++++++-----
85
hw/arm/fsl-imx7.c | 582 ++++++++++++++++++++++++++++
65
target/arm/translate.c | 19 ++++++++++++++-----
86
hw/arm/mcimx7d-sabre.c | 90 +++++
66
14 files changed, 98 insertions(+), 31 deletions(-)
87
hw/arm/virt.c | 30 +-
88
hw/arm/xlnx-zynqmp.c | 2 +
89
hw/pci-host/designware.c | 754 ++++++++++++++++++++++++++++++++++++
90
hw/sd/sd.c | 55 ++-
91
hw/sd/sdhci.c | 4 +-
92
hw/sd/sdmmc-internal.c | 72 ++++
93
linux-user/signal.c | 415 ++++++++++++++++----
94
linux-user/syscall.c | 27 ++
95
target/arm/cpu.c | 103 ++++-
96
target/arm/cpu64.c | 113 ++++--
97
target/arm/kvm.c | 53 +--
98
target/arm/kvm32.c | 8 +-
99
target/arm/kvm64.c | 8 +-
100
MAINTAINERS | 8 +
101
default-configs/arm-softmmu.mak | 9 +
102
hw/sd/trace-events | 8 +-
103
30 files changed, 2583 insertions(+), 198 deletions(-)
104
create mode 100644 include/hw/arm/fsl-imx7.h
105
create mode 100644 include/hw/pci-host/designware.h
106
create mode 100644 hw/arm/fsl-imx7.c
107
create mode 100644 hw/arm/mcimx7d-sabre.c
108
create mode 100644 hw/pci-host/designware.c
109
create mode 100644 hw/sd/sdmmc-internal.c
67
110
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
2
3
The cortex A53 TRM specifies that bits 24 and 25 of the L2CTLR register
4
specify the number of cores in the processor, not the total number of
5
cores in the system. To report this correctly on machines with multiple
6
CPU clusters (ARM's big.LITTLE or Xilinx's ZynqMP) we need to allow
7
the machine to overwrite this value. To do this let's add an optional
8
property.
9
10
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
11
Message-id: ef01d95c0759e88f47f22d11b14c91512a658b4f.1520018138.git.alistair.francis@xilinx.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
target/arm/cpu.h | 5 +++++
16
target/arm/cpu.c | 6 ++++++
17
target/arm/cpu64.c | 6 ++++--
18
3 files changed, 15 insertions(+), 2 deletions(-)
19
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
25
/* Uniprocessor system with MP extensions */
26
bool mp_is_up;
27
28
+ /* Specify the number of cores in this CPU cluster. Used for the L2CTLR
29
+ * register.
30
+ */
31
+ int32_t core_count;
32
+
33
/* The instance init functions for implementation-specific subclasses
34
* set these fields to specify the implementation-dependent values of
35
* various constant registers and reset values of non-constant
36
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/cpu.c
39
+++ b/target/arm/cpu.c
40
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
41
cs->num_ases = 1;
42
}
43
cpu_address_space_init(cs, ARMASIdx_NS, "cpu-memory", cs->memory);
44
+
45
+ /* No core_count specified, default to smp_cpus. */
46
+ if (cpu->core_count == -1) {
47
+ cpu->core_count = smp_cpus;
48
+ }
49
#endif
50
51
qemu_init_vcpu(cs);
52
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_properties[] = {
53
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
54
mp_affinity, ARM64_AFFINITY_INVALID),
55
DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
56
+ DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1),
57
DEFINE_PROP_END_OF_LIST()
58
};
59
60
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/cpu64.c
63
+++ b/target/arm/cpu64.c
64
@@ -XXX,XX +XXX,XX @@ static inline void unset_feature(CPUARMState *env, int feature)
65
#ifndef CONFIG_USER_ONLY
66
static uint64_t a57_a53_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
67
{
68
- /* Number of processors is in [25:24]; otherwise we RAZ */
69
- return (smp_cpus - 1) << 24;
70
+ ARMCPU *cpu = arm_env_get_cpu(env);
71
+
72
+ /* Number of cores is in [25:24]; otherwise we RAZ */
73
+ return (cpu->core_count - 1) << 24;
74
}
75
#endif
76
77
--
78
2.16.2
79
80
diff view generated by jsdifflib
New patch
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
2
3
Set the ARM CPU core count property for the A53's attached to the Xilnx
4
ZynqMP machine.
5
6
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: fe0dd90b85ac73f9fc9548c253bededa70a07006.1520018138.git.alistair.francis@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/xlnx-zynqmp.c | 2 ++
12
1 file changed, 2 insertions(+)
13
14
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/xlnx-zynqmp.c
17
+++ b/hw/arm/xlnx-zynqmp.c
18
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
19
s->virt, "has_el2", NULL);
20
object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
21
"reset-cbar", &error_abort);
22
+ object_property_set_int(OBJECT(&s->apu_cpu[i]), num_apus,
23
+ "core-count", &error_abort);
24
object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
25
&err);
26
if (err) {
27
--
28
2.16.2
29
30
diff view generated by jsdifflib
New patch
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
2
3
Add code needed to get a functional PCI subsytem when using in
4
conjunction with upstream Linux guest (4.13+). Tested to work against
5
"e1000e" (network adapter, using MSI interrupts) as well as
6
"usb-ehci" (USB controller, using legacy PCI interrupts).
7
8
Based on "i.MX6 Applications Processor Reference Manual" (Document
9
Number: IMX6DQRM Rev. 4) as well as corresponding dirver in Linux
10
kernel (circa 4.13 - 4.16 found in drivers/pci/dwc/*)
11
12
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
hw/pci-host/Makefile.objs | 2 +
17
include/hw/pci-host/designware.h | 102 ++++++
18
include/hw/pci/pci_ids.h | 2 +
19
hw/pci-host/designware.c | 754 +++++++++++++++++++++++++++++++++++++++
20
default-configs/arm-softmmu.mak | 1 +
21
5 files changed, 861 insertions(+)
22
create mode 100644 include/hw/pci-host/designware.h
23
create mode 100644 hw/pci-host/designware.c
24
25
diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/pci-host/Makefile.objs
28
+++ b/hw/pci-host/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PCI_PIIX) += piix.o
30
common-obj-$(CONFIG_PCI_Q35) += q35.o
31
common-obj-$(CONFIG_PCI_GENERIC) += gpex.o
32
common-obj-$(CONFIG_PCI_XILINX) += xilinx-pcie.o
33
+
34
+common-obj-$(CONFIG_PCI_DESIGNWARE) += designware.o
35
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/include/hw/pci-host/designware.h
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * Copyright (c) 2017, Impinj, Inc.
43
+ *
44
+ * Designware PCIe IP block emulation
45
+ *
46
+ * This library is free software; you can redistribute it and/or
47
+ * modify it under the terms of the GNU Lesser General Public
48
+ * License as published by the Free Software Foundation; either
49
+ * version 2 of the License, or (at your option) any later version.
50
+ *
51
+ * This library is distributed in the hope that it will be useful,
52
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
53
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
54
+ * Lesser General Public License for more details.
55
+ *
56
+ * You should have received a copy of the GNU Lesser General Public
57
+ * License along with this library; if not, see
58
+ * <http://www.gnu.org/licenses/>.
59
+ */
60
+
61
+#ifndef DESIGNWARE_H
62
+#define DESIGNWARE_H
63
+
64
+#include "hw/hw.h"
65
+#include "hw/sysbus.h"
66
+#include "hw/pci/pci.h"
67
+#include "hw/pci/pci_bus.h"
68
+#include "hw/pci/pcie_host.h"
69
+#include "hw/pci/pci_bridge.h"
70
+
71
+#define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
72
+#define DESIGNWARE_PCIE_HOST(obj) \
73
+ OBJECT_CHECK(DesignwarePCIEHost, (obj), TYPE_DESIGNWARE_PCIE_HOST)
74
+
75
+#define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
76
+#define DESIGNWARE_PCIE_ROOT(obj) \
77
+ OBJECT_CHECK(DesignwarePCIERoot, (obj), TYPE_DESIGNWARE_PCIE_ROOT)
78
+
79
+struct DesignwarePCIERoot;
80
+typedef struct DesignwarePCIERoot DesignwarePCIERoot;
81
+
82
+typedef struct DesignwarePCIEViewport {
83
+ DesignwarePCIERoot *root;
84
+
85
+ MemoryRegion cfg;
86
+ MemoryRegion mem;
87
+
88
+ uint64_t base;
89
+ uint64_t target;
90
+ uint32_t limit;
91
+ uint32_t cr[2];
92
+
93
+ bool inbound;
94
+} DesignwarePCIEViewport;
95
+
96
+typedef struct DesignwarePCIEMSIBank {
97
+ uint32_t enable;
98
+ uint32_t mask;
99
+ uint32_t status;
100
+} DesignwarePCIEMSIBank;
101
+
102
+typedef struct DesignwarePCIEMSI {
103
+ uint64_t base;
104
+ MemoryRegion iomem;
105
+
106
+#define DESIGNWARE_PCIE_NUM_MSI_BANKS 1
107
+
108
+ DesignwarePCIEMSIBank intr[DESIGNWARE_PCIE_NUM_MSI_BANKS];
109
+} DesignwarePCIEMSI;
110
+
111
+struct DesignwarePCIERoot {
112
+ PCIBridge parent_obj;
113
+
114
+ uint32_t atu_viewport;
115
+
116
+#define DESIGNWARE_PCIE_VIEWPORT_OUTBOUND 0
117
+#define DESIGNWARE_PCIE_VIEWPORT_INBOUND 1
118
+#define DESIGNWARE_PCIE_NUM_VIEWPORTS 4
119
+
120
+ DesignwarePCIEViewport viewports[2][DESIGNWARE_PCIE_NUM_VIEWPORTS];
121
+ DesignwarePCIEMSI msi;
122
+};
123
+
124
+typedef struct DesignwarePCIEHost {
125
+ PCIHostState parent_obj;
126
+
127
+ DesignwarePCIERoot root;
128
+
129
+ struct {
130
+ AddressSpace address_space;
131
+ MemoryRegion address_space_root;
132
+
133
+ MemoryRegion memory;
134
+ MemoryRegion io;
135
+
136
+ qemu_irq irqs[4];
137
+ } pci;
138
+
139
+ MemoryRegion mmio;
140
+} DesignwarePCIEHost;
141
+
142
+#endif /* DESIGNWARE_H */
143
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
144
index XXXXXXX..XXXXXXX 100644
145
--- a/include/hw/pci/pci_ids.h
146
+++ b/include/hw/pci/pci_ids.h
147
@@ -XXX,XX +XXX,XX @@
148
#define PCI_VENDOR_ID_VMWARE 0x15ad
149
#define PCI_DEVICE_ID_VMWARE_PVRDMA 0x0820
150
151
+#define PCI_VENDOR_ID_SYNOPSYS 0x16C3
152
+
153
#endif
154
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
155
new file mode 100644
156
index XXXXXXX..XXXXXXX
157
--- /dev/null
158
+++ b/hw/pci-host/designware.c
159
@@ -XXX,XX +XXX,XX @@
160
+/*
161
+ * Copyright (c) 2018, Impinj, Inc.
162
+ *
163
+ * Designware PCIe IP block emulation
164
+ *
165
+ * This library is free software; you can redistribute it and/or
166
+ * modify it under the terms of the GNU Lesser General Public
167
+ * License as published by the Free Software Foundation; either
168
+ * version 2 of the License, or (at your option) any later version.
169
+ *
170
+ * This library is distributed in the hope that it will be useful,
171
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
172
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
173
+ * Lesser General Public License for more details.
174
+ *
175
+ * You should have received a copy of the GNU Lesser General Public
176
+ * License along with this library; if not, see
177
+ * <http://www.gnu.org/licenses/>.
178
+ */
179
+
180
+#include "qemu/osdep.h"
181
+#include "qapi/error.h"
182
+#include "hw/pci/msi.h"
183
+#include "hw/pci/pci_bridge.h"
184
+#include "hw/pci/pci_host.h"
185
+#include "hw/pci/pcie_port.h"
186
+#include "hw/pci-host/designware.h"
187
+
188
+#define DESIGNWARE_PCIE_PORT_LINK_CONTROL 0x710
189
+#define DESIGNWARE_PCIE_PHY_DEBUG_R1 0x72C
190
+#define DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP BIT(4)
191
+#define DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
192
+#define DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE BIT(17)
193
+#define DESIGNWARE_PCIE_MSI_ADDR_LO 0x820
194
+#define DESIGNWARE_PCIE_MSI_ADDR_HI 0x824
195
+#define DESIGNWARE_PCIE_MSI_INTR0_ENABLE 0x828
196
+#define DESIGNWARE_PCIE_MSI_INTR0_MASK 0x82C
197
+#define DESIGNWARE_PCIE_MSI_INTR0_STATUS 0x830
198
+#define DESIGNWARE_PCIE_ATU_VIEWPORT 0x900
199
+#define DESIGNWARE_PCIE_ATU_REGION_INBOUND BIT(31)
200
+#define DESIGNWARE_PCIE_ATU_CR1 0x904
201
+#define DESIGNWARE_PCIE_ATU_TYPE_MEM (0x0 << 0)
202
+#define DESIGNWARE_PCIE_ATU_CR2 0x908
203
+#define DESIGNWARE_PCIE_ATU_ENABLE BIT(31)
204
+#define DESIGNWARE_PCIE_ATU_LOWER_BASE 0x90C
205
+#define DESIGNWARE_PCIE_ATU_UPPER_BASE 0x910
206
+#define DESIGNWARE_PCIE_ATU_LIMIT 0x914
207
+#define DESIGNWARE_PCIE_ATU_LOWER_TARGET 0x918
208
+#define DESIGNWARE_PCIE_ATU_BUS(x) (((x) >> 24) & 0xff)
209
+#define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff)
210
+#define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C
211
+
212
+static DesignwarePCIEHost *
213
+designware_pcie_root_to_host(DesignwarePCIERoot *root)
214
+{
215
+ BusState *bus = qdev_get_parent_bus(DEVICE(root));
216
+ return DESIGNWARE_PCIE_HOST(bus->parent);
217
+}
218
+
219
+static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
220
+ uint64_t val, unsigned len)
221
+{
222
+ DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(opaque);
223
+ DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
224
+
225
+ root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable;
226
+
227
+ if (root->msi.intr[0].status & ~root->msi.intr[0].mask) {
228
+ qemu_set_irq(host->pci.irqs[0], 1);
229
+ }
230
+}
231
+
232
+static const MemoryRegionOps designware_pci_host_msi_ops = {
233
+ .write = designware_pcie_root_msi_write,
234
+ .endianness = DEVICE_LITTLE_ENDIAN,
235
+ .valid = {
236
+ .min_access_size = 4,
237
+ .max_access_size = 4,
238
+ },
239
+};
240
+
241
+static void designware_pcie_root_update_msi_mapping(DesignwarePCIERoot *root)
242
+
243
+{
244
+ MemoryRegion *mem = &root->msi.iomem;
245
+ const uint64_t base = root->msi.base;
246
+ const bool enable = root->msi.intr[0].enable;
247
+
248
+ memory_region_set_address(mem, base);
249
+ memory_region_set_enabled(mem, enable);
250
+}
251
+
252
+static DesignwarePCIEViewport *
253
+designware_pcie_root_get_current_viewport(DesignwarePCIERoot *root)
254
+{
255
+ const unsigned int idx = root->atu_viewport & 0xF;
256
+ const unsigned int dir =
257
+ !!(root->atu_viewport & DESIGNWARE_PCIE_ATU_REGION_INBOUND);
258
+ return &root->viewports[dir][idx];
259
+}
260
+
261
+static uint32_t
262
+designware_pcie_root_config_read(PCIDevice *d, uint32_t address, int len)
263
+{
264
+ DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
265
+ DesignwarePCIEViewport *viewport =
266
+ designware_pcie_root_get_current_viewport(root);
267
+
268
+ uint32_t val;
269
+
270
+ switch (address) {
271
+ case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
272
+ /*
273
+ * Linux guest uses this register only to configure number of
274
+ * PCIE lane (which in our case is irrelevant) and doesn't
275
+ * really care about the value it reads from this register
276
+ */
277
+ val = 0xDEADBEEF;
278
+ break;
279
+
280
+ case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
281
+ /*
282
+ * To make sure that any code in guest waiting for speed
283
+ * change does not time out we always report
284
+ * PORT_LOGIC_SPEED_CHANGE as set
285
+ */
286
+ val = DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE;
287
+ break;
288
+
289
+ case DESIGNWARE_PCIE_MSI_ADDR_LO:
290
+ val = root->msi.base;
291
+ break;
292
+
293
+ case DESIGNWARE_PCIE_MSI_ADDR_HI:
294
+ val = root->msi.base >> 32;
295
+ break;
296
+
297
+ case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
298
+ val = root->msi.intr[0].enable;
299
+ break;
300
+
301
+ case DESIGNWARE_PCIE_MSI_INTR0_MASK:
302
+ val = root->msi.intr[0].mask;
303
+ break;
304
+
305
+ case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
306
+ val = root->msi.intr[0].status;
307
+ break;
308
+
309
+ case DESIGNWARE_PCIE_PHY_DEBUG_R1:
310
+ val = DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
311
+ break;
312
+
313
+ case DESIGNWARE_PCIE_ATU_VIEWPORT:
314
+ val = root->atu_viewport;
315
+ break;
316
+
317
+ case DESIGNWARE_PCIE_ATU_LOWER_BASE:
318
+ val = viewport->base;
319
+ break;
320
+
321
+ case DESIGNWARE_PCIE_ATU_UPPER_BASE:
322
+ val = viewport->base >> 32;
323
+ break;
324
+
325
+ case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
326
+ val = viewport->target;
327
+ break;
328
+
329
+ case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
330
+ val = viewport->target >> 32;
331
+ break;
332
+
333
+ case DESIGNWARE_PCIE_ATU_LIMIT:
334
+ val = viewport->limit;
335
+ break;
336
+
337
+ case DESIGNWARE_PCIE_ATU_CR1:
338
+ case DESIGNWARE_PCIE_ATU_CR2: /* FALLTHROUGH */
339
+ val = viewport->cr[(address - DESIGNWARE_PCIE_ATU_CR1) /
340
+ sizeof(uint32_t)];
341
+ break;
342
+
343
+ default:
344
+ val = pci_default_read_config(d, address, len);
345
+ break;
346
+ }
347
+
348
+ return val;
349
+}
350
+
351
+static uint64_t designware_pcie_root_data_access(void *opaque, hwaddr addr,
352
+ uint64_t *val, unsigned len)
353
+{
354
+ DesignwarePCIEViewport *viewport = opaque;
355
+ DesignwarePCIERoot *root = viewport->root;
356
+
357
+ const uint8_t busnum = DESIGNWARE_PCIE_ATU_BUS(viewport->target);
358
+ const uint8_t devfn = DESIGNWARE_PCIE_ATU_DEVFN(viewport->target);
359
+ PCIBus *pcibus = pci_get_bus(PCI_DEVICE(root));
360
+ PCIDevice *pcidev = pci_find_device(pcibus, busnum, devfn);
361
+
362
+ if (pcidev) {
363
+ addr &= pci_config_size(pcidev) - 1;
364
+
365
+ if (val) {
366
+ pci_host_config_write_common(pcidev, addr,
367
+ pci_config_size(pcidev),
368
+ *val, len);
369
+ } else {
370
+ return pci_host_config_read_common(pcidev, addr,
371
+ pci_config_size(pcidev),
372
+ len);
373
+ }
374
+ }
375
+
376
+ return UINT64_MAX;
377
+}
378
+
379
+static uint64_t designware_pcie_root_data_read(void *opaque, hwaddr addr,
380
+ unsigned len)
381
+{
382
+ return designware_pcie_root_data_access(opaque, addr, NULL, len);
383
+}
384
+
385
+static void designware_pcie_root_data_write(void *opaque, hwaddr addr,
386
+ uint64_t val, unsigned len)
387
+{
388
+ designware_pcie_root_data_access(opaque, addr, &val, len);
389
+}
390
+
391
+static const MemoryRegionOps designware_pci_host_conf_ops = {
392
+ .read = designware_pcie_root_data_read,
393
+ .write = designware_pcie_root_data_write,
394
+ .endianness = DEVICE_LITTLE_ENDIAN,
395
+ .valid = {
396
+ .min_access_size = 1,
397
+ .max_access_size = 4,
398
+ },
399
+};
400
+
401
+static void designware_pcie_update_viewport(DesignwarePCIERoot *root,
402
+ DesignwarePCIEViewport *viewport)
403
+{
404
+ const uint64_t target = viewport->target;
405
+ const uint64_t base = viewport->base;
406
+ const uint64_t size = (uint64_t)viewport->limit - base + 1;
407
+ const bool enabled = viewport->cr[1] & DESIGNWARE_PCIE_ATU_ENABLE;
408
+
409
+ MemoryRegion *current, *other;
410
+
411
+ if (viewport->cr[0] == DESIGNWARE_PCIE_ATU_TYPE_MEM) {
412
+ current = &viewport->mem;
413
+ other = &viewport->cfg;
414
+ memory_region_set_alias_offset(current, target);
415
+ } else {
416
+ current = &viewport->cfg;
417
+ other = &viewport->mem;
418
+ }
419
+
420
+ /*
421
+ * An outbound viewport can be reconfigure from being MEM to CFG,
422
+ * to account for that we disable the "other" memory region that
423
+ * becomes unused due to that fact.
424
+ */
425
+ memory_region_set_enabled(other, false);
426
+ if (enabled) {
427
+ memory_region_set_size(current, size);
428
+ memory_region_set_address(current, base);
429
+ }
430
+ memory_region_set_enabled(current, enabled);
431
+}
432
+
433
+static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
434
+ uint32_t val, int len)
435
+{
436
+ DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
437
+ DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
438
+ DesignwarePCIEViewport *viewport =
439
+ designware_pcie_root_get_current_viewport(root);
440
+
441
+ switch (address) {
442
+ case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
443
+ case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
444
+ case DESIGNWARE_PCIE_PHY_DEBUG_R1:
445
+ /* No-op */
446
+ break;
447
+
448
+ case DESIGNWARE_PCIE_MSI_ADDR_LO:
449
+ root->msi.base &= 0xFFFFFFFF00000000ULL;
450
+ root->msi.base |= val;
451
+ break;
452
+
453
+ case DESIGNWARE_PCIE_MSI_ADDR_HI:
454
+ root->msi.base &= 0x00000000FFFFFFFFULL;
455
+ root->msi.base |= (uint64_t)val << 32;
456
+ break;
457
+
458
+ case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: {
459
+ const bool update_msi_mapping = !root->msi.intr[0].enable ^ !!val;
460
+
461
+ root->msi.intr[0].enable = val;
462
+
463
+ if (update_msi_mapping) {
464
+ designware_pcie_root_update_msi_mapping(root);
465
+ }
466
+ break;
467
+ }
468
+
469
+ case DESIGNWARE_PCIE_MSI_INTR0_MASK:
470
+ root->msi.intr[0].mask = val;
471
+ break;
472
+
473
+ case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
474
+ root->msi.intr[0].status ^= val;
475
+ if (!root->msi.intr[0].status) {
476
+ qemu_set_irq(host->pci.irqs[0], 0);
477
+ }
478
+ break;
479
+
480
+ case DESIGNWARE_PCIE_ATU_VIEWPORT:
481
+ root->atu_viewport = val;
482
+ break;
483
+
484
+ case DESIGNWARE_PCIE_ATU_LOWER_BASE:
485
+ viewport->base &= 0xFFFFFFFF00000000ULL;
486
+ viewport->base |= val;
487
+ break;
488
+
489
+ case DESIGNWARE_PCIE_ATU_UPPER_BASE:
490
+ viewport->base &= 0x00000000FFFFFFFFULL;
491
+ viewport->base |= (uint64_t)val << 32;
492
+ break;
493
+
494
+ case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
495
+ viewport->target &= 0xFFFFFFFF00000000ULL;
496
+ viewport->target |= val;
497
+ break;
498
+
499
+ case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
500
+ viewport->target &= 0x00000000FFFFFFFFULL;
501
+ viewport->target |= val;
502
+ break;
503
+
504
+ case DESIGNWARE_PCIE_ATU_LIMIT:
505
+ viewport->limit = val;
506
+ break;
507
+
508
+ case DESIGNWARE_PCIE_ATU_CR1:
509
+ viewport->cr[0] = val;
510
+ break;
511
+ case DESIGNWARE_PCIE_ATU_CR2:
512
+ viewport->cr[1] = val;
513
+ designware_pcie_update_viewport(root, viewport);
514
+ break;
515
+
516
+ default:
517
+ pci_bridge_write_config(d, address, val, len);
518
+ break;
519
+ }
520
+}
521
+
522
+static char *designware_pcie_viewport_name(const char *direction,
523
+ unsigned int i,
524
+ const char *type)
525
+{
526
+ return g_strdup_printf("PCI %s Viewport %u [%s]",
527
+ direction, i, type);
528
+}
529
+
530
+static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
531
+{
532
+ DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(dev);
533
+ DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
534
+ MemoryRegion *address_space = &host->pci.memory;
535
+ PCIBridge *br = PCI_BRIDGE(dev);
536
+ DesignwarePCIEViewport *viewport;
537
+ /*
538
+ * Dummy values used for initial configuration of MemoryRegions
539
+ * that belong to a given viewport
540
+ */
541
+ const hwaddr dummy_offset = 0;
542
+ const uint64_t dummy_size = 4;
543
+ size_t i;
544
+
545
+ br->bus_name = "dw-pcie";
546
+
547
+ pci_set_word(dev->config + PCI_COMMAND,
548
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
549
+
550
+ pci_config_set_interrupt_pin(dev->config, 1);
551
+ pci_bridge_initfn(dev, TYPE_PCIE_BUS);
552
+
553
+ pcie_port_init_reg(dev);
554
+
555
+ pcie_cap_init(dev, 0x70, PCI_EXP_TYPE_ROOT_PORT,
556
+ 0, &error_fatal);
557
+
558
+ msi_nonbroken = true;
559
+ msi_init(dev, 0x50, 32, true, true, &error_fatal);
560
+
561
+ for (i = 0; i < DESIGNWARE_PCIE_NUM_VIEWPORTS; i++) {
562
+ MemoryRegion *source, *destination, *mem;
563
+ const char *direction;
564
+ char *name;
565
+
566
+ viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][i];
567
+ viewport->inbound = true;
568
+ viewport->base = 0x0000000000000000ULL;
569
+ viewport->target = 0x0000000000000000ULL;
570
+ viewport->limit = UINT32_MAX;
571
+ viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM;
572
+
573
+ source = &host->pci.address_space_root;
574
+ destination = get_system_memory();
575
+ direction = "Inbound";
576
+
577
+ /*
578
+ * Configure MemoryRegion implementing PCI -> CPU memory
579
+ * access
580
+ */
581
+ mem = &viewport->mem;
582
+ name = designware_pcie_viewport_name(direction, i, "MEM");
583
+ memory_region_init_alias(mem, OBJECT(root), name, destination,
584
+ dummy_offset, dummy_size);
585
+ memory_region_add_subregion_overlap(source, dummy_offset, mem, -1);
586
+ memory_region_set_enabled(mem, false);
587
+ g_free(name);
588
+
589
+ viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_OUTBOUND][i];
590
+ viewport->root = root;
591
+ viewport->inbound = false;
592
+ viewport->base = 0x0000000000000000ULL;
593
+ viewport->target = 0x0000000000000000ULL;
594
+ viewport->limit = UINT32_MAX;
595
+ viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM;
596
+
597
+ destination = &host->pci.memory;
598
+ direction = "Outbound";
599
+ source = get_system_memory();
600
+
601
+ /*
602
+ * Configure MemoryRegion implementing CPU -> PCI memory
603
+ * access
604
+ */
605
+ mem = &viewport->mem;
606
+ name = designware_pcie_viewport_name(direction, i, "MEM");
607
+ memory_region_init_alias(mem, OBJECT(root), name, destination,
608
+ dummy_offset, dummy_size);
609
+ memory_region_add_subregion(source, dummy_offset, mem);
610
+ memory_region_set_enabled(mem, false);
611
+ g_free(name);
612
+
613
+ /*
614
+ * Configure MemoryRegion implementing access to configuration
615
+ * space
616
+ */
617
+ mem = &viewport->cfg;
618
+ name = designware_pcie_viewport_name(direction, i, "CFG");
619
+ memory_region_init_io(&viewport->cfg, OBJECT(root),
620
+ &designware_pci_host_conf_ops,
621
+ viewport, name, dummy_size);
622
+ memory_region_add_subregion(source, dummy_offset, mem);
623
+ memory_region_set_enabled(mem, false);
624
+ g_free(name);
625
+ }
626
+
627
+ /*
628
+ * If no inbound iATU windows are configured, HW defaults to
629
+ * letting inbound TLPs to pass in. We emulate that by exlicitly
630
+ * configuring first inbound window to cover all of target's
631
+ * address space.
632
+ *
633
+ * NOTE: This will not work correctly for the case when first
634
+ * configured inbound window is window 0
635
+ */
636
+ viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][0];
637
+ viewport->cr[1] = DESIGNWARE_PCIE_ATU_ENABLE;
638
+ designware_pcie_update_viewport(root, viewport);
639
+
640
+ memory_region_init_io(&root->msi.iomem, OBJECT(root),
641
+ &designware_pci_host_msi_ops,
642
+ root, "pcie-msi", 0x4);
643
+ /*
644
+ * We initially place MSI interrupt I/O region a adress 0 and
645
+ * disable it. It'll be later moved to correct offset and enabled
646
+ * in designware_pcie_root_update_msi_mapping() as a part of
647
+ * initialization done by guest OS
648
+ */
649
+ memory_region_add_subregion(address_space, dummy_offset, &root->msi.iomem);
650
+ memory_region_set_enabled(&root->msi.iomem, false);
651
+}
652
+
653
+static void designware_pcie_set_irq(void *opaque, int irq_num, int level)
654
+{
655
+ DesignwarePCIEHost *host = DESIGNWARE_PCIE_HOST(opaque);
656
+
657
+ qemu_set_irq(host->pci.irqs[irq_num], level);
658
+}
659
+
660
+static const char *
661
+designware_pcie_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus)
662
+{
663
+ return "0000:00";
664
+}
665
+
666
+static const VMStateDescription vmstate_designware_pcie_msi_bank = {
667
+ .name = "designware-pcie-msi-bank",
668
+ .version_id = 1,
669
+ .minimum_version_id = 1,
670
+ .fields = (VMStateField[]) {
671
+ VMSTATE_UINT32(enable, DesignwarePCIEMSIBank),
672
+ VMSTATE_UINT32(mask, DesignwarePCIEMSIBank),
673
+ VMSTATE_UINT32(status, DesignwarePCIEMSIBank),
674
+ VMSTATE_END_OF_LIST()
675
+ }
676
+};
677
+
678
+static const VMStateDescription vmstate_designware_pcie_msi = {
679
+ .name = "designware-pcie-msi",
680
+ .version_id = 1,
681
+ .minimum_version_id = 1,
682
+ .fields = (VMStateField[]) {
683
+ VMSTATE_UINT64(base, DesignwarePCIEMSI),
684
+ VMSTATE_STRUCT_ARRAY(intr,
685
+ DesignwarePCIEMSI,
686
+ DESIGNWARE_PCIE_NUM_MSI_BANKS,
687
+ 1,
688
+ vmstate_designware_pcie_msi_bank,
689
+ DesignwarePCIEMSIBank),
690
+ VMSTATE_END_OF_LIST()
691
+ }
692
+};
693
+
694
+static const VMStateDescription vmstate_designware_pcie_viewport = {
695
+ .name = "designware-pcie-viewport",
696
+ .version_id = 1,
697
+ .minimum_version_id = 1,
698
+ .fields = (VMStateField[]) {
699
+ VMSTATE_UINT64(base, DesignwarePCIEViewport),
700
+ VMSTATE_UINT64(target, DesignwarePCIEViewport),
701
+ VMSTATE_UINT32(limit, DesignwarePCIEViewport),
702
+ VMSTATE_UINT32_ARRAY(cr, DesignwarePCIEViewport, 2),
703
+ VMSTATE_END_OF_LIST()
704
+ }
705
+};
706
+
707
+static const VMStateDescription vmstate_designware_pcie_root = {
708
+ .name = "designware-pcie-root",
709
+ .version_id = 1,
710
+ .minimum_version_id = 1,
711
+ .fields = (VMStateField[]) {
712
+ VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
713
+ VMSTATE_UINT32(atu_viewport, DesignwarePCIERoot),
714
+ VMSTATE_STRUCT_2DARRAY(viewports,
715
+ DesignwarePCIERoot,
716
+ 2,
717
+ DESIGNWARE_PCIE_NUM_VIEWPORTS,
718
+ 1,
719
+ vmstate_designware_pcie_viewport,
720
+ DesignwarePCIEViewport),
721
+ VMSTATE_STRUCT(msi,
722
+ DesignwarePCIERoot,
723
+ 1,
724
+ vmstate_designware_pcie_msi,
725
+ DesignwarePCIEMSI),
726
+ VMSTATE_END_OF_LIST()
727
+ }
728
+};
729
+
730
+static void designware_pcie_root_class_init(ObjectClass *klass, void *data)
731
+{
732
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
733
+ DeviceClass *dc = DEVICE_CLASS(klass);
734
+
735
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
736
+
737
+ k->vendor_id = PCI_VENDOR_ID_SYNOPSYS;
738
+ k->device_id = 0xABCD;
739
+ k->revision = 0;
740
+ k->class_id = PCI_CLASS_BRIDGE_PCI;
741
+ k->is_bridge = true;
742
+ k->exit = pci_bridge_exitfn;
743
+ k->realize = designware_pcie_root_realize;
744
+ k->config_read = designware_pcie_root_config_read;
745
+ k->config_write = designware_pcie_root_config_write;
746
+
747
+ dc->reset = pci_bridge_reset;
748
+ /*
749
+ * PCI-facing part of the host bridge, not usable without the
750
+ * host-facing part, which can't be device_add'ed, yet.
751
+ */
752
+ dc->user_creatable = false;
753
+ dc->vmsd = &vmstate_designware_pcie_root;
754
+}
755
+
756
+static uint64_t designware_pcie_host_mmio_read(void *opaque, hwaddr addr,
757
+ unsigned int size)
758
+{
759
+ PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
760
+ PCIDevice *device = pci_find_device(pci->bus, 0, 0);
761
+
762
+ return pci_host_config_read_common(device,
763
+ addr,
764
+ pci_config_size(device),
765
+ size);
766
+}
767
+
768
+static void designware_pcie_host_mmio_write(void *opaque, hwaddr addr,
769
+ uint64_t val, unsigned int size)
770
+{
771
+ PCIHostState *pci = PCI_HOST_BRIDGE(opaque);
772
+ PCIDevice *device = pci_find_device(pci->bus, 0, 0);
773
+
774
+ return pci_host_config_write_common(device,
775
+ addr,
776
+ pci_config_size(device),
777
+ val, size);
778
+}
779
+
780
+static const MemoryRegionOps designware_pci_mmio_ops = {
781
+ .read = designware_pcie_host_mmio_read,
782
+ .write = designware_pcie_host_mmio_write,
783
+ .endianness = DEVICE_LITTLE_ENDIAN,
784
+ .impl = {
785
+ /*
786
+ * Our device would not work correctly if the guest was doing
787
+ * unaligned access. This might not be a limitation on the real
788
+ * device but in practice there is no reason for a guest to access
789
+ * this device unaligned.
790
+ */
791
+ .min_access_size = 4,
792
+ .max_access_size = 4,
793
+ .unaligned = false,
794
+ },
795
+};
796
+
797
+static AddressSpace *designware_pcie_host_set_iommu(PCIBus *bus, void *opaque,
798
+ int devfn)
799
+{
800
+ DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(opaque);
801
+
802
+ return &s->pci.address_space;
803
+}
804
+
805
+static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
806
+{
807
+ PCIHostState *pci = PCI_HOST_BRIDGE(dev);
808
+ DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(dev);
809
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
810
+ size_t i;
811
+
812
+ for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) {
813
+ sysbus_init_irq(sbd, &s->pci.irqs[i]);
814
+ }
815
+
816
+ memory_region_init_io(&s->mmio,
817
+ OBJECT(s),
818
+ &designware_pci_mmio_ops,
819
+ s,
820
+ "pcie.reg", 4 * 1024);
821
+ sysbus_init_mmio(sbd, &s->mmio);
822
+
823
+ memory_region_init(&s->pci.io, OBJECT(s), "pcie-pio", 16);
824
+ memory_region_init(&s->pci.memory, OBJECT(s),
825
+ "pcie-bus-memory",
826
+ UINT64_MAX);
827
+
828
+ pci->bus = pci_register_root_bus(dev, "pcie",
829
+ designware_pcie_set_irq,
830
+ pci_swizzle_map_irq_fn,
831
+ s,
832
+ &s->pci.memory,
833
+ &s->pci.io,
834
+ 0, 4,
835
+ TYPE_PCIE_BUS);
836
+
837
+ memory_region_init(&s->pci.address_space_root,
838
+ OBJECT(s),
839
+ "pcie-bus-address-space-root",
840
+ UINT64_MAX);
841
+ memory_region_add_subregion(&s->pci.address_space_root,
842
+ 0x0, &s->pci.memory);
843
+ address_space_init(&s->pci.address_space,
844
+ &s->pci.address_space_root,
845
+ "pcie-bus-address-space");
846
+ pci_setup_iommu(pci->bus, designware_pcie_host_set_iommu, s);
847
+
848
+ qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus));
849
+ qdev_init_nofail(DEVICE(&s->root));
850
+}
851
+
852
+static const VMStateDescription vmstate_designware_pcie_host = {
853
+ .name = "designware-pcie-host",
854
+ .version_id = 1,
855
+ .minimum_version_id = 1,
856
+ .fields = (VMStateField[]) {
857
+ VMSTATE_STRUCT(root,
858
+ DesignwarePCIEHost,
859
+ 1,
860
+ vmstate_designware_pcie_root,
861
+ DesignwarePCIERoot),
862
+ VMSTATE_END_OF_LIST()
863
+ }
864
+};
865
+
866
+static void designware_pcie_host_class_init(ObjectClass *klass, void *data)
867
+{
868
+ DeviceClass *dc = DEVICE_CLASS(klass);
869
+ PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
870
+
871
+ hc->root_bus_path = designware_pcie_host_root_bus_path;
872
+ dc->realize = designware_pcie_host_realize;
873
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
874
+ dc->fw_name = "pci";
875
+ dc->vmsd = &vmstate_designware_pcie_host;
876
+}
877
+
878
+static void designware_pcie_host_init(Object *obj)
879
+{
880
+ DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(obj);
881
+ DesignwarePCIERoot *root = &s->root;
882
+
883
+ object_initialize(root, sizeof(*root), TYPE_DESIGNWARE_PCIE_ROOT);
884
+ object_property_add_child(obj, "root", OBJECT(root), NULL);
885
+ qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
886
+ qdev_prop_set_bit(DEVICE(root), "multifunction", false);
887
+}
888
+
889
+static const TypeInfo designware_pcie_root_info = {
890
+ .name = TYPE_DESIGNWARE_PCIE_ROOT,
891
+ .parent = TYPE_PCI_BRIDGE,
892
+ .instance_size = sizeof(DesignwarePCIERoot),
893
+ .class_init = designware_pcie_root_class_init,
894
+ .interfaces = (InterfaceInfo[]) {
895
+ { INTERFACE_PCIE_DEVICE },
896
+ { }
897
+ },
898
+};
899
+
900
+static const TypeInfo designware_pcie_host_info = {
901
+ .name = TYPE_DESIGNWARE_PCIE_HOST,
902
+ .parent = TYPE_PCI_HOST_BRIDGE,
903
+ .instance_size = sizeof(DesignwarePCIEHost),
904
+ .instance_init = designware_pcie_host_init,
905
+ .class_init = designware_pcie_host_class_init,
906
+};
907
+
908
+static void designware_pcie_register(void)
909
+{
910
+ type_register_static(&designware_pcie_root_info);
911
+ type_register_static(&designware_pcie_host_info);
912
+}
913
+type_init(designware_pcie_register)
914
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
915
index XXXXXXX..XXXXXXX 100644
916
--- a/default-configs/arm-softmmu.mak
917
+++ b/default-configs/arm-softmmu.mak
918
@@ -XXX,XX +XXX,XX @@ CONFIG_GPIO_KEY=y
919
CONFIG_MSF2=y
920
CONFIG_FW_CFG_DMA=y
921
CONFIG_XILINX_AXI=y
922
+CONFIG_PCI_DESIGNWARE=y
923
--
924
2.16.2
925
926
diff view generated by jsdifflib
New patch
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
2
3
The following interfaces are partially or fully emulated:
4
5
* up to 2 Cortex A9 cores (SMP works with PSCI)
6
* A7 MPCORE (identical to A15 MPCORE)
7
* 4 GPTs modules
8
* 7 GPIO controllers
9
* 2 IOMUXC controllers
10
* 1 CCM module
11
* 1 SVNS module
12
* 1 SRC module
13
* 1 GPCv2 controller
14
* 4 eCSPI controllers
15
* 4 I2C controllers
16
* 7 i.MX UART controllers
17
* 2 FlexCAN controllers
18
* 2 Ethernet controllers (FEC)
19
* 3 SD controllers (USDHC)
20
* 4 WDT modules
21
* 1 SDMA module
22
* 1 GPR module
23
* 2 USBMISC modules
24
* 2 ADC modules
25
* 1 PCIe controller
26
27
Tested to boot and work with upstream Linux (4.13+) guest.
28
29
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
31
[PMM: folded a couple of long lines]
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
---
34
hw/arm/Makefile.objs | 1 +
35
include/hw/arm/fsl-imx7.h | 222 +++++++++++++++
36
hw/arm/fsl-imx7.c | 582 ++++++++++++++++++++++++++++++++++++++++
37
default-configs/arm-softmmu.mak | 1 +
38
4 files changed, 806 insertions(+)
39
create mode 100644 include/hw/arm/fsl-imx7.h
40
create mode 100644 hw/arm/fsl-imx7.c
41
42
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/Makefile.objs
45
+++ b/hw/arm/Makefile.objs
46
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2) += mps2.o
47
obj-$(CONFIG_MPS2) += mps2-tz.o
48
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
49
obj-$(CONFIG_IOTKIT) += iotkit.o
50
+obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
51
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
52
new file mode 100644
53
index XXXXXXX..XXXXXXX
54
--- /dev/null
55
+++ b/include/hw/arm/fsl-imx7.h
56
@@ -XXX,XX +XXX,XX @@
57
+/*
58
+ * Copyright (c) 2018, Impinj, Inc.
59
+ *
60
+ * i.MX7 SoC definitions
61
+ *
62
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
63
+ *
64
+ * This program is free software; you can redistribute it and/or modify
65
+ * it under the terms of the GNU General Public License as published by
66
+ * the Free Software Foundation; either version 2 of the License, or
67
+ * (at your option) any later version.
68
+ *
69
+ * This program is distributed in the hope that it will be useful,
70
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
71
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72
+ * GNU General Public License for more details.
73
+ */
74
+
75
+#ifndef FSL_IMX7_H
76
+#define FSL_IMX7_H
77
+
78
+#include "hw/arm/arm.h"
79
+#include "hw/cpu/a15mpcore.h"
80
+#include "hw/intc/imx_gpcv2.h"
81
+#include "hw/misc/imx7_ccm.h"
82
+#include "hw/misc/imx7_snvs.h"
83
+#include "hw/misc/imx7_gpr.h"
84
+#include "hw/misc/imx6_src.h"
85
+#include "hw/misc/imx2_wdt.h"
86
+#include "hw/gpio/imx_gpio.h"
87
+#include "hw/char/imx_serial.h"
88
+#include "hw/timer/imx_gpt.h"
89
+#include "hw/timer/imx_epit.h"
90
+#include "hw/i2c/imx_i2c.h"
91
+#include "hw/gpio/imx_gpio.h"
92
+#include "hw/sd/sdhci.h"
93
+#include "hw/ssi/imx_spi.h"
94
+#include "hw/net/imx_fec.h"
95
+#include "hw/pci-host/designware.h"
96
+#include "hw/usb/chipidea.h"
97
+#include "exec/memory.h"
98
+#include "cpu.h"
99
+
100
+#define TYPE_FSL_IMX7 "fsl,imx7"
101
+#define FSL_IMX7(obj) OBJECT_CHECK(FslIMX7State, (obj), TYPE_FSL_IMX7)
102
+
103
+enum FslIMX7Configuration {
104
+ FSL_IMX7_NUM_CPUS = 2,
105
+ FSL_IMX7_NUM_UARTS = 7,
106
+ FSL_IMX7_NUM_ETHS = 2,
107
+ FSL_IMX7_ETH_NUM_TX_RINGS = 3,
108
+ FSL_IMX7_NUM_USDHCS = 3,
109
+ FSL_IMX7_NUM_WDTS = 4,
110
+ FSL_IMX7_NUM_GPTS = 4,
111
+ FSL_IMX7_NUM_IOMUXCS = 2,
112
+ FSL_IMX7_NUM_GPIOS = 7,
113
+ FSL_IMX7_NUM_I2CS = 4,
114
+ FSL_IMX7_NUM_ECSPIS = 4,
115
+ FSL_IMX7_NUM_USBS = 3,
116
+ FSL_IMX7_NUM_ADCS = 2,
117
+};
118
+
119
+typedef struct FslIMX7State {
120
+ /*< private >*/
121
+ DeviceState parent_obj;
122
+
123
+ /*< public >*/
124
+ ARMCPU cpu[FSL_IMX7_NUM_CPUS];
125
+ A15MPPrivState a7mpcore;
126
+ IMXGPTState gpt[FSL_IMX7_NUM_GPTS];
127
+ IMXGPIOState gpio[FSL_IMX7_NUM_GPIOS];
128
+ IMX7CCMState ccm;
129
+ IMX7AnalogState analog;
130
+ IMX7SNVSState snvs;
131
+ IMXGPCv2State gpcv2;
132
+ IMXSPIState spi[FSL_IMX7_NUM_ECSPIS];
133
+ IMXI2CState i2c[FSL_IMX7_NUM_I2CS];
134
+ IMXSerialState uart[FSL_IMX7_NUM_UARTS];
135
+ IMXFECState eth[FSL_IMX7_NUM_ETHS];
136
+ SDHCIState usdhc[FSL_IMX7_NUM_USDHCS];
137
+ IMX2WdtState wdt[FSL_IMX7_NUM_WDTS];
138
+ IMX7GPRState gpr;
139
+ ChipideaState usb[FSL_IMX7_NUM_USBS];
140
+ DesignwarePCIEHost pcie;
141
+} FslIMX7State;
142
+
143
+enum FslIMX7MemoryMap {
144
+ FSL_IMX7_MMDC_ADDR = 0x80000000,
145
+ FSL_IMX7_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
146
+
147
+ FSL_IMX7_GPIO1_ADDR = 0x30200000,
148
+ FSL_IMX7_GPIO2_ADDR = 0x30210000,
149
+ FSL_IMX7_GPIO3_ADDR = 0x30220000,
150
+ FSL_IMX7_GPIO4_ADDR = 0x30230000,
151
+ FSL_IMX7_GPIO5_ADDR = 0x30240000,
152
+ FSL_IMX7_GPIO6_ADDR = 0x30250000,
153
+ FSL_IMX7_GPIO7_ADDR = 0x30260000,
154
+
155
+ FSL_IMX7_IOMUXC_LPSR_GPR_ADDR = 0x30270000,
156
+
157
+ FSL_IMX7_WDOG1_ADDR = 0x30280000,
158
+ FSL_IMX7_WDOG2_ADDR = 0x30290000,
159
+ FSL_IMX7_WDOG3_ADDR = 0x302A0000,
160
+ FSL_IMX7_WDOG4_ADDR = 0x302B0000,
161
+
162
+ FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000,
163
+
164
+ FSL_IMX7_GPT1_ADDR = 0x302D0000,
165
+ FSL_IMX7_GPT2_ADDR = 0x302E0000,
166
+ FSL_IMX7_GPT3_ADDR = 0x302F0000,
167
+ FSL_IMX7_GPT4_ADDR = 0x30300000,
168
+
169
+ FSL_IMX7_IOMUXC_ADDR = 0x30330000,
170
+ FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
171
+ FSL_IMX7_IOMUXCn_SIZE = 0x1000,
172
+
173
+ FSL_IMX7_ANALOG_ADDR = 0x30360000,
174
+ FSL_IMX7_SNVS_ADDR = 0x30370000,
175
+ FSL_IMX7_CCM_ADDR = 0x30380000,
176
+
177
+ FSL_IMX7_SRC_ADDR = 0x30390000,
178
+ FSL_IMX7_SRC_SIZE = 0x1000,
179
+
180
+ FSL_IMX7_ADC1_ADDR = 0x30610000,
181
+ FSL_IMX7_ADC2_ADDR = 0x30620000,
182
+ FSL_IMX7_ADCn_SIZE = 0x1000,
183
+
184
+ FSL_IMX7_GPC_ADDR = 0x303A0000,
185
+
186
+ FSL_IMX7_I2C1_ADDR = 0x30A20000,
187
+ FSL_IMX7_I2C2_ADDR = 0x30A30000,
188
+ FSL_IMX7_I2C3_ADDR = 0x30A40000,
189
+ FSL_IMX7_I2C4_ADDR = 0x30A50000,
190
+
191
+ FSL_IMX7_ECSPI1_ADDR = 0x30820000,
192
+ FSL_IMX7_ECSPI2_ADDR = 0x30830000,
193
+ FSL_IMX7_ECSPI3_ADDR = 0x30840000,
194
+ FSL_IMX7_ECSPI4_ADDR = 0x30630000,
195
+
196
+ FSL_IMX7_LCDIF_ADDR = 0x30730000,
197
+ FSL_IMX7_LCDIF_SIZE = 0x1000,
198
+
199
+ FSL_IMX7_UART1_ADDR = 0x30860000,
200
+ /*
201
+ * Some versions of the reference manual claim that UART2 is @
202
+ * 0x30870000, but experiments with HW + DT files in upstream
203
+ * Linux kernel show that not to be true and that block is
204
+ * acutally located @ 0x30890000
205
+ */
206
+ FSL_IMX7_UART2_ADDR = 0x30890000,
207
+ FSL_IMX7_UART3_ADDR = 0x30880000,
208
+ FSL_IMX7_UART4_ADDR = 0x30A60000,
209
+ FSL_IMX7_UART5_ADDR = 0x30A70000,
210
+ FSL_IMX7_UART6_ADDR = 0x30A80000,
211
+ FSL_IMX7_UART7_ADDR = 0x30A90000,
212
+
213
+ FSL_IMX7_ENET1_ADDR = 0x30BE0000,
214
+ FSL_IMX7_ENET2_ADDR = 0x30BF0000,
215
+
216
+ FSL_IMX7_USB1_ADDR = 0x30B10000,
217
+ FSL_IMX7_USBMISC1_ADDR = 0x30B10200,
218
+ FSL_IMX7_USB2_ADDR = 0x30B20000,
219
+ FSL_IMX7_USBMISC2_ADDR = 0x30B20200,
220
+ FSL_IMX7_USB3_ADDR = 0x30B30000,
221
+ FSL_IMX7_USBMISC3_ADDR = 0x30B30200,
222
+ FSL_IMX7_USBMISCn_SIZE = 0x200,
223
+
224
+ FSL_IMX7_USDHC1_ADDR = 0x30B40000,
225
+ FSL_IMX7_USDHC2_ADDR = 0x30B50000,
226
+ FSL_IMX7_USDHC3_ADDR = 0x30B60000,
227
+
228
+ FSL_IMX7_SDMA_ADDR = 0x30BD0000,
229
+ FSL_IMX7_SDMA_SIZE = 0x1000,
230
+
231
+ FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
232
+ FSL_IMX7_A7MPCORE_DAP_ADDR = 0x30000000,
233
+
234
+ FSL_IMX7_PCIE_REG_ADDR = 0x33800000,
235
+ FSL_IMX7_PCIE_REG_SIZE = 16 * 1024,
236
+
237
+ FSL_IMX7_GPR_ADDR = 0x30340000,
238
+};
239
+
240
+enum FslIMX7IRQs {
241
+ FSL_IMX7_USDHC1_IRQ = 22,
242
+ FSL_IMX7_USDHC2_IRQ = 23,
243
+ FSL_IMX7_USDHC3_IRQ = 24,
244
+
245
+ FSL_IMX7_UART1_IRQ = 26,
246
+ FSL_IMX7_UART2_IRQ = 27,
247
+ FSL_IMX7_UART3_IRQ = 28,
248
+ FSL_IMX7_UART4_IRQ = 29,
249
+ FSL_IMX7_UART5_IRQ = 30,
250
+ FSL_IMX7_UART6_IRQ = 16,
251
+
252
+ FSL_IMX7_ECSPI1_IRQ = 31,
253
+ FSL_IMX7_ECSPI2_IRQ = 32,
254
+ FSL_IMX7_ECSPI3_IRQ = 33,
255
+ FSL_IMX7_ECSPI4_IRQ = 34,
256
+
257
+ FSL_IMX7_I2C1_IRQ = 35,
258
+ FSL_IMX7_I2C2_IRQ = 36,
259
+ FSL_IMX7_I2C3_IRQ = 37,
260
+ FSL_IMX7_I2C4_IRQ = 38,
261
+
262
+ FSL_IMX7_USB1_IRQ = 43,
263
+ FSL_IMX7_USB2_IRQ = 42,
264
+ FSL_IMX7_USB3_IRQ = 40,
265
+
266
+ FSL_IMX7_PCI_INTA_IRQ = 122,
267
+ FSL_IMX7_PCI_INTB_IRQ = 123,
268
+ FSL_IMX7_PCI_INTC_IRQ = 124,
269
+ FSL_IMX7_PCI_INTD_IRQ = 125,
270
+
271
+ FSL_IMX7_UART7_IRQ = 126,
272
+
273
+#define FSL_IMX7_ENET_IRQ(i, n) ((n) + ((i) ? 100 : 118))
274
+
275
+ FSL_IMX7_MAX_IRQ = 128,
276
+};
277
+
278
+#endif /* FSL_IMX7_H */
279
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
280
new file mode 100644
281
index XXXXXXX..XXXXXXX
282
--- /dev/null
283
+++ b/hw/arm/fsl-imx7.c
284
@@ -XXX,XX +XXX,XX @@
285
+/*
286
+ * Copyright (c) 2018, Impinj, Inc.
287
+ *
288
+ * i.MX7 SoC definitions
289
+ *
290
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
291
+ *
292
+ * Based on hw/arm/fsl-imx6.c
293
+ *
294
+ * This program is free software; you can redistribute it and/or modify
295
+ * it under the terms of the GNU General Public License as published by
296
+ * the Free Software Foundation; either version 2 of the License, or
297
+ * (at your option) any later version.
298
+ *
299
+ * This program is distributed in the hope that it will be useful,
300
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
301
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
302
+ * GNU General Public License for more details.
303
+ */
304
+
305
+#include "qemu/osdep.h"
306
+#include "qapi/error.h"
307
+#include "qemu-common.h"
308
+#include "hw/arm/fsl-imx7.h"
309
+#include "hw/misc/unimp.h"
310
+#include "sysemu/sysemu.h"
311
+#include "qemu/error-report.h"
312
+
313
+#define NAME_SIZE 20
314
+
315
+static void fsl_imx7_init(Object *obj)
316
+{
317
+ BusState *sysbus = sysbus_get_default();
318
+ FslIMX7State *s = FSL_IMX7(obj);
319
+ char name[NAME_SIZE];
320
+ int i;
321
+
322
+ if (smp_cpus > FSL_IMX7_NUM_CPUS) {
323
+ error_report("%s: Only %d CPUs are supported (%d requested)",
324
+ TYPE_FSL_IMX7, FSL_IMX7_NUM_CPUS, smp_cpus);
325
+ exit(1);
326
+ }
327
+
328
+ for (i = 0; i < smp_cpus; i++) {
329
+ object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
330
+ ARM_CPU_TYPE_NAME("cortex-a7"));
331
+ snprintf(name, NAME_SIZE, "cpu%d", i);
332
+ object_property_add_child(obj, name, OBJECT(&s->cpu[i]),
333
+ &error_fatal);
334
+ }
335
+
336
+ /*
337
+ * A7MPCORE
338
+ */
339
+ object_initialize(&s->a7mpcore, sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV);
340
+ qdev_set_parent_bus(DEVICE(&s->a7mpcore), sysbus);
341
+ object_property_add_child(obj, "a7mpcore",
342
+ OBJECT(&s->a7mpcore), &error_fatal);
343
+
344
+ /*
345
+ * GPIOs 1 to 7
346
+ */
347
+ for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
348
+ object_initialize(&s->gpio[i], sizeof(s->gpio[i]),
349
+ TYPE_IMX_GPIO);
350
+ qdev_set_parent_bus(DEVICE(&s->gpio[i]), sysbus);
351
+ snprintf(name, NAME_SIZE, "gpio%d", i);
352
+ object_property_add_child(obj, name,
353
+ OBJECT(&s->gpio[i]), &error_fatal);
354
+ }
355
+
356
+ /*
357
+ * GPT1, 2, 3, 4
358
+ */
359
+ for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
360
+ object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX7_GPT);
361
+ qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus);
362
+ snprintf(name, NAME_SIZE, "gpt%d", i);
363
+ object_property_add_child(obj, name, OBJECT(&s->gpt[i]),
364
+ &error_fatal);
365
+ }
366
+
367
+ /*
368
+ * CCM
369
+ */
370
+ object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX7_CCM);
371
+ qdev_set_parent_bus(DEVICE(&s->ccm), sysbus);
372
+ object_property_add_child(obj, "ccm", OBJECT(&s->ccm), &error_fatal);
373
+
374
+ /*
375
+ * Analog
376
+ */
377
+ object_initialize(&s->analog, sizeof(s->analog), TYPE_IMX7_ANALOG);
378
+ qdev_set_parent_bus(DEVICE(&s->analog), sysbus);
379
+ object_property_add_child(obj, "analog", OBJECT(&s->analog), &error_fatal);
380
+
381
+ /*
382
+ * GPCv2
383
+ */
384
+ object_initialize(&s->gpcv2, sizeof(s->gpcv2), TYPE_IMX_GPCV2);
385
+ qdev_set_parent_bus(DEVICE(&s->gpcv2), sysbus);
386
+ object_property_add_child(obj, "gpcv2", OBJECT(&s->gpcv2), &error_fatal);
387
+
388
+ for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
389
+ object_initialize(&s->spi[i], sizeof(s->spi[i]), TYPE_IMX_SPI);
390
+ qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
391
+ snprintf(name, NAME_SIZE, "spi%d", i + 1);
392
+ object_property_add_child(obj, name, OBJECT(&s->spi[i]), NULL);
393
+ }
394
+
395
+
396
+ for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
397
+ object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
398
+ qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
399
+ snprintf(name, NAME_SIZE, "i2c%d", i + 1);
400
+ object_property_add_child(obj, name, OBJECT(&s->i2c[i]), NULL);
401
+ }
402
+
403
+ /*
404
+ * UART
405
+ */
406
+ for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
407
+ object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
408
+ qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus);
409
+ snprintf(name, NAME_SIZE, "uart%d", i);
410
+ object_property_add_child(obj, name, OBJECT(&s->uart[i]),
411
+ &error_fatal);
412
+ }
413
+
414
+ /*
415
+ * Ethernet
416
+ */
417
+ for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
418
+ object_initialize(&s->eth[i], sizeof(s->eth[i]), TYPE_IMX_ENET);
419
+ qdev_set_parent_bus(DEVICE(&s->eth[i]), sysbus);
420
+ snprintf(name, NAME_SIZE, "eth%d", i);
421
+ object_property_add_child(obj, name, OBJECT(&s->eth[i]),
422
+ &error_fatal);
423
+ }
424
+
425
+ /*
426
+ * SDHCI
427
+ */
428
+ for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
429
+ object_initialize(&s->usdhc[i], sizeof(s->usdhc[i]),
430
+ TYPE_IMX_USDHC);
431
+ qdev_set_parent_bus(DEVICE(&s->usdhc[i]), sysbus);
432
+ snprintf(name, NAME_SIZE, "usdhc%d", i);
433
+ object_property_add_child(obj, name, OBJECT(&s->usdhc[i]),
434
+ &error_fatal);
435
+ }
436
+
437
+ /*
438
+ * SNVS
439
+ */
440
+ object_initialize(&s->snvs, sizeof(s->snvs), TYPE_IMX7_SNVS);
441
+ qdev_set_parent_bus(DEVICE(&s->snvs), sysbus);
442
+ object_property_add_child(obj, "snvs", OBJECT(&s->snvs), &error_fatal);
443
+
444
+ /*
445
+ * Watchdog
446
+ */
447
+ for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
448
+ object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_IMX2_WDT);
449
+ qdev_set_parent_bus(DEVICE(&s->wdt[i]), sysbus);
450
+ snprintf(name, NAME_SIZE, "wdt%d", i);
451
+ object_property_add_child(obj, name, OBJECT(&s->wdt[i]),
452
+ &error_fatal);
453
+ }
454
+
455
+ /*
456
+ * GPR
457
+ */
458
+ object_initialize(&s->gpr, sizeof(s->gpr), TYPE_IMX7_GPR);
459
+ qdev_set_parent_bus(DEVICE(&s->gpr), sysbus);
460
+ object_property_add_child(obj, "gpr", OBJECT(&s->gpr), &error_fatal);
461
+
462
+ object_initialize(&s->pcie, sizeof(s->pcie), TYPE_DESIGNWARE_PCIE_HOST);
463
+ qdev_set_parent_bus(DEVICE(&s->pcie), sysbus);
464
+ object_property_add_child(obj, "pcie", OBJECT(&s->pcie), &error_fatal);
465
+
466
+ for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
467
+ object_initialize(&s->usb[i],
468
+ sizeof(s->usb[i]), TYPE_CHIPIDEA);
469
+ qdev_set_parent_bus(DEVICE(&s->usb[i]), sysbus);
470
+ snprintf(name, NAME_SIZE, "usb%d", i);
471
+ object_property_add_child(obj, name,
472
+ OBJECT(&s->usb[i]), &error_fatal);
473
+ }
474
+}
475
+
476
+static void fsl_imx7_realize(DeviceState *dev, Error **errp)
477
+{
478
+ FslIMX7State *s = FSL_IMX7(dev);
479
+ Object *o;
480
+ int i;
481
+ qemu_irq irq;
482
+ char name[NAME_SIZE];
483
+
484
+ for (i = 0; i < smp_cpus; i++) {
485
+ o = OBJECT(&s->cpu[i]);
486
+
487
+ object_property_set_int(o, QEMU_PSCI_CONDUIT_SMC,
488
+ "psci-conduit", &error_abort);
489
+
490
+ /* On uniprocessor, the CBAR is set to 0 */
491
+ if (smp_cpus > 1) {
492
+ object_property_set_int(o, FSL_IMX7_A7MPCORE_ADDR,
493
+ "reset-cbar", &error_abort);
494
+ }
495
+
496
+ if (i) {
497
+ /* Secondary CPUs start in PSCI powered-down state */
498
+ object_property_set_bool(o, true,
499
+ "start-powered-off", &error_abort);
500
+ }
501
+
502
+ object_property_set_bool(o, true, "realized", &error_abort);
503
+ }
504
+
505
+ /*
506
+ * A7MPCORE
507
+ */
508
+ object_property_set_int(OBJECT(&s->a7mpcore), smp_cpus, "num-cpu",
509
+ &error_abort);
510
+ object_property_set_int(OBJECT(&s->a7mpcore),
511
+ FSL_IMX7_MAX_IRQ + GIC_INTERNAL,
512
+ "num-irq", &error_abort);
513
+
514
+ object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized",
515
+ &error_abort);
516
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX7_A7MPCORE_ADDR);
517
+
518
+ for (i = 0; i < smp_cpus; i++) {
519
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore);
520
+ DeviceState *d = DEVICE(qemu_get_cpu(i));
521
+
522
+ irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
523
+ sysbus_connect_irq(sbd, i, irq);
524
+ irq = qdev_get_gpio_in(d, ARM_CPU_FIQ);
525
+ sysbus_connect_irq(sbd, i + smp_cpus, irq);
526
+ }
527
+
528
+ /*
529
+ * A7MPCORE DAP
530
+ */
531
+ create_unimplemented_device("a7mpcore-dap", FSL_IMX7_A7MPCORE_DAP_ADDR,
532
+ 0x100000);
533
+
534
+ /*
535
+ * GPT1, 2, 3, 4
536
+ */
537
+ for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
538
+ static const hwaddr FSL_IMX7_GPTn_ADDR[FSL_IMX7_NUM_GPTS] = {
539
+ FSL_IMX7_GPT1_ADDR,
540
+ FSL_IMX7_GPT2_ADDR,
541
+ FSL_IMX7_GPT3_ADDR,
542
+ FSL_IMX7_GPT4_ADDR,
543
+ };
544
+
545
+ s->gpt[i].ccm = IMX_CCM(&s->ccm);
546
+ object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized",
547
+ &error_abort);
548
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, FSL_IMX7_GPTn_ADDR[i]);
549
+ }
550
+
551
+ for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
552
+ static const hwaddr FSL_IMX7_GPIOn_ADDR[FSL_IMX7_NUM_GPIOS] = {
553
+ FSL_IMX7_GPIO1_ADDR,
554
+ FSL_IMX7_GPIO2_ADDR,
555
+ FSL_IMX7_GPIO3_ADDR,
556
+ FSL_IMX7_GPIO4_ADDR,
557
+ FSL_IMX7_GPIO5_ADDR,
558
+ FSL_IMX7_GPIO6_ADDR,
559
+ FSL_IMX7_GPIO7_ADDR,
560
+ };
561
+
562
+ object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized",
563
+ &error_abort);
564
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, FSL_IMX7_GPIOn_ADDR[i]);
565
+ }
566
+
567
+ /*
568
+ * IOMUXC and IOMUXC_LPSR
569
+ */
570
+ for (i = 0; i < FSL_IMX7_NUM_IOMUXCS; i++) {
571
+ static const hwaddr FSL_IMX7_IOMUXCn_ADDR[FSL_IMX7_NUM_IOMUXCS] = {
572
+ FSL_IMX7_IOMUXC_ADDR,
573
+ FSL_IMX7_IOMUXC_LPSR_ADDR,
574
+ };
575
+
576
+ snprintf(name, NAME_SIZE, "iomuxc%d", i);
577
+ create_unimplemented_device(name, FSL_IMX7_IOMUXCn_ADDR[i],
578
+ FSL_IMX7_IOMUXCn_SIZE);
579
+ }
580
+
581
+ /*
582
+ * CCM
583
+ */
584
+ object_property_set_bool(OBJECT(&s->ccm), true, "realized", &error_abort);
585
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX7_CCM_ADDR);
586
+
587
+ /*
588
+ * Analog
589
+ */
590
+ object_property_set_bool(OBJECT(&s->analog), true, "realized",
591
+ &error_abort);
592
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0, FSL_IMX7_ANALOG_ADDR);
593
+
594
+ /*
595
+ * GPCv2
596
+ */
597
+ object_property_set_bool(OBJECT(&s->gpcv2), true,
598
+ "realized", &error_abort);
599
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX7_GPC_ADDR);
600
+
601
+ /* Initialize all ECSPI */
602
+ for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
603
+ static const hwaddr FSL_IMX7_SPIn_ADDR[FSL_IMX7_NUM_ECSPIS] = {
604
+ FSL_IMX7_ECSPI1_ADDR,
605
+ FSL_IMX7_ECSPI2_ADDR,
606
+ FSL_IMX7_ECSPI3_ADDR,
607
+ FSL_IMX7_ECSPI4_ADDR,
608
+ };
609
+
610
+ static const hwaddr FSL_IMX7_SPIn_IRQ[FSL_IMX7_NUM_ECSPIS] = {
611
+ FSL_IMX7_ECSPI1_IRQ,
612
+ FSL_IMX7_ECSPI2_IRQ,
613
+ FSL_IMX7_ECSPI3_IRQ,
614
+ FSL_IMX7_ECSPI4_IRQ,
615
+ };
616
+
617
+ /* Initialize the SPI */
618
+ object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
619
+ &error_abort);
620
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
621
+ FSL_IMX7_SPIn_ADDR[i]);
622
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
623
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
624
+ FSL_IMX7_SPIn_IRQ[i]));
625
+ }
626
+
627
+ for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
628
+ static const hwaddr FSL_IMX7_I2Cn_ADDR[FSL_IMX7_NUM_I2CS] = {
629
+ FSL_IMX7_I2C1_ADDR,
630
+ FSL_IMX7_I2C2_ADDR,
631
+ FSL_IMX7_I2C3_ADDR,
632
+ FSL_IMX7_I2C4_ADDR,
633
+ };
634
+
635
+ static const hwaddr FSL_IMX7_I2Cn_IRQ[FSL_IMX7_NUM_I2CS] = {
636
+ FSL_IMX7_I2C1_IRQ,
637
+ FSL_IMX7_I2C2_IRQ,
638
+ FSL_IMX7_I2C3_IRQ,
639
+ FSL_IMX7_I2C4_IRQ,
640
+ };
641
+
642
+ object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized",
643
+ &error_abort);
644
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX7_I2Cn_ADDR[i]);
645
+
646
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
647
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
648
+ FSL_IMX7_I2Cn_IRQ[i]));
649
+ }
650
+
651
+ /*
652
+ * UART
653
+ */
654
+ for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
655
+ static const hwaddr FSL_IMX7_UARTn_ADDR[FSL_IMX7_NUM_UARTS] = {
656
+ FSL_IMX7_UART1_ADDR,
657
+ FSL_IMX7_UART2_ADDR,
658
+ FSL_IMX7_UART3_ADDR,
659
+ FSL_IMX7_UART4_ADDR,
660
+ FSL_IMX7_UART5_ADDR,
661
+ FSL_IMX7_UART6_ADDR,
662
+ FSL_IMX7_UART7_ADDR,
663
+ };
664
+
665
+ static const int FSL_IMX7_UARTn_IRQ[FSL_IMX7_NUM_UARTS] = {
666
+ FSL_IMX7_UART1_IRQ,
667
+ FSL_IMX7_UART2_IRQ,
668
+ FSL_IMX7_UART3_IRQ,
669
+ FSL_IMX7_UART4_IRQ,
670
+ FSL_IMX7_UART5_IRQ,
671
+ FSL_IMX7_UART6_IRQ,
672
+ FSL_IMX7_UART7_IRQ,
673
+ };
674
+
675
+
676
+ if (i < MAX_SERIAL_PORTS) {
677
+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hds[i]);
678
+ }
679
+
680
+ object_property_set_bool(OBJECT(&s->uart[i]), true, "realized",
681
+ &error_abort);
682
+
683
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, FSL_IMX7_UARTn_ADDR[i]);
684
+
685
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_UARTn_IRQ[i]);
686
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, irq);
687
+ }
688
+
689
+ /*
690
+ * Ethernet
691
+ */
692
+ for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
693
+ static const hwaddr FSL_IMX7_ENETn_ADDR[FSL_IMX7_NUM_ETHS] = {
694
+ FSL_IMX7_ENET1_ADDR,
695
+ FSL_IMX7_ENET2_ADDR,
696
+ };
697
+
698
+ object_property_set_uint(OBJECT(&s->eth[i]), FSL_IMX7_ETH_NUM_TX_RINGS,
699
+ "tx-ring-num", &error_abort);
700
+ qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]);
701
+ object_property_set_bool(OBJECT(&s->eth[i]), true, "realized",
702
+ &error_abort);
703
+
704
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0, FSL_IMX7_ENETn_ADDR[i]);
705
+
706
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_ENET_IRQ(i, 0));
707
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 0, irq);
708
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_ENET_IRQ(i, 3));
709
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 1, irq);
710
+ }
711
+
712
+ /*
713
+ * USDHC
714
+ */
715
+ for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
716
+ static const hwaddr FSL_IMX7_USDHCn_ADDR[FSL_IMX7_NUM_USDHCS] = {
717
+ FSL_IMX7_USDHC1_ADDR,
718
+ FSL_IMX7_USDHC2_ADDR,
719
+ FSL_IMX7_USDHC3_ADDR,
720
+ };
721
+
722
+ static const int FSL_IMX7_USDHCn_IRQ[FSL_IMX7_NUM_USDHCS] = {
723
+ FSL_IMX7_USDHC1_IRQ,
724
+ FSL_IMX7_USDHC2_IRQ,
725
+ FSL_IMX7_USDHC3_IRQ,
726
+ };
727
+
728
+ object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized",
729
+ &error_abort);
730
+
731
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
732
+ FSL_IMX7_USDHCn_ADDR[i]);
733
+
734
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_USDHCn_IRQ[i]);
735
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0, irq);
736
+ }
737
+
738
+ /*
739
+ * SNVS
740
+ */
741
+ object_property_set_bool(OBJECT(&s->snvs), true, "realized", &error_abort);
742
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_ADDR);
743
+
744
+ /*
745
+ * SRC
746
+ */
747
+ create_unimplemented_device("sdma", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE);
748
+
749
+ /*
750
+ * Watchdog
751
+ */
752
+ for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
753
+ static const hwaddr FSL_IMX7_WDOGn_ADDR[FSL_IMX7_NUM_WDTS] = {
754
+ FSL_IMX7_WDOG1_ADDR,
755
+ FSL_IMX7_WDOG2_ADDR,
756
+ FSL_IMX7_WDOG3_ADDR,
757
+ FSL_IMX7_WDOG4_ADDR,
758
+ };
759
+
760
+ object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
761
+ &error_abort);
762
+
763
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]);
764
+ }
765
+
766
+ /*
767
+ * SDMA
768
+ */
769
+ create_unimplemented_device("sdma", FSL_IMX7_SDMA_ADDR, FSL_IMX7_SDMA_SIZE);
770
+
771
+
772
+ object_property_set_bool(OBJECT(&s->gpr), true, "realized",
773
+ &error_abort);
774
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_GPR_ADDR);
775
+
776
+ object_property_set_bool(OBJECT(&s->pcie), true,
777
+ "realized", &error_abort);
778
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR);
779
+
780
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTA_IRQ);
781
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq);
782
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTB_IRQ);
783
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq);
784
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTC_IRQ);
785
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq);
786
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ);
787
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
788
+
789
+
790
+ for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
791
+ static const hwaddr FSL_IMX7_USBMISCn_ADDR[FSL_IMX7_NUM_USBS] = {
792
+ FSL_IMX7_USBMISC1_ADDR,
793
+ FSL_IMX7_USBMISC2_ADDR,
794
+ FSL_IMX7_USBMISC3_ADDR,
795
+ };
796
+
797
+ static const hwaddr FSL_IMX7_USBn_ADDR[FSL_IMX7_NUM_USBS] = {
798
+ FSL_IMX7_USB1_ADDR,
799
+ FSL_IMX7_USB2_ADDR,
800
+ FSL_IMX7_USB3_ADDR,
801
+ };
802
+
803
+ static const hwaddr FSL_IMX7_USBn_IRQ[FSL_IMX7_NUM_USBS] = {
804
+ FSL_IMX7_USB1_IRQ,
805
+ FSL_IMX7_USB2_IRQ,
806
+ FSL_IMX7_USB3_IRQ,
807
+ };
808
+
809
+ object_property_set_bool(OBJECT(&s->usb[i]), true, "realized",
810
+ &error_abort);
811
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0,
812
+ FSL_IMX7_USBn_ADDR[i]);
813
+
814
+ irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_USBn_IRQ[i]);
815
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0, irq);
816
+
817
+ snprintf(name, NAME_SIZE, "usbmisc%d", i);
818
+ create_unimplemented_device(name, FSL_IMX7_USBMISCn_ADDR[i],
819
+ FSL_IMX7_USBMISCn_SIZE);
820
+ }
821
+
822
+ /*
823
+ * ADCs
824
+ */
825
+ for (i = 0; i < FSL_IMX7_NUM_ADCS; i++) {
826
+ static const hwaddr FSL_IMX7_ADCn_ADDR[FSL_IMX7_NUM_ADCS] = {
827
+ FSL_IMX7_ADC1_ADDR,
828
+ FSL_IMX7_ADC2_ADDR,
829
+ };
830
+
831
+ snprintf(name, NAME_SIZE, "adc%d", i);
832
+ create_unimplemented_device(name, FSL_IMX7_ADCn_ADDR[i],
833
+ FSL_IMX7_ADCn_SIZE);
834
+ }
835
+
836
+ /*
837
+ * LCD
838
+ */
839
+ create_unimplemented_device("lcdif", FSL_IMX7_LCDIF_ADDR,
840
+ FSL_IMX7_LCDIF_SIZE);
841
+}
842
+
843
+static void fsl_imx7_class_init(ObjectClass *oc, void *data)
844
+{
845
+ DeviceClass *dc = DEVICE_CLASS(oc);
846
+
847
+ dc->realize = fsl_imx7_realize;
848
+
849
+ /* Reason: Uses serial_hds and nd_table in realize() directly */
850
+ dc->user_creatable = false;
851
+ dc->desc = "i.MX7 SOC";
852
+}
853
+
854
+static const TypeInfo fsl_imx7_type_info = {
855
+ .name = TYPE_FSL_IMX7,
856
+ .parent = TYPE_DEVICE,
857
+ .instance_size = sizeof(FslIMX7State),
858
+ .instance_init = fsl_imx7_init,
859
+ .class_init = fsl_imx7_class_init,
860
+};
861
+
862
+static void fsl_imx7_register_types(void)
863
+{
864
+ type_register_static(&fsl_imx7_type_info);
865
+}
866
+type_init(fsl_imx7_register_types)
867
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
868
index XXXXXXX..XXXXXXX 100644
869
--- a/default-configs/arm-softmmu.mak
870
+++ b/default-configs/arm-softmmu.mak
871
@@ -XXX,XX +XXX,XX @@ CONFIG_ALLWINNER_A10=y
872
CONFIG_FSL_IMX6=y
873
CONFIG_FSL_IMX31=y
874
CONFIG_FSL_IMX25=y
875
+CONFIG_FSL_IMX7=y
876
877
CONFIG_IMX_I2C=y
878
879
--
880
2.16.2
881
882
diff view generated by jsdifflib
New patch
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
2
3
Implement code needed to set up emulation of MCIMX7SABRE board from
4
NXP. For more info about the HW see:
5
6
https://www.nxp.com/support/developer-resources/hardware-development-tools/sabre-development-system/sabre-board-for-smart-devices-based-on-the-i.mx-7dual-applications-processors:MCIMX7SABRE
7
8
Cc: Peter Maydell <peter.maydell@linaro.org>
9
Cc: Jason Wang <jasowang@redhat.com>
10
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
12
Cc: Michael S. Tsirkin <mst@redhat.com>
13
Cc: qemu-devel@nongnu.org
14
Cc: qemu-arm@nongnu.org
15
Cc: yurovsky@gmail.com
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
hw/arm/Makefile.objs | 2 +-
21
hw/arm/mcimx7d-sabre.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++
22
2 files changed, 91 insertions(+), 1 deletion(-)
23
create mode 100644 hw/arm/mcimx7d-sabre.c
24
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/Makefile.objs
28
+++ b/hw/arm/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2) += mps2.o
30
obj-$(CONFIG_MPS2) += mps2-tz.o
31
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
32
obj-$(CONFIG_IOTKIT) += iotkit.o
33
-obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
34
+obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
35
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/hw/arm/mcimx7d-sabre.c
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * Copyright (c) 2018, Impinj, Inc.
43
+ *
44
+ * MCIMX7D_SABRE Board System emulation.
45
+ *
46
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
47
+ *
48
+ * This code is licensed under the GPL, version 2 or later.
49
+ * See the file `COPYING' in the top level directory.
50
+ *
51
+ * It (partially) emulates a mcimx7d_sabre board, with a Freescale
52
+ * i.MX7 SoC
53
+ */
54
+
55
+#include "qemu/osdep.h"
56
+#include "qapi/error.h"
57
+#include "qemu-common.h"
58
+#include "hw/arm/fsl-imx7.h"
59
+#include "hw/boards.h"
60
+#include "sysemu/sysemu.h"
61
+#include "sysemu/device_tree.h"
62
+#include "qemu/error-report.h"
63
+#include "sysemu/qtest.h"
64
+#include "net/net.h"
65
+
66
+typedef struct {
67
+ FslIMX7State soc;
68
+ MemoryRegion ram;
69
+} MCIMX7Sabre;
70
+
71
+static void mcimx7d_sabre_init(MachineState *machine)
72
+{
73
+ static struct arm_boot_info boot_info;
74
+ MCIMX7Sabre *s = g_new0(MCIMX7Sabre, 1);
75
+ Object *soc;
76
+ int i;
77
+
78
+ if (machine->ram_size > FSL_IMX7_MMDC_SIZE) {
79
+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)",
80
+ machine->ram_size, FSL_IMX7_MMDC_SIZE);
81
+ exit(1);
82
+ }
83
+
84
+ boot_info = (struct arm_boot_info) {
85
+ .loader_start = FSL_IMX7_MMDC_ADDR,
86
+ .board_id = -1,
87
+ .ram_size = machine->ram_size,
88
+ .kernel_filename = machine->kernel_filename,
89
+ .kernel_cmdline = machine->kernel_cmdline,
90
+ .initrd_filename = machine->initrd_filename,
91
+ .nb_cpus = smp_cpus,
92
+ };
93
+
94
+ object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX7);
95
+ soc = OBJECT(&s->soc);
96
+ object_property_add_child(OBJECT(machine), "soc", soc, &error_fatal);
97
+ object_property_set_bool(soc, true, "realized", &error_fatal);
98
+
99
+ memory_region_allocate_system_memory(&s->ram, NULL, "mcimx7d-sabre.ram",
100
+ machine->ram_size);
101
+ memory_region_add_subregion(get_system_memory(),
102
+ FSL_IMX7_MMDC_ADDR, &s->ram);
103
+
104
+ for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
105
+ BusState *bus;
106
+ DeviceState *carddev;
107
+ DriveInfo *di;
108
+ BlockBackend *blk;
109
+
110
+ di = drive_get_next(IF_SD);
111
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
112
+ bus = qdev_get_child_bus(DEVICE(&s->soc.usdhc[i]), "sd-bus");
113
+ carddev = qdev_create(bus, TYPE_SD_CARD);
114
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
115
+ object_property_set_bool(OBJECT(carddev), true,
116
+ "realized", &error_fatal);
117
+ }
118
+
119
+ if (!qtest_enabled()) {
120
+ arm_load_kernel(&s->soc.cpu[0], &boot_info);
121
+ }
122
+}
123
+
124
+static void mcimx7d_sabre_machine_init(MachineClass *mc)
125
+{
126
+ mc->desc = "Freescale i.MX7 DUAL SABRE (Cortex A7)";
127
+ mc->init = mcimx7d_sabre_init;
128
+ mc->max_cpus = FSL_IMX7_NUM_CPUS;
129
+}
130
+DEFINE_MACHINE("mcimx7d-sabre", mcimx7d_sabre_machine_init)
131
--
132
2.16.2
133
134
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
As an implementation choice, widening VL has zeroed the
4
previously inaccessible portion of the sve registers.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Acked-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20180303143823.27055-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/aarch64/target_syscall.h | 3 +++
13
target/arm/cpu.h | 1 +
14
linux-user/syscall.c | 27 ++++++++++++++++++++++++
15
target/arm/cpu64.c | 41 +++++++++++++++++++++++++++++++++++++
16
4 files changed, 72 insertions(+)
17
18
diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/linux-user/aarch64/target_syscall.h
21
+++ b/linux-user/aarch64/target_syscall.h
22
@@ -XXX,XX +XXX,XX @@ struct target_pt_regs {
23
#define TARGET_MLOCKALL_MCL_CURRENT 1
24
#define TARGET_MLOCKALL_MCL_FUTURE 2
25
26
+#define TARGET_PR_SVE_SET_VL 50
27
+#define TARGET_PR_SVE_GET_VL 51
28
+
29
#endif /* AARCH64_TARGET_SYSCALL_H */
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.h
33
+++ b/target/arm/cpu.h
34
@@ -XXX,XX +XXX,XX @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
35
#ifdef TARGET_AARCH64
36
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
37
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
38
+void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
39
#endif
40
41
target_ulong do_arm_semihosting(CPUARMState *env);
42
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/linux-user/syscall.c
45
+++ b/linux-user/syscall.c
46
@@ -XXX,XX +XXX,XX @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
47
break;
48
}
49
#endif
50
+#ifdef TARGET_AARCH64
51
+ case TARGET_PR_SVE_SET_VL:
52
+ /* We cannot support either PR_SVE_SET_VL_ONEXEC
53
+ or PR_SVE_VL_INHERIT. Therefore, anything above
54
+ ARM_MAX_VQ results in EINVAL. */
55
+ ret = -TARGET_EINVAL;
56
+ if (arm_feature(cpu_env, ARM_FEATURE_SVE)
57
+ && arg2 >= 0 && arg2 <= ARM_MAX_VQ * 16 && !(arg2 & 15)) {
58
+ CPUARMState *env = cpu_env;
59
+ int old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
60
+ int vq = MAX(arg2 / 16, 1);
61
+
62
+ if (vq < old_vq) {
63
+ aarch64_sve_narrow_vq(env, vq);
64
+ }
65
+ env->vfp.zcr_el[1] = vq - 1;
66
+ ret = vq * 16;
67
+ }
68
+ break;
69
+ case TARGET_PR_SVE_GET_VL:
70
+ ret = -TARGET_EINVAL;
71
+ if (arm_feature(cpu_env, ARM_FEATURE_SVE)) {
72
+ CPUARMState *env = cpu_env;
73
+ ret = ((env->vfp.zcr_el[1] & 0xf) + 1) * 16;
74
+ }
75
+ break;
76
+#endif /* AARCH64 */
77
case PR_GET_SECCOMP:
78
case PR_SET_SECCOMP:
79
/* Disable seccomp to prevent the target disabling syscalls we
80
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/cpu64.c
83
+++ b/target/arm/cpu64.c
84
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_register_types(void)
85
}
86
87
type_init(aarch64_cpu_register_types)
88
+
89
+/* The manual says that when SVE is enabled and VQ is widened the
90
+ * implementation is allowed to zero the previously inaccessible
91
+ * portion of the registers. The corollary to that is that when
92
+ * SVE is enabled and VQ is narrowed we are also allowed to zero
93
+ * the now inaccessible portion of the registers.
94
+ *
95
+ * The intent of this is that no predicate bit beyond VQ is ever set.
96
+ * Which means that some operations on predicate registers themselves
97
+ * may operate on full uint64_t or even unrolled across the maximum
98
+ * uint64_t[4]. Performing 4 bits of host arithmetic unconditionally
99
+ * may well be cheaper than conditionals to restrict the operation
100
+ * to the relevant portion of a uint16_t[16].
101
+ *
102
+ * TODO: Need to call this for changes to the real system registers
103
+ * and EL state changes.
104
+ */
105
+void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
106
+{
107
+ int i, j;
108
+ uint64_t pmask;
109
+
110
+ assert(vq >= 1 && vq <= ARM_MAX_VQ);
111
+
112
+ /* Zap the high bits of the zregs. */
113
+ for (i = 0; i < 32; i++) {
114
+ memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq));
115
+ }
116
+
117
+ /* Zap the high bits of the pregs and ffr. */
118
+ pmask = 0;
119
+ if (vq & 3) {
120
+ pmask = ~(-1ULL << (16 * (vq & 3)));
121
+ }
122
+ for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) {
123
+ for (i = 0; i < 17; ++i) {
124
+ env->vfp.pregs[i].p[j] &= pmask;
125
+ }
126
+ pmask = 0;
127
+ }
128
+}
129
--
130
2.16.2
131
132
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Split out helpers from target_setup_frame and target_restore_sigframe
4
for dealing with general registers, fpsimd registers, and the end record.
5
6
When we add support for sve registers, the relative positions of
7
these will change.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180303143823.27055-3-richard.henderson@linaro.org
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
linux-user/signal.c | 120 ++++++++++++++++++++++++++++++----------------------
16
1 file changed, 69 insertions(+), 51 deletions(-)
17
18
diff --git a/linux-user/signal.c b/linux-user/signal.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/linux-user/signal.c
21
+++ b/linux-user/signal.c
22
@@ -XXX,XX +XXX,XX @@ struct target_rt_sigframe {
23
uint32_t tramp[2];
24
};
25
26
-static int target_setup_sigframe(struct target_rt_sigframe *sf,
27
- CPUARMState *env, target_sigset_t *set)
28
+static void target_setup_general_frame(struct target_rt_sigframe *sf,
29
+ CPUARMState *env, target_sigset_t *set)
30
{
31
int i;
32
- struct target_aux_context *aux =
33
- (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
34
35
- /* set up the stack frame for unwinding */
36
- __put_user(env->xregs[29], &sf->fp);
37
- __put_user(env->xregs[30], &sf->lr);
38
+ __put_user(0, &sf->uc.tuc_flags);
39
+ __put_user(0, &sf->uc.tuc_link);
40
+
41
+ __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
42
+ __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
43
+ __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
44
45
for (i = 0; i < 31; i++) {
46
__put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
47
@@ -XXX,XX +XXX,XX @@ static int target_setup_sigframe(struct target_rt_sigframe *sf,
48
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
49
__put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
50
}
51
+}
52
+
53
+static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
54
+ CPUARMState *env)
55
+{
56
+ int i;
57
+
58
+ __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic);
59
+ __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size);
60
+ __put_user(vfp_get_fpsr(env), &fpsimd->fpsr);
61
+ __put_user(vfp_get_fpcr(env), &fpsimd->fpcr);
62
63
for (i = 0; i < 32; i++) {
64
uint64_t *q = aa64_vfp_qreg(env, i);
65
#ifdef TARGET_WORDS_BIGENDIAN
66
- __put_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]);
67
- __put_user(q[1], &aux->fpsimd.vregs[i * 2]);
68
+ __put_user(q[0], &fpsimd->vregs[i * 2 + 1]);
69
+ __put_user(q[1], &fpsimd->vregs[i * 2]);
70
#else
71
- __put_user(q[0], &aux->fpsimd.vregs[i * 2]);
72
- __put_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]);
73
+ __put_user(q[0], &fpsimd->vregs[i * 2]);
74
+ __put_user(q[1], &fpsimd->vregs[i * 2 + 1]);
75
#endif
76
}
77
- __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
78
- __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
79
- __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
80
- __put_user(sizeof(struct target_fpsimd_context),
81
- &aux->fpsimd.head.size);
82
-
83
- /* set the "end" magic */
84
- __put_user(0, &aux->end.magic);
85
- __put_user(0, &aux->end.size);
86
-
87
- return 0;
88
}
89
90
-static int target_restore_sigframe(CPUARMState *env,
91
- struct target_rt_sigframe *sf)
92
+static void target_setup_end_record(struct target_aarch64_ctx *end)
93
+{
94
+ __put_user(0, &end->magic);
95
+ __put_user(0, &end->size);
96
+}
97
+
98
+static void target_restore_general_frame(CPUARMState *env,
99
+ struct target_rt_sigframe *sf)
100
{
101
sigset_t set;
102
- int i;
103
- struct target_aux_context *aux =
104
- (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
105
- uint32_t magic, size, fpsr, fpcr;
106
uint64_t pstate;
107
+ int i;
108
109
target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
110
set_sigmask(&set);
111
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
112
__get_user(env->pc, &sf->uc.tuc_mcontext.pc);
113
__get_user(pstate, &sf->uc.tuc_mcontext.pstate);
114
pstate_write(env, pstate);
115
+}
116
117
- __get_user(magic, &aux->fpsimd.head.magic);
118
- __get_user(size, &aux->fpsimd.head.size);
119
+static void target_restore_fpsimd_record(CPUARMState *env,
120
+ struct target_fpsimd_context *fpsimd)
121
+{
122
+ uint32_t fpsr, fpcr;
123
+ int i;
124
125
- if (magic != TARGET_FPSIMD_MAGIC
126
- || size != sizeof(struct target_fpsimd_context)) {
127
- return 1;
128
- }
129
+ __get_user(fpsr, &fpsimd->fpsr);
130
+ vfp_set_fpsr(env, fpsr);
131
+ __get_user(fpcr, &fpsimd->fpcr);
132
+ vfp_set_fpcr(env, fpcr);
133
134
for (i = 0; i < 32; i++) {
135
uint64_t *q = aa64_vfp_qreg(env, i);
136
#ifdef TARGET_WORDS_BIGENDIAN
137
- __get_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]);
138
- __get_user(q[1], &aux->fpsimd.vregs[i * 2]);
139
+ __get_user(q[0], &fpsimd->vregs[i * 2 + 1]);
140
+ __get_user(q[1], &fpsimd->vregs[i * 2]);
141
#else
142
- __get_user(q[0], &aux->fpsimd.vregs[i * 2]);
143
- __get_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]);
144
+ __get_user(q[0], &fpsimd->vregs[i * 2]);
145
+ __get_user(q[1], &fpsimd->vregs[i * 2 + 1]);
146
#endif
147
}
148
- __get_user(fpsr, &aux->fpsimd.fpsr);
149
- vfp_set_fpsr(env, fpsr);
150
- __get_user(fpcr, &aux->fpsimd.fpcr);
151
- vfp_set_fpcr(env, fpcr);
152
+}
153
154
+static int target_restore_sigframe(CPUARMState *env,
155
+ struct target_rt_sigframe *sf)
156
+{
157
+ struct target_aux_context *aux
158
+ = (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
159
+ uint32_t magic, size;
160
+
161
+ target_restore_general_frame(env, sf);
162
+
163
+ __get_user(magic, &aux->fpsimd.head.magic);
164
+ __get_user(size, &aux->fpsimd.head.size);
165
+ if (magic == TARGET_FPSIMD_MAGIC
166
+ && size == sizeof(struct target_fpsimd_context)) {
167
+ target_restore_fpsimd_record(env, &aux->fpsimd);
168
+ } else {
169
+ return 1;
170
+ }
171
return 0;
172
}
173
174
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
175
CPUARMState *env)
176
{
177
struct target_rt_sigframe *frame;
178
+ struct target_aux_context *aux;
179
abi_ulong frame_addr, return_addr;
180
181
frame_addr = get_sigframe(ka, env);
182
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
183
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
184
goto give_sigsegv;
185
}
186
+ aux = (struct target_aux_context *)frame->uc.tuc_mcontext.__reserved;
187
188
- __put_user(0, &frame->uc.tuc_flags);
189
- __put_user(0, &frame->uc.tuc_link);
190
+ target_setup_general_frame(frame, env, set);
191
+ target_setup_fpsimd_record(&aux->fpsimd, env);
192
+ target_setup_end_record(&aux->end);
193
194
- __put_user(target_sigaltstack_used.ss_sp,
195
- &frame->uc.tuc_stack.ss_sp);
196
- __put_user(sas_ss_flags(env->xregs[31]),
197
- &frame->uc.tuc_stack.ss_flags);
198
- __put_user(target_sigaltstack_used.ss_size,
199
- &frame->uc.tuc_stack.ss_size);
200
- target_setup_sigframe(frame, env, set);
201
if (ka->sa_flags & TARGET_SA_RESTORER) {
202
return_addr = ka->sa_restorer;
203
} else {
204
--
205
2.16.2
206
207
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
This changes the qemu signal frame layout to be more like the kernel's,
4
in that the various records are dynamically allocated rather than fixed
5
in place by a structure.
6
7
For now, all of the allocation is out of uc.tuc_mcontext.__reserved,
8
so the allocation is actually trivial. That will change with SVE support.
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180303143823.27055-4-richard.henderson@linaro.org
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
linux-user/signal.c | 89 ++++++++++++++++++++++++++++++++++++-----------------
17
1 file changed, 61 insertions(+), 28 deletions(-)
18
19
diff --git a/linux-user/signal.c b/linux-user/signal.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/linux-user/signal.c
22
+++ b/linux-user/signal.c
23
@@ -XXX,XX +XXX,XX @@ struct target_fpsimd_context {
24
uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
25
};
26
27
-/*
28
- * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
29
- * user space as it will change with the addition of new context. User space
30
- * should check the magic/size information.
31
- */
32
-struct target_aux_context {
33
- struct target_fpsimd_context fpsimd;
34
- /* additional context to be added before "end" */
35
- struct target_aarch64_ctx end;
36
-};
37
-
38
struct target_rt_sigframe {
39
struct target_siginfo info;
40
struct target_ucontext uc;
41
+};
42
+
43
+struct target_rt_frame_record {
44
uint64_t fp;
45
uint64_t lr;
46
uint32_t tramp[2];
47
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
48
static int target_restore_sigframe(CPUARMState *env,
49
struct target_rt_sigframe *sf)
50
{
51
- struct target_aux_context *aux
52
- = (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
53
- uint32_t magic, size;
54
+ struct target_aarch64_ctx *ctx;
55
+ struct target_fpsimd_context *fpsimd = NULL;
56
57
target_restore_general_frame(env, sf);
58
59
- __get_user(magic, &aux->fpsimd.head.magic);
60
- __get_user(size, &aux->fpsimd.head.size);
61
- if (magic == TARGET_FPSIMD_MAGIC
62
- && size == sizeof(struct target_fpsimd_context)) {
63
- target_restore_fpsimd_record(env, &aux->fpsimd);
64
- } else {
65
+ ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
66
+ while (ctx) {
67
+ uint32_t magic, size;
68
+
69
+ __get_user(magic, &ctx->magic);
70
+ __get_user(size, &ctx->size);
71
+ switch (magic) {
72
+ case 0:
73
+ if (size != 0) {
74
+ return 1;
75
+ }
76
+ ctx = NULL;
77
+ continue;
78
+
79
+ case TARGET_FPSIMD_MAGIC:
80
+ if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
81
+ return 1;
82
+ }
83
+ fpsimd = (struct target_fpsimd_context *)ctx;
84
+ break;
85
+
86
+ default:
87
+ /* Unknown record -- we certainly didn't generate it.
88
+ * Did we in fact get out of sync?
89
+ */
90
+ return 1;
91
+ }
92
+ ctx = (void *)ctx + size;
93
+ }
94
+
95
+ /* Require FPSIMD always. */
96
+ if (!fpsimd) {
97
return 1;
98
}
99
+ target_restore_fpsimd_record(env, fpsimd);
100
+
101
return 0;
102
}
103
104
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
105
target_siginfo_t *info, target_sigset_t *set,
106
CPUARMState *env)
107
{
108
+ int size = offsetof(struct target_rt_sigframe, uc.tuc_mcontext.__reserved);
109
+ int fpsimd_ofs, end1_ofs, fr_ofs;
110
struct target_rt_sigframe *frame;
111
- struct target_aux_context *aux;
112
+ struct target_rt_frame_record *fr;
113
abi_ulong frame_addr, return_addr;
114
115
+ fpsimd_ofs = size;
116
+ size += sizeof(struct target_fpsimd_context);
117
+ end1_ofs = size;
118
+ size += sizeof(struct target_aarch64_ctx);
119
+ fr_ofs = size;
120
+ size += sizeof(struct target_rt_frame_record);
121
+
122
frame_addr = get_sigframe(ka, env);
123
trace_user_setup_frame(env, frame_addr);
124
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
125
goto give_sigsegv;
126
}
127
- aux = (struct target_aux_context *)frame->uc.tuc_mcontext.__reserved;
128
129
target_setup_general_frame(frame, env, set);
130
- target_setup_fpsimd_record(&aux->fpsimd, env);
131
- target_setup_end_record(&aux->end);
132
+ target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
133
+ target_setup_end_record((void *)frame + end1_ofs);
134
+
135
+ /* Set up the stack frame for unwinding. */
136
+ fr = (void *)frame + fr_ofs;
137
+ __put_user(env->xregs[29], &fr->fp);
138
+ __put_user(env->xregs[30], &fr->lr);
139
140
if (ka->sa_flags & TARGET_SA_RESTORER) {
141
return_addr = ka->sa_restorer;
142
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
143
* Since these are instructions they need to be put as little-endian
144
* regardless of target default or current CPU endianness.
145
*/
146
- __put_user_e(0xd2801168, &frame->tramp[0], le);
147
- __put_user_e(0xd4000001, &frame->tramp[1], le);
148
- return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
149
+ __put_user_e(0xd2801168, &fr->tramp[0], le);
150
+ __put_user_e(0xd4000001, &fr->tramp[1], le);
151
+ return_addr = frame_addr + fr_ofs
152
+ + offsetof(struct target_rt_frame_record, tramp);
153
}
154
env->xregs[0] = usig;
155
env->xregs[31] = frame_addr;
156
- env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
157
+ env->xregs[29] = frame_addr + fr_ofs;
158
env->pc = ka->_sa_handler;
159
env->xregs[30] = return_addr;
160
if (info) {
161
--
162
2.16.2
163
164
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The EXTRA record allows for additional space to be allocated
4
beyon what is currently reserved. Add code to emit and read
5
this record type.
6
7
Nothing uses extra space yet.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180303143823.27055-5-richard.henderson@linaro.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
linux-user/signal.c | 74 +++++++++++++++++++++++++++++++++++++++++++++--------
16
1 file changed, 63 insertions(+), 11 deletions(-)
17
18
diff --git a/linux-user/signal.c b/linux-user/signal.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/linux-user/signal.c
21
+++ b/linux-user/signal.c
22
@@ -XXX,XX +XXX,XX @@ struct target_fpsimd_context {
23
uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
24
};
25
26
+#define TARGET_EXTRA_MAGIC 0x45585401
27
+
28
+struct target_extra_context {
29
+ struct target_aarch64_ctx head;
30
+ uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */
31
+ uint32_t size; /* size in bytes of the extra space */
32
+ uint32_t reserved[3];
33
+};
34
+
35
struct target_rt_sigframe {
36
struct target_siginfo info;
37
struct target_ucontext uc;
38
@@ -XXX,XX +XXX,XX @@ static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd,
39
}
40
}
41
42
+static void target_setup_extra_record(struct target_extra_context *extra,
43
+ uint64_t datap, uint32_t extra_size)
44
+{
45
+ __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic);
46
+ __put_user(sizeof(struct target_extra_context), &extra->head.size);
47
+ __put_user(datap, &extra->datap);
48
+ __put_user(extra_size, &extra->size);
49
+}
50
+
51
static void target_setup_end_record(struct target_aarch64_ctx *end)
52
{
53
__put_user(0, &end->magic);
54
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
55
static int target_restore_sigframe(CPUARMState *env,
56
struct target_rt_sigframe *sf)
57
{
58
- struct target_aarch64_ctx *ctx;
59
+ struct target_aarch64_ctx *ctx, *extra = NULL;
60
struct target_fpsimd_context *fpsimd = NULL;
61
+ uint64_t extra_datap = 0;
62
+ bool used_extra = false;
63
+ bool err = false;
64
65
target_restore_general_frame(env, sf);
66
67
ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved;
68
while (ctx) {
69
- uint32_t magic, size;
70
+ uint32_t magic, size, extra_size;
71
72
__get_user(magic, &ctx->magic);
73
__get_user(size, &ctx->size);
74
switch (magic) {
75
case 0:
76
if (size != 0) {
77
- return 1;
78
+ err = true;
79
+ goto exit;
80
+ }
81
+ if (used_extra) {
82
+ ctx = NULL;
83
+ } else {
84
+ ctx = extra;
85
+ used_extra = true;
86
}
87
- ctx = NULL;
88
continue;
89
90
case TARGET_FPSIMD_MAGIC:
91
if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
92
- return 1;
93
+ err = true;
94
+ goto exit;
95
}
96
fpsimd = (struct target_fpsimd_context *)ctx;
97
break;
98
99
+ case TARGET_EXTRA_MAGIC:
100
+ if (extra || size != sizeof(struct target_extra_context)) {
101
+ err = true;
102
+ goto exit;
103
+ }
104
+ __get_user(extra_datap,
105
+ &((struct target_extra_context *)ctx)->datap);
106
+ __get_user(extra_size,
107
+ &((struct target_extra_context *)ctx)->size);
108
+ extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
109
+ break;
110
+
111
default:
112
/* Unknown record -- we certainly didn't generate it.
113
* Did we in fact get out of sync?
114
*/
115
- return 1;
116
+ err = true;
117
+ goto exit;
118
}
119
ctx = (void *)ctx + size;
120
}
121
122
/* Require FPSIMD always. */
123
- if (!fpsimd) {
124
- return 1;
125
+ if (fpsimd) {
126
+ target_restore_fpsimd_record(env, fpsimd);
127
+ } else {
128
+ err = true;
129
}
130
- target_restore_fpsimd_record(env, fpsimd);
131
132
- return 0;
133
+ exit:
134
+ unlock_user(extra, extra_datap, 0);
135
+ return err;
136
}
137
138
static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
139
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
140
CPUARMState *env)
141
{
142
int size = offsetof(struct target_rt_sigframe, uc.tuc_mcontext.__reserved);
143
- int fpsimd_ofs, end1_ofs, fr_ofs;
144
+ int fpsimd_ofs, end1_ofs, fr_ofs, end2_ofs = 0;
145
+ int extra_ofs = 0, extra_base = 0, extra_size = 0;
146
struct target_rt_sigframe *frame;
147
struct target_rt_frame_record *fr;
148
abi_ulong frame_addr, return_addr;
149
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
150
151
target_setup_general_frame(frame, env, set);
152
target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
153
+ if (extra_ofs) {
154
+ target_setup_extra_record((void *)frame + extra_ofs,
155
+ frame_addr + extra_base, extra_size);
156
+ }
157
target_setup_end_record((void *)frame + end1_ofs);
158
+ if (end2_ofs) {
159
+ target_setup_end_record((void *)frame + end2_ofs);
160
+ }
161
162
/* Set up the stack frame for unwinding. */
163
fr = (void *)frame + fr_ofs;
164
--
165
2.16.2
166
167
diff view generated by jsdifflib
1
The MDCR_EL2.TDE bit allows the exception level targeted by debug
1
From: Richard Henderson <richard.henderson@linaro.org>
2
exceptions to be set to EL2 for code executing at EL0. We handle
2
3
this in the arm_debug_target_el() function, but this is only used for
3
Depending on the currently selected size of the SVE vector registers,
4
hardware breakpoint and watchpoint exceptions, not for the exception
4
we can either store the data within the "standard" allocation, or we
5
generated when the guest executes an AArch32 BKPT or AArch64 BRK
5
may beedn to allocate additional space with an EXTRA record.
6
instruction. We don't have enough information for a translate-time
6
7
equivalent of arm_debug_target_el(), so instead make BKPT and BRK
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
call a special purpose helper which can do the routing, rather than
8
Message-id: 20180303143823.27055-6-richard.henderson@linaro.org
9
the generic exception_with_syndrome helper.
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20180320134114.30418-2-peter.maydell@linaro.org
14
---
11
---
15
target/arm/helper.h | 1 +
12
linux-user/signal.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++-----
16
target/arm/op_helper.c | 8 ++++++++
13
1 file changed, 192 insertions(+), 18 deletions(-)
17
target/arm/translate-a64.c | 15 +++++++++++++--
14
18
target/arm/translate.c | 19 ++++++++++++++-----
15
diff --git a/linux-user/signal.c b/linux-user/signal.c
19
4 files changed, 36 insertions(+), 7 deletions(-)
20
21
diff --git a/target/arm/helper.h b/target/arm/helper.h
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.h
17
--- a/linux-user/signal.c
24
+++ b/target/arm/helper.h
18
+++ b/linux-user/signal.c
25
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
19
@@ -XXX,XX +XXX,XX @@ struct target_extra_context {
26
i32, i32, i32, i32)
20
uint32_t reserved[3];
27
DEF_HELPER_2(exception_internal, void, env, i32)
21
};
28
DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
22
29
+DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
23
+#define TARGET_SVE_MAGIC 0x53564501
30
DEF_HELPER_1(setend, void, env)
24
+
31
DEF_HELPER_2(wfi, void, env, i32)
25
+struct target_sve_context {
32
DEF_HELPER_1(wfe, void, env)
26
+ struct target_aarch64_ctx head;
33
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
27
+ uint16_t vl;
34
index XXXXXXX..XXXXXXX 100644
28
+ uint16_t reserved[3];
35
--- a/target/arm/op_helper.c
29
+ /* The actual SVE data immediately follows. It is layed out
36
+++ b/target/arm/op_helper.c
30
+ * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
37
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
31
+ * the original struct pointer.
38
raise_exception(env, excp, syndrome, target_el);
32
+ */
33
+};
34
+
35
+#define TARGET_SVE_VQ_BYTES 16
36
+
37
+#define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES)
38
+#define TARGET_SVE_SIG_PREG_SIZE(VQ) ((VQ) * (TARGET_SVE_VQ_BYTES / 8))
39
+
40
+#define TARGET_SVE_SIG_REGS_OFFSET \
41
+ QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES)
42
+#define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \
43
+ (TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N))
44
+#define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \
45
+ (TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N))
46
+#define TARGET_SVE_SIG_FFR_OFFSET(VQ) \
47
+ (TARGET_SVE_SIG_PREG_OFFSET(VQ, 16))
48
+#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
49
+ (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
50
+
51
struct target_rt_sigframe {
52
struct target_siginfo info;
53
struct target_ucontext uc;
54
@@ -XXX,XX +XXX,XX @@ static void target_setup_end_record(struct target_aarch64_ctx *end)
55
__put_user(0, &end->size);
39
}
56
}
40
57
41
+/* Raise an EXCP_BKPT with the specified syndrome register value,
58
+static void target_setup_sve_record(struct target_sve_context *sve,
42
+ * targeting the correct exception level for debug exceptions.
59
+ CPUARMState *env, int vq, int size)
43
+ */
44
+void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
45
+{
60
+{
46
+ raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env));
61
+ int i, j;
62
+
63
+ __put_user(TARGET_SVE_MAGIC, &sve->head.magic);
64
+ __put_user(size, &sve->head.size);
65
+ __put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
66
+
67
+ /* Note that SVE regs are stored as a byte stream, with each byte element
68
+ * at a subsequent address. This corresponds to a little-endian store
69
+ * of our 64-bit hunks.
70
+ */
71
+ for (i = 0; i < 32; ++i) {
72
+ uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
73
+ for (j = 0; j < vq * 2; ++j) {
74
+ __put_user_e(env->vfp.zregs[i].d[j], z + j, le);
75
+ }
76
+ }
77
+ for (i = 0; i <= 16; ++i) {
78
+ uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
79
+ for (j = 0; j < vq; ++j) {
80
+ uint64_t r = env->vfp.pregs[i].p[j >> 2];
81
+ __put_user_e(r >> ((j & 3) * 16), p + j, le);
82
+ }
83
+ }
47
+}
84
+}
48
+
85
+
49
uint32_t HELPER(cpsr_read)(CPUARMState *env)
86
static void target_restore_general_frame(CPUARMState *env,
87
struct target_rt_sigframe *sf)
50
{
88
{
51
return cpsr_read(env) & ~(CPSR_EXEC | CPSR_RESERVED);
89
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
52
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
}
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/translate-a64.c
55
+++ b/target/arm/translate-a64.c
56
@@ -XXX,XX +XXX,XX @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
57
s->base.is_jmp = DISAS_NORETURN;
58
}
91
}
59
92
60
+static void gen_exception_bkpt_insn(DisasContext *s, int offset,
93
+static void target_restore_sve_record(CPUARMState *env,
61
+ uint32_t syndrome)
94
+ struct target_sve_context *sve, int vq)
62
+{
95
+{
63
+ TCGv_i32 tcg_syn;
96
+ int i, j;
64
+
97
+
65
+ gen_a64_set_pc_im(s->pc - offset);
98
+ /* Note that SVE regs are stored as a byte stream, with each byte element
66
+ tcg_syn = tcg_const_i32(syndrome);
99
+ * at a subsequent address. This corresponds to a little-endian load
67
+ gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
100
+ * of our 64-bit hunks.
68
+ tcg_temp_free_i32(tcg_syn);
101
+ */
69
+ s->base.is_jmp = DISAS_NORETURN;
102
+ for (i = 0; i < 32; ++i) {
103
+ uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
104
+ for (j = 0; j < vq * 2; ++j) {
105
+ __get_user_e(env->vfp.zregs[i].d[j], z + j, le);
106
+ }
107
+ }
108
+ for (i = 0; i <= 16; ++i) {
109
+ uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
110
+ for (j = 0; j < vq; ++j) {
111
+ uint16_t r;
112
+ __get_user_e(r, p + j, le);
113
+ if (j & 3) {
114
+ env->vfp.pregs[i].p[j >> 2] |= (uint64_t)r << ((j & 3) * 16);
115
+ } else {
116
+ env->vfp.pregs[i].p[j >> 2] = r;
117
+ }
118
+ }
119
+ }
70
+}
120
+}
71
+
121
+
72
static void gen_ss_advance(DisasContext *s)
122
static int target_restore_sigframe(CPUARMState *env,
123
struct target_rt_sigframe *sf)
73
{
124
{
74
/* If the singlestep state is Active-not-pending, advance to
125
struct target_aarch64_ctx *ctx, *extra = NULL;
75
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
126
struct target_fpsimd_context *fpsimd = NULL;
127
+ struct target_sve_context *sve = NULL;
128
uint64_t extra_datap = 0;
129
bool used_extra = false;
130
bool err = false;
131
+ int vq = 0, sve_size = 0;
132
133
target_restore_general_frame(env, sf);
134
135
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
136
fpsimd = (struct target_fpsimd_context *)ctx;
76
break;
137
break;
77
}
138
78
/* BRK */
139
+ case TARGET_SVE_MAGIC:
79
- gen_exception_insn(s, 4, EXCP_BKPT, syn_aa64_bkpt(imm16),
140
+ if (arm_feature(env, ARM_FEATURE_SVE)) {
80
- default_exception_el(s));
141
+ vq = (env->vfp.zcr_el[1] & 0xf) + 1;
81
+ gen_exception_bkpt_insn(s, 4, syn_aa64_bkpt(imm16));
142
+ sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
82
break;
143
+ if (!sve && size == sve_size) {
83
case 2:
144
+ sve = (struct target_sve_context *)ctx;
84
if (op2_ll != 0) {
145
+ break;
85
diff --git a/target/arm/translate.c b/target/arm/translate.c
146
+ }
86
index XXXXXXX..XXXXXXX 100644
147
+ }
87
--- a/target/arm/translate.c
148
+ err = true;
88
+++ b/target/arm/translate.c
149
+ goto exit;
89
@@ -XXX,XX +XXX,XX @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
150
+
90
s->base.is_jmp = DISAS_NORETURN;
151
case TARGET_EXTRA_MAGIC:
152
if (extra || size != sizeof(struct target_extra_context)) {
153
err = true;
154
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
155
err = true;
156
}
157
158
+ /* SVE data, if present, overwrites FPSIMD data. */
159
+ if (sve) {
160
+ target_restore_sve_record(env, sve, vq);
161
+ }
162
+
163
exit:
164
unlock_user(extra, extra_datap, 0);
165
return err;
91
}
166
}
92
167
93
+static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
168
-static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
169
+static abi_ulong get_sigframe(struct target_sigaction *ka,
170
+ CPUARMState *env, int size)
171
{
172
abi_ulong sp;
173
174
@@ -XXX,XX +XXX,XX @@ static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
175
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
176
}
177
178
- sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
179
+ sp = (sp - size) & ~15;
180
181
return sp;
182
}
183
184
+typedef struct {
185
+ int total_size;
186
+ int extra_base;
187
+ int extra_size;
188
+ int std_end_ofs;
189
+ int extra_ofs;
190
+ int extra_end_ofs;
191
+} target_sigframe_layout;
192
+
193
+static int alloc_sigframe_space(int this_size, target_sigframe_layout *l)
94
+{
194
+{
95
+ TCGv_i32 tcg_syn;
195
+ /* Make sure there will always be space for the end marker. */
96
+
196
+ const int std_size = sizeof(struct target_rt_sigframe)
97
+ gen_set_condexec(s);
197
+ - sizeof(struct target_aarch64_ctx);
98
+ gen_set_pc_im(s, s->pc - offset);
198
+ int this_loc = l->total_size;
99
+ tcg_syn = tcg_const_i32(syn);
199
+
100
+ gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
200
+ if (l->extra_base) {
101
+ tcg_temp_free_i32(tcg_syn);
201
+ /* Once we have begun an extra space, all allocations go there. */
102
+ s->base.is_jmp = DISAS_NORETURN;
202
+ l->extra_size += this_size;
203
+ } else if (this_size + this_loc > std_size) {
204
+ /* This allocation does not fit in the standard space. */
205
+ /* Allocate the extra record. */
206
+ l->extra_ofs = this_loc;
207
+ l->total_size += sizeof(struct target_extra_context);
208
+
209
+ /* Allocate the standard end record. */
210
+ l->std_end_ofs = l->total_size;
211
+ l->total_size += sizeof(struct target_aarch64_ctx);
212
+
213
+ /* Allocate the requested record. */
214
+ l->extra_base = this_loc = l->total_size;
215
+ l->extra_size = this_size;
216
+ }
217
+ l->total_size += this_size;
218
+
219
+ return this_loc;
103
+}
220
+}
104
+
221
+
105
/* Force a TB lookup after an instruction that changes the CPU state. */
222
static void target_setup_frame(int usig, struct target_sigaction *ka,
106
static inline void gen_lookup_tb(DisasContext *s)
223
target_siginfo_t *info, target_sigset_t *set,
224
CPUARMState *env)
107
{
225
{
108
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
226
- int size = offsetof(struct target_rt_sigframe, uc.tuc_mcontext.__reserved);
109
case 1:
227
- int fpsimd_ofs, end1_ofs, fr_ofs, end2_ofs = 0;
110
/* bkpt */
228
- int extra_ofs = 0, extra_base = 0, extra_size = 0;
111
ARCH(5);
229
+ target_sigframe_layout layout = {
112
- gen_exception_insn(s, 4, EXCP_BKPT,
230
+ /* Begin with the size pointing to the reserved space. */
113
- syn_aa32_bkpt(imm16, false),
231
+ .total_size = offsetof(struct target_rt_sigframe,
114
- default_exception_el(s));
232
+ uc.tuc_mcontext.__reserved),
115
+ gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
233
+ };
116
break;
234
+ int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
117
case 2:
235
struct target_rt_sigframe *frame;
118
/* Hypervisor call (v7) */
236
struct target_rt_frame_record *fr;
119
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
237
abi_ulong frame_addr, return_addr;
120
{
238
121
int imm8 = extract32(insn, 0, 8);
239
- fpsimd_ofs = size;
122
ARCH(5);
240
- size += sizeof(struct target_fpsimd_context);
123
- gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true),
241
- end1_ofs = size;
124
- default_exception_el(s));
242
- size += sizeof(struct target_aarch64_ctx);
125
+ gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
243
- fr_ofs = size;
126
break;
244
- size += sizeof(struct target_rt_frame_record);
127
}
245
+ /* FPSIMD record is always in the standard space. */
128
246
+ fpsimd_ofs = alloc_sigframe_space(sizeof(struct target_fpsimd_context),
247
+ &layout);
248
249
- frame_addr = get_sigframe(ka, env);
250
+ /* SVE state needs saving only if it exists. */
251
+ if (arm_feature(env, ARM_FEATURE_SVE)) {
252
+ vq = (env->vfp.zcr_el[1] & 0xf) + 1;
253
+ sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
254
+ sve_ofs = alloc_sigframe_space(sve_size, &layout);
255
+ }
256
+
257
+ if (layout.extra_ofs) {
258
+ /* Reserve space for the extra end marker. The standard end marker
259
+ * will have been allocated when we allocated the extra record.
260
+ */
261
+ layout.extra_end_ofs
262
+ = alloc_sigframe_space(sizeof(struct target_aarch64_ctx), &layout);
263
+ } else {
264
+ /* Reserve space for the standard end marker.
265
+ * Do not use alloc_sigframe_space because we cheat
266
+ * std_size therein to reserve space for this.
267
+ */
268
+ layout.std_end_ofs = layout.total_size;
269
+ layout.total_size += sizeof(struct target_aarch64_ctx);
270
+ }
271
+
272
+ /* Reserve space for the return code. On a real system this would
273
+ * be within the VDSO. So, despite the name this is not a "real"
274
+ * record within the frame.
275
+ */
276
+ fr_ofs = layout.total_size;
277
+ layout.total_size += sizeof(struct target_rt_frame_record);
278
+
279
+ frame_addr = get_sigframe(ka, env, layout.total_size);
280
trace_user_setup_frame(env, frame_addr);
281
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
282
goto give_sigsegv;
283
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
284
285
target_setup_general_frame(frame, env, set);
286
target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
287
- if (extra_ofs) {
288
- target_setup_extra_record((void *)frame + extra_ofs,
289
- frame_addr + extra_base, extra_size);
290
+ target_setup_end_record((void *)frame + layout.std_end_ofs);
291
+ if (layout.extra_ofs) {
292
+ target_setup_extra_record((void *)frame + layout.extra_ofs,
293
+ frame_addr + layout.extra_base,
294
+ layout.extra_size);
295
+ target_setup_end_record((void *)frame + layout.extra_end_ofs);
296
}
297
- target_setup_end_record((void *)frame + end1_ofs);
298
- if (end2_ofs) {
299
- target_setup_end_record((void *)frame + end2_ofs);
300
+ if (sve_ofs) {
301
+ target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
302
}
303
304
/* Set up the stack frame for unwinding. */
129
--
305
--
130
2.16.2
306
2.16.2
131
307
132
308
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
A lot of ARM object files are linked into the executable unconditionally,
4
even though we have corresponding CONFIG switches like CONFIG_PXA2XX or
5
CONFIG_OMAP. We should make sure to use these switches in the Makefile so
6
that the users can disable certain unwanted boards and devices more easily.
7
While we're at it, also add some new switches for the boards that do not
8
have a CONFIG option yet.
9
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
11
Message-id: 1520266949-29817-1-git-send-email-thuth@redhat.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
hw/arm/Makefile.objs | 30 +++++++++++++++++++++---------
17
default-configs/arm-softmmu.mak | 7 +++++++
18
2 files changed, 28 insertions(+), 9 deletions(-)
19
20
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/Makefile.objs
23
+++ b/hw/arm/Makefile.objs
24
@@ -XXX,XX +XXX,XX @@
25
-obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
26
-obj-$(CONFIG_DIGIC) += digic_boards.o
27
-obj-y += integratorcp.o mainstone.o musicpal.o nseries.o
28
-obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
29
-obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
30
+obj-y += boot.o virt.o sysbus-fdt.o
31
obj-$(CONFIG_ACPI) += virt-acpi-build.o
32
-obj-y += netduino2.o
33
-obj-y += sysbus-fdt.o
34
+obj-$(CONFIG_DIGIC) += digic_boards.o
35
+obj-$(CONFIG_EXYNOS4) += exynos4_boards.o
36
+obj-$(CONFIG_HIGHBANK) += highbank.o
37
+obj-$(CONFIG_INTEGRATOR) += integratorcp.o
38
+obj-$(CONFIG_MAINSTONE) += mainstone.o
39
+obj-$(CONFIG_MUSICPAL) += musicpal.o
40
+obj-$(CONFIG_NETDUINO2) += netduino2.o
41
+obj-$(CONFIG_NSERIES) += nseries.o
42
+obj-$(CONFIG_OMAP) += omap_sx1.o palm.o
43
+obj-$(CONFIG_PXA2XX) += gumstix.o spitz.o tosa.o z2.o
44
+obj-$(CONFIG_REALVIEW) += realview.o
45
+obj-$(CONFIG_STELLARIS) += stellaris.o
46
+obj-$(CONFIG_STRONGARM) += collie.o
47
+obj-$(CONFIG_VERSATILE) += vexpress.o versatilepb.o
48
+obj-$(CONFIG_ZYNQ) += xilinx_zynq.o
49
50
-obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
51
+obj-$(CONFIG_ARM_V7M) += armv7m.o
52
+obj-$(CONFIG_EXYNOS4) += exynos4210.o
53
+obj-$(CONFIG_PXA2XX) += pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
54
obj-$(CONFIG_DIGIC) += digic.o
55
-obj-y += omap1.o omap2.o strongarm.o
56
+obj-$(CONFIG_OMAP) += omap1.o omap2.o
57
+obj-$(CONFIG_STRONGARM) += strongarm.o
58
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
59
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
60
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
61
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
62
index XXXXXXX..XXXXXXX 100644
63
--- a/default-configs/arm-softmmu.mak
64
+++ b/default-configs/arm-softmmu.mak
65
@@ -XXX,XX +XXX,XX @@ CONFIG_A9MPCORE=y
66
CONFIG_A15MPCORE=y
67
68
CONFIG_ARM_V7M=y
69
+CONFIG_NETDUINO2=y
70
71
CONFIG_ARM_GIC=y
72
CONFIG_ARM_GIC_KVM=$(CONFIG_KVM)
73
@@ -XXX,XX +XXX,XX @@ CONFIG_TZ_PPC=y
74
CONFIG_IOTKIT=y
75
CONFIG_IOTKIT_SECCTL=y
76
77
+CONFIG_VERSATILE=y
78
CONFIG_VERSATILE_PCI=y
79
CONFIG_VERSATILE_I2C=y
80
81
@@ -XXX,XX +XXX,XX @@ CONFIG_VFIO_XGMAC=y
82
CONFIG_VFIO_AMD_XGBE=y
83
84
CONFIG_SDHCI=y
85
+CONFIG_INTEGRATOR=y
86
CONFIG_INTEGRATOR_DEBUG=y
87
88
CONFIG_ALLWINNER_A10_PIT=y
89
@@ -XXX,XX +XXX,XX @@ CONFIG_MSF2=y
90
CONFIG_FW_CFG_DMA=y
91
CONFIG_XILINX_AXI=y
92
CONFIG_PCI_DESIGNWARE=y
93
+
94
+CONFIG_STRONGARM=y
95
+CONFIG_HIGHBANK=y
96
+CONFIG_MUSICPAL=y
97
--
98
2.16.2
99
100
diff view generated by jsdifflib
New patch
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
1
2
3
Spotted by ASAN:
4
QTEST_QEMU_BINARY=aarch64-softmmu/qemu-system-aarch64 tests/boot-serial-test
5
6
Direct leak of 48 byte(s) in 1 object(s) allocated from:
7
#0 0x7ff8a9b0ca38 in __interceptor_calloc (/lib64/libasan.so.4+0xdea38)
8
#1 0x7ff8a8ea7f75 in g_malloc0 ../glib/gmem.c:124
9
#2 0x55fef3d99129 in error_setv /home/elmarco/src/qemu/util/error.c:59
10
#3 0x55fef3d99738 in error_setg_internal /home/elmarco/src/qemu/util/error.c:95
11
#4 0x55fef323acb2 in load_elf_hdr /home/elmarco/src/qemu/hw/core/loader.c:393
12
#5 0x55fef2d15776 in arm_load_elf /home/elmarco/src/qemu/hw/arm/boot.c:830
13
#6 0x55fef2d16d39 in arm_load_kernel_notify /home/elmarco/src/qemu/hw/arm/boot.c:1022
14
#7 0x55fef3dc634d in notifier_list_notify /home/elmarco/src/qemu/util/notify.c:40
15
#8 0x55fef2fc3182 in qemu_run_machine_init_done_notifiers /home/elmarco/src/qemu/vl.c:2716
16
#9 0x55fef2fcbbd1 in main /home/elmarco/src/qemu/vl.c:4679
17
#10 0x7ff89dfed009 in __libc_start_main (/lib64/libc.so.6+0x21009)
18
19
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/arm/boot.c | 1 +
24
1 file changed, 1 insertion(+)
25
26
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/boot.c
29
+++ b/hw/arm/boot.c
30
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
31
32
load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err);
33
if (err) {
34
+ error_free(err);
35
return ret;
36
}
37
38
--
39
2.16.2
40
41
diff view generated by jsdifflib
New patch
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
1
2
3
Spotted by ASAN:
4
5
elmarco@boraha:~/src/qemu/build (master *%)$ QTEST_QEMU_BINARY=aarch64-softmmu/qemu-system-aarch64 tests/boot-serial-test
6
/aarch64/boot-serial/virt: ** (process:19740): DEBUG: 18:39:30.275: foo /tmp/qtest-boot-serial-cXaS94D
7
=================================================================
8
==19740==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000069648 at pc 0x7f1d2201cc54 bp 0x7fff331f6a40 sp 0x7fff331f61e8
9
READ of size 4 at 0x603000069648 thread T0
10
#0 0x7f1d2201cc53 (/lib64/libasan.so.4+0xafc53)
11
#1 0x55bc86685ee3 in load_aarch64_image /home/elmarco/src/qemu/hw/arm/boot.c:894
12
#2 0x55bc86687217 in arm_load_kernel_notify /home/elmarco/src/qemu/hw/arm/boot.c:1047
13
#3 0x55bc877363b5 in notifier_list_notify /home/elmarco/src/qemu/util/notify.c:40
14
#4 0x55bc869331ea in qemu_run_machine_init_done_notifiers /home/elmarco/src/qemu/vl.c:2716
15
#5 0x55bc8693bc39 in main /home/elmarco/src/qemu/vl.c:4679
16
#6 0x7f1d1652c009 in __libc_start_main (/lib64/libc.so.6+0x21009)
17
#7 0x55bc86255cc9 in _start (/home/elmarco/src/qemu/build/aarch64-softmmu/qemu-system-aarch64+0x1ae5cc9)
18
19
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/arm/boot.c | 3 ++-
24
1 file changed, 2 insertions(+), 1 deletion(-)
25
26
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/boot.c
29
+++ b/hw/arm/boot.c
30
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
31
}
32
33
/* check the arm64 magic header value -- very old kernels may not have it */
34
- if (memcmp(buffer + ARM64_MAGIC_OFFSET, "ARM\x64", 4) == 0) {
35
+ if (size > ARM64_MAGIC_OFFSET + 4 &&
36
+ memcmp(buffer + ARM64_MAGIC_OFFSET, "ARM\x64", 4) == 0) {
37
uint64_t hdrvals[2];
38
39
/* The arm64 Image header has text_offset and image_size fields at 8 and
40
--
41
2.16.2
42
43
diff view generated by jsdifflib
1
For debug exceptions due to breakpoints or the BKPT instruction which
1
Currently we query the host CPU features in the class init function
2
are taken to AArch32, the Fault Address Register is architecturally
2
for the TYPE_ARM_HOST_CPU class, so that we can later copy them
3
UNKNOWN. We were using that as license to simply not set
3
from the class object into the instance object in the object
4
env->exception.vaddress, but this isn't correct, because it will
4
instance init function. This is awkward for implementing "-cpu max",
5
expose to the guest whatever old value was in that field when
5
which should work like "-cpu host" for KVM but like "cpu with all
6
arm_cpu_do_interrupt_aarch32() writes it to the guest IFSR. That old
6
implemented features" for TCG.
7
value might be a FAR for a previous guest EL2 or secure exception, in
7
8
which case we shouldn't show it to an EL1 or non-secure exception
8
Move the place where we store the information about the host CPU from
9
handler. It might also be a non-deterministic value, which is bad
9
a class object to static variables in kvm.c, and then in the instance
10
for record-and-replay.
10
init function call a new kvm_arm_set_cpu_features_from_host()
11
11
function which will query the host kernel if necessary and then
12
Clear env->exception.vaddress before taking breakpoint debug
12
fill in the CPU instance fields.
13
exceptions, to avoid this minor information leak.
13
14
This allows us to drop the special class struct and class init
15
function for TYPE_ARM_HOST_CPU entirely.
16
17
We can't delay the probe until realize, because the ARM
18
instance_post_init hook needs to look at the feature bits we
19
set, so we need to do it in the initfn. This is safe because
20
the probing doesn't affect the actual VM state (it creates a
21
separate scratch VM to do its testing), but the probe might fail.
22
Because we can't report errors in retrieving the host features
23
in the initfn, we check this belatedly in the realize function
24
(the intervening code will be able to cope with the relevant
25
fields in the CPU structure being zero).
14
26
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
28
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20180320134114.30418-5-peter.maydell@linaro.org
29
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
30
Message-id: 20180308130626.12393-2-peter.maydell@linaro.org
18
---
31
---
19
target/arm/op_helper.c | 11 ++++++++++-
32
target/arm/cpu.h | 5 +++++
20
1 file changed, 10 insertions(+), 1 deletion(-)
33
target/arm/kvm_arm.h | 35 ++++++++++++++++++++++++-----------
21
34
target/arm/cpu.c | 13 +++++++++++++
22
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
35
target/arm/kvm.c | 36 +++++++++++++++++++-----------------
23
index XXXXXXX..XXXXXXX 100644
36
target/arm/kvm32.c | 8 ++++----
24
--- a/target/arm/op_helper.c
37
target/arm/kvm64.c | 8 ++++----
25
+++ b/target/arm/op_helper.c
38
6 files changed, 69 insertions(+), 36 deletions(-)
26
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
39
27
{
40
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
28
/* FSR will only be used if the debug target EL is AArch32. */
41
index XXXXXXX..XXXXXXX 100644
29
env->exception.fsr = arm_debug_exception_fsr(env);
42
--- a/target/arm/cpu.h
30
+ /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
43
+++ b/target/arm/cpu.h
31
+ * values to the guest that it shouldn't be able to see at its
44
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
32
+ * exception/security level.
45
/* Uniprocessor system with MP extensions */
46
bool mp_is_up;
47
48
+ /* True if we tried kvm_arm_host_cpu_features() during CPU instance_init
49
+ * and the probe failed (so we need to report the error in realize)
33
+ */
50
+ */
34
+ env->exception.vaddress = 0;
51
+ bool host_cpu_probe_failed;
35
raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env));
52
+
36
}
53
/* Specify the number of cores in this CPU cluster. Used for the L2CTLR
37
54
* register.
38
@@ -XXX,XX +XXX,XX @@ void arm_debug_excp_handler(CPUState *cs)
55
*/
39
}
56
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
40
57
index XXXXXXX..XXXXXXX 100644
41
env->exception.fsr = arm_debug_exception_fsr(env);
58
--- a/target/arm/kvm_arm.h
42
- /* FAR is UNKNOWN, so doesn't need setting */
59
+++ b/target/arm/kvm_arm.h
43
+ /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
60
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
44
+ * values to the guest that it shouldn't be able to see at its
61
void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
45
+ * exception/security level.
62
46
+ */
63
#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
47
+ env->exception.vaddress = 0;
64
-#define ARM_HOST_CPU_CLASS(klass) \
48
raise_exception(env, EXCP_PREFETCH_ABORT,
65
- OBJECT_CLASS_CHECK(ARMHostCPUClass, (klass), TYPE_ARM_HOST_CPU)
49
syn_breakpoint(same_el),
66
-#define ARM_HOST_CPU_GET_CLASS(obj) \
50
arm_debug_target_el(env));
67
- OBJECT_GET_CLASS(ARMHostCPUClass, (obj), TYPE_ARM_HOST_CPU)
68
-
69
-typedef struct ARMHostCPUClass {
70
- /*< private >*/
71
- ARMCPUClass parent_class;
72
- /*< public >*/
73
74
+/**
75
+ * ARMHostCPUFeatures: information about the host CPU (identified
76
+ * by asking the host kernel)
77
+ */
78
+typedef struct ARMHostCPUFeatures {
79
uint64_t features;
80
uint32_t target;
81
const char *dtb_compatible;
82
-} ARMHostCPUClass;
83
+} ARMHostCPUFeatures;
84
85
/**
86
* kvm_arm_get_host_cpu_features:
87
@@ -XXX,XX +XXX,XX @@ typedef struct ARMHostCPUClass {
88
* Probe the capabilities of the host kernel's preferred CPU and fill
89
* in the ARMHostCPUClass struct accordingly.
90
*/
91
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc);
92
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
93
94
+/**
95
+ * kvm_arm_set_cpu_features_from_host:
96
+ * @cpu: ARMCPU to set the features for
97
+ *
98
+ * Set up the ARMCPU struct fields up to match the information probed
99
+ * from the host CPU.
100
+ */
101
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
102
103
/**
104
* kvm_arm_sync_mpstate_to_kvm
105
@@ -XXX,XX +XXX,XX @@ void kvm_arm_pmu_init(CPUState *cs);
106
107
#else
108
109
+static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
110
+{
111
+ /* This should never actually be called in the "not KVM" case,
112
+ * but set up the fields to indicate an error anyway.
113
+ */
114
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
115
+ cpu->host_cpu_probe_failed = true;
116
+}
117
+
118
static inline int kvm_arm_vgic_probe(void)
119
{
120
return 0;
121
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/target/arm/cpu.c
124
+++ b/target/arm/cpu.c
125
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
126
int pagebits;
127
Error *local_err = NULL;
128
129
+ /* If we needed to query the host kernel for the CPU features
130
+ * then it's possible that might have failed in the initfn, but
131
+ * this is the first point where we can report it.
132
+ */
133
+ if (cpu->host_cpu_probe_failed) {
134
+ if (!kvm_enabled()) {
135
+ error_setg(errp, "The 'host' CPU type can only be used with KVM");
136
+ } else {
137
+ error_setg(errp, "Failed to retrieve host CPU features");
138
+ }
139
+ return;
140
+ }
141
+
142
cpu_exec_realizefn(cs, &local_err);
143
if (local_err != NULL) {
144
error_propagate(errp, local_err);
145
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/arm/kvm.c
148
+++ b/target/arm/kvm.c
149
@@ -XXX,XX +XXX,XX @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
150
151
static bool cap_has_mp_state;
152
153
+static ARMHostCPUFeatures arm_host_cpu_features;
154
+
155
int kvm_arm_vcpu_init(CPUState *cs)
156
{
157
ARMCPU *cpu = ARM_CPU(cs);
158
@@ -XXX,XX +XXX,XX @@ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray)
159
}
160
}
161
162
-static void kvm_arm_host_cpu_class_init(ObjectClass *oc, void *data)
163
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
164
{
165
- ARMHostCPUClass *ahcc = ARM_HOST_CPU_CLASS(oc);
166
+ CPUARMState *env = &cpu->env;
167
168
- /* All we really need to set up for the 'host' CPU
169
- * is the feature bits -- we rely on the fact that the
170
- * various ID register values in ARMCPU are only used for
171
- * TCG CPUs.
172
- */
173
- if (!kvm_arm_get_host_cpu_features(ahcc)) {
174
- fprintf(stderr, "Failed to retrieve host CPU features!\n");
175
- abort();
176
+ if (!arm_host_cpu_features.dtb_compatible) {
177
+ if (!kvm_enabled() ||
178
+ !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) {
179
+ /* We can't report this error yet, so flag that we need to
180
+ * in arm_cpu_realizefn().
181
+ */
182
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
183
+ cpu->host_cpu_probe_failed = true;
184
+ return;
185
+ }
186
}
187
+
188
+ cpu->kvm_target = arm_host_cpu_features.target;
189
+ cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible;
190
+ env->features = arm_host_cpu_features.features;
191
}
192
193
static void kvm_arm_host_cpu_initfn(Object *obj)
194
{
195
- ARMHostCPUClass *ahcc = ARM_HOST_CPU_GET_CLASS(obj);
196
ARMCPU *cpu = ARM_CPU(obj);
197
- CPUARMState *env = &cpu->env;
198
199
- cpu->kvm_target = ahcc->target;
200
- cpu->dtb_compatible = ahcc->dtb_compatible;
201
- env->features = ahcc->features;
202
+ kvm_arm_set_cpu_features_from_host(cpu);
203
}
204
205
static const TypeInfo host_arm_cpu_type_info = {
206
@@ -XXX,XX +XXX,XX @@ static const TypeInfo host_arm_cpu_type_info = {
207
.parent = TYPE_ARM_CPU,
208
#endif
209
.instance_init = kvm_arm_host_cpu_initfn,
210
- .class_init = kvm_arm_host_cpu_class_init,
211
- .class_size = sizeof(ARMHostCPUClass),
212
};
213
214
int kvm_arch_init(MachineState *ms, KVMState *s)
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 @@ static inline void set_feature(uint64_t *features, int feature)
220
*features |= 1ULL << feature;
221
}
222
223
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
224
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
225
{
226
/* Identify the feature bits corresponding to the host CPU, and
227
* fill out the ARMHostCPUClass fields accordingly. To do this
228
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
229
return false;
230
}
231
232
- ahcc->target = init.target;
233
+ ahcf->target = init.target;
234
235
/* This is not strictly blessed by the device tree binding docs yet,
236
* but in practice the kernel does not care about this string so
237
* there is no point maintaining an KVM_ARM_TARGET_* -> string table.
238
*/
239
- ahcc->dtb_compatible = "arm,arm-v7";
240
+ ahcf->dtb_compatible = "arm,arm-v7";
241
242
for (i = 0; i < ARRAY_SIZE(idregs); i++) {
243
ret = ioctl(fdarray[2], KVM_GET_ONE_REG, &idregs[i]);
244
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
245
set_feature(&features, ARM_FEATURE_VFP4);
246
}
247
248
- ahcc->features = features;
249
+ ahcf->features = features;
250
251
return true;
252
}
253
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
254
index XXXXXXX..XXXXXXX 100644
255
--- a/target/arm/kvm64.c
256
+++ b/target/arm/kvm64.c
257
@@ -XXX,XX +XXX,XX @@ static inline void unset_feature(uint64_t *features, int feature)
258
*features &= ~(1ULL << feature);
259
}
260
261
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
262
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
263
{
264
/* Identify the feature bits corresponding to the host CPU, and
265
* fill out the ARMHostCPUClass fields accordingly. To do this
266
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
267
return false;
268
}
269
270
- ahcc->target = init.target;
271
- ahcc->dtb_compatible = "arm,arm-v8";
272
+ ahcf->target = init.target;
273
+ ahcf->dtb_compatible = "arm,arm-v8";
274
275
kvm_arm_destroy_scratch_host_vcpu(fdarray);
276
277
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
278
set_feature(&features, ARM_FEATURE_AARCH64);
279
set_feature(&features, ARM_FEATURE_PMU);
280
281
- ahcc->features = features;
282
+ ahcf->features = features;
283
284
return true;
285
}
51
--
286
--
52
2.16.2
287
2.16.2
53
288
54
289
diff view generated by jsdifflib
1
Now that we have a helper function specifically for the BRK and
1
Move the definition of the 'host' cpu type into cpu.c, where all the
2
BKPT instructions, we can set the exception.fsr there rather
2
other CPU types are defined. We can do this now we've decoupled it
3
than in arm_cpu_do_interrupt_aarch32(). This allows us to
3
from the KVM-specific host feature probing. This means we now create
4
use our new arm_debug_exception_fsr() helper.
4
the type unconditionally (assuming we were built with KVM support at
5
all), but if you try to use it without -enable-kvm this will end
6
up in the "host cpu probe failed and KVM not enabled" path in
7
arm_cpu_realizefn(), for an appropriate error message.
5
8
6
In particular this fixes a bug where we were hardcoding the
7
short-form IFSR value, which is wrong if the target exception
8
level has LPAE enabled.
9
10
Fixes: https://bugs.launchpad.net/qemu/+bug/1756927
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20180320134114.30418-4-peter.maydell@linaro.org
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Message-id: 20180308130626.12393-3-peter.maydell@linaro.org
14
---
13
---
15
target/arm/helper.c | 1 -
14
target/arm/cpu.c | 24 ++++++++++++++++++++++++
16
target/arm/op_helper.c | 2 ++
15
target/arm/kvm.c | 19 -------------------
17
2 files changed, 2 insertions(+), 1 deletion(-)
16
2 files changed, 24 insertions(+), 19 deletions(-)
18
17
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
20
--- a/target/arm/cpu.c
22
+++ b/target/arm/helper.c
21
+++ b/target/arm/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
22
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
24
offset = 0;
23
#endif
25
break;
24
}
26
case EXCP_BKPT:
25
27
- env->exception.fsr = 2;
26
+#ifdef CONFIG_KVM
28
/* Fall through to prefetch abort. */
27
+static void arm_host_initfn(Object *obj)
29
case EXCP_PREFETCH_ABORT:
28
+{
30
A32_BANKED_CURRENT_REG_SET(env, ifsr, env->exception.fsr);
29
+ ARMCPU *cpu = ARM_CPU(obj);
31
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
30
+
31
+ kvm_arm_set_cpu_features_from_host(cpu);
32
+}
33
+
34
+static const TypeInfo host_arm_cpu_type_info = {
35
+ .name = TYPE_ARM_HOST_CPU,
36
+#ifdef TARGET_AARCH64
37
+ .parent = TYPE_AARCH64_CPU,
38
+#else
39
+ .parent = TYPE_ARM_CPU,
40
+#endif
41
+ .instance_init = arm_host_initfn,
42
+};
43
+
44
+#endif
45
+
46
static void cpu_register(const ARMCPUInfo *info)
47
{
48
TypeInfo type_info = {
49
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
50
cpu_register(info);
51
info++;
52
}
53
+
54
+#ifdef CONFIG_KVM
55
+ type_register_static(&host_arm_cpu_type_info);
56
+#endif
57
}
58
59
type_init(arm_cpu_register_types)
60
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
32
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/op_helper.c
62
--- a/target/arm/kvm.c
34
+++ b/target/arm/op_helper.c
63
+++ b/target/arm/kvm.c
35
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
64
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
36
*/
65
env->features = arm_host_cpu_features.features;
37
void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
66
}
67
68
-static void kvm_arm_host_cpu_initfn(Object *obj)
69
-{
70
- ARMCPU *cpu = ARM_CPU(obj);
71
-
72
- kvm_arm_set_cpu_features_from_host(cpu);
73
-}
74
-
75
-static const TypeInfo host_arm_cpu_type_info = {
76
- .name = TYPE_ARM_HOST_CPU,
77
-#ifdef TARGET_AARCH64
78
- .parent = TYPE_AARCH64_CPU,
79
-#else
80
- .parent = TYPE_ARM_CPU,
81
-#endif
82
- .instance_init = kvm_arm_host_cpu_initfn,
83
-};
84
-
85
int kvm_arch_init(MachineState *ms, KVMState *s)
38
{
86
{
39
+ /* FSR will only be used if the debug target EL is AArch32. */
87
/* For ARM interrupt delivery is always asynchronous,
40
+ env->exception.fsr = arm_debug_exception_fsr(env);
88
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init(MachineState *ms, KVMState *s)
41
raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env));
89
90
cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
91
92
- type_register_static(&host_arm_cpu_type_info);
93
-
94
return 0;
42
}
95
}
43
96
44
--
97
--
45
2.16.2
98
2.16.2
46
99
47
100
diff view generated by jsdifflib
1
When a debug exception is taken to AArch32, it appears as a Prefetch
1
Add support for "-cpu max" for ARM guests. This CPU type behaves
2
Abort, and the Instruction Fault Status Register (IFSR) must be set.
2
like "-cpu host" when KVM is enabled, and like a system CPU with
3
The IFSR has two possible formats, depending on whether LPAE is in
3
the maximum possible feature set otherwise. (Note that this means
4
use. Factor out the code in arm_debug_excp_handler() which picks
4
it won't be migratable across versions, as we will likely add
5
an FSR value into its own utility function, update it to use
5
features to it in future.)
6
arm_fi_to_lfsc() and arm_fi_to_sfsc() rather than hard-coded constants,
7
and use the correct condition to select long or short format.
8
9
In particular this fixes a bug where we could select the short
10
format because we're at EL0 and the EL1 translation regime is
11
not using LPAE, but then route the debug exception to EL2 because
12
of MDCR_EL2.TDE and hand EL2 the wrong format FSR.
13
6
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
16
Message-id: 20180320134114.30418-3-peter.maydell@linaro.org
9
Message-id: 20180308130626.12393-4-peter.maydell@linaro.org
17
---
10
---
18
target/arm/internals.h | 25 +++++++++++++++++++++++++
11
target/arm/cpu-qom.h | 2 ++
19
target/arm/op_helper.c | 12 ++----------
12
target/arm/cpu.c | 24 ++++++++++++++++++++++++
20
2 files changed, 27 insertions(+), 10 deletions(-)
13
target/arm/cpu64.c | 21 +++++++++++++++++++++
14
3 files changed, 47 insertions(+)
21
15
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
18
--- a/target/arm/cpu-qom.h
25
+++ b/target/arm/internals.h
19
+++ b/target/arm/cpu-qom.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
20
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info;
27
}
21
#define ARM_CPU_GET_CLASS(obj) \
22
OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU)
23
24
+#define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU
25
+
26
/**
27
* ARMCPUClass:
28
* @parent_realize: The parent class' realize handler.
29
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.c
32
+++ b/target/arm/cpu.c
33
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
34
cpu->reset_sctlr = 0x00000078;
28
}
35
}
29
36
30
+/* Return the FSR value for a debug exception (watchpoint, hardware
37
+#ifndef TARGET_AARCH64
31
+ * breakpoint or BKPT insn) targeting the specified exception level.
38
+/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
39
+ * otherwise, a CPU with as many features enabled as our emulation supports.
40
+ * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
41
+ * this only needs to handle 32 bits.
32
+ */
42
+ */
33
+static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
43
+static void arm_max_initfn(Object *obj)
34
+{
44
+{
35
+ ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
45
+ ARMCPU *cpu = ARM_CPU(obj);
36
+ int target_el = arm_debug_target_el(env);
37
+ bool using_lpae = false;
38
+
46
+
39
+ if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
47
+ if (kvm_enabled()) {
40
+ using_lpae = true;
48
+ kvm_arm_set_cpu_features_from_host(cpu);
41
+ } else {
49
+ } else {
42
+ if (arm_feature(env, ARM_FEATURE_LPAE) &&
50
+ cortex_a15_initfn(obj);
43
+ (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
51
+ /* In future we might add feature bits here even if the
44
+ using_lpae = true;
52
+ * real-world A15 doesn't implement them.
45
+ }
53
+ */
46
+ }
54
+ }
55
+}
56
+#endif
47
+
57
+
48
+ if (using_lpae) {
58
#ifdef CONFIG_USER_ONLY
49
+ return arm_fi_to_lfsc(&fi);
59
static void arm_any_initfn(Object *obj)
60
{
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
62
{ .name = "pxa270-b1", .initfn = pxa270b1_initfn },
63
{ .name = "pxa270-c0", .initfn = pxa270c0_initfn },
64
{ .name = "pxa270-c5", .initfn = pxa270c5_initfn },
65
+#ifndef TARGET_AARCH64
66
+ { .name = "max", .initfn = arm_max_initfn },
67
+#endif
68
#ifdef CONFIG_USER_ONLY
69
{ .name = "any", .initfn = arm_any_initfn },
70
#endif
71
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/cpu64.c
74
+++ b/target/arm/cpu64.c
75
@@ -XXX,XX +XXX,XX @@
76
#include "hw/arm/arm.h"
77
#include "sysemu/sysemu.h"
78
#include "sysemu/kvm.h"
79
+#include "kvm_arm.h"
80
81
static inline void set_feature(CPUARMState *env, int feature)
82
{
83
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
84
define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo);
85
}
86
87
+/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
88
+ * otherwise, a CPU with as many features enabled as our emulation supports.
89
+ * The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
90
+ * this only needs to handle 64 bits.
91
+ */
92
+static void aarch64_max_initfn(Object *obj)
93
+{
94
+ ARMCPU *cpu = ARM_CPU(obj);
95
+
96
+ if (kvm_enabled()) {
97
+ kvm_arm_set_cpu_features_from_host(cpu);
50
+ } else {
98
+ } else {
51
+ return arm_fi_to_sfsc(&fi);
99
+ aarch64_a57_initfn(obj);
100
+ /* In future we might add feature bits here even if the
101
+ * real-world A57 doesn't implement them.
102
+ */
52
+ }
103
+ }
53
+}
104
+}
54
+
105
+
106
#ifdef CONFIG_USER_ONLY
107
static void aarch64_any_initfn(Object *obj)
108
{
109
@@ -XXX,XX +XXX,XX @@ typedef struct ARMCPUInfo {
110
static const ARMCPUInfo aarch64_cpus[] = {
111
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
112
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
113
+ { .name = "max", .initfn = aarch64_max_initfn },
114
#ifdef CONFIG_USER_ONLY
115
{ .name = "any", .initfn = aarch64_any_initfn },
55
#endif
116
#endif
56
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/op_helper.c
59
+++ b/target/arm/op_helper.c
60
@@ -XXX,XX +XXX,XX @@ void arm_debug_excp_handler(CPUState *cs)
61
62
cs->watchpoint_hit = NULL;
63
64
- if (extended_addresses_enabled(env)) {
65
- env->exception.fsr = (1 << 9) | 0x22;
66
- } else {
67
- env->exception.fsr = 0x2;
68
- }
69
+ env->exception.fsr = arm_debug_exception_fsr(env);
70
env->exception.vaddress = wp_hit->hitaddr;
71
raise_exception(env, EXCP_DATA_ABORT,
72
syn_watchpoint(same_el, 0, wnr),
73
@@ -XXX,XX +XXX,XX @@ void arm_debug_excp_handler(CPUState *cs)
74
return;
75
}
76
77
- if (extended_addresses_enabled(env)) {
78
- env->exception.fsr = (1 << 9) | 0x22;
79
- } else {
80
- env->exception.fsr = 0x2;
81
- }
82
+ env->exception.fsr = arm_debug_exception_fsr(env);
83
/* FAR is UNKNOWN, so doesn't need setting */
84
raise_exception(env, EXCP_PREFETCH_ABORT,
85
syn_breakpoint(same_el),
86
--
117
--
87
2.16.2
118
2.16.2
88
119
89
120
diff view generated by jsdifflib
New patch
1
Now we have a working '-cpu max', the linux-user-only
2
'any' CPU is pretty much the same thing, so implement it
3
that way.
1
4
5
For the moment we don't add any of the extra feature bits
6
to the system-emulation "max", because we don't set the
7
ID register bits we would need to to advertise those
8
features as present.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20180308130626.12393-5-peter.maydell@linaro.org
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
---
15
target/arm/cpu.c | 52 +++++++++++++++++++++++++----------------------
16
target/arm/cpu64.c | 59 ++++++++++++++++++++++++++----------------------------
17
2 files changed, 56 insertions(+), 55 deletions(-)
18
19
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.c
22
+++ b/target/arm/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
24
ObjectClass *oc;
25
char *typename;
26
char **cpuname;
27
+ const char *cpunamestr;
28
29
cpuname = g_strsplit(cpu_model, ",", 1);
30
- typename = g_strdup_printf(ARM_CPU_TYPE_NAME("%s"), cpuname[0]);
31
+ cpunamestr = cpuname[0];
32
+#ifdef CONFIG_USER_ONLY
33
+ /* For backwards compatibility usermode emulation allows "-cpu any",
34
+ * which has the same semantics as "-cpu max".
35
+ */
36
+ if (!strcmp(cpunamestr, "any")) {
37
+ cpunamestr = "max";
38
+ }
39
+#endif
40
+ typename = g_strdup_printf(ARM_CPU_TYPE_NAME("%s"), cpunamestr);
41
oc = object_class_by_name(typename);
42
g_strfreev(cpuname);
43
g_free(typename);
44
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
45
kvm_arm_set_cpu_features_from_host(cpu);
46
} else {
47
cortex_a15_initfn(obj);
48
- /* In future we might add feature bits here even if the
49
- * real-world A15 doesn't implement them.
50
- */
51
- }
52
-}
53
-#endif
54
-
55
#ifdef CONFIG_USER_ONLY
56
-static void arm_any_initfn(Object *obj)
57
-{
58
- ARMCPU *cpu = ARM_CPU(obj);
59
- set_feature(&cpu->env, ARM_FEATURE_V8);
60
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
61
- set_feature(&cpu->env, ARM_FEATURE_NEON);
62
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
63
- set_feature(&cpu->env, ARM_FEATURE_V8_AES);
64
- set_feature(&cpu->env, ARM_FEATURE_V8_SHA1);
65
- set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
66
- set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
67
- set_feature(&cpu->env, ARM_FEATURE_CRC);
68
- set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
69
- set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
70
- cpu->midr = 0xffffffff;
71
+ /* We don't set these in system emulation mode for the moment,
72
+ * since we don't correctly set the ID registers to advertise them,
73
+ */
74
+ set_feature(&cpu->env, ARM_FEATURE_V8);
75
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
76
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
77
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
78
+ set_feature(&cpu->env, ARM_FEATURE_V8_AES);
79
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA1);
80
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
81
+ set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
82
+ set_feature(&cpu->env, ARM_FEATURE_CRC);
83
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
84
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
85
+#endif
86
+ }
87
}
88
#endif
89
90
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
91
{ .name = "max", .initfn = arm_max_initfn },
92
#endif
93
#ifdef CONFIG_USER_ONLY
94
- { .name = "any", .initfn = arm_any_initfn },
95
+ { .name = "any", .initfn = arm_max_initfn },
96
#endif
97
#endif
98
{ .name = NULL }
99
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/cpu64.c
102
+++ b/target/arm/cpu64.c
103
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
104
kvm_arm_set_cpu_features_from_host(cpu);
105
} else {
106
aarch64_a57_initfn(obj);
107
- /* In future we might add feature bits here even if the
108
- * real-world A57 doesn't implement them.
109
+#ifdef CONFIG_USER_ONLY
110
+ /* We don't set these in system emulation mode for the moment,
111
+ * since we don't correctly set the ID registers to advertise them,
112
+ * and in some cases they're only available in AArch64 and not AArch32,
113
+ * whereas the architecture requires them to be present in both if
114
+ * present in either.
115
*/
116
+ set_feature(&cpu->env, ARM_FEATURE_V8);
117
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
118
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
119
+ set_feature(&cpu->env, ARM_FEATURE_AARCH64);
120
+ set_feature(&cpu->env, ARM_FEATURE_V8_AES);
121
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA1);
122
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
123
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA512);
124
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA3);
125
+ set_feature(&cpu->env, ARM_FEATURE_V8_SM3);
126
+ set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
127
+ set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
128
+ set_feature(&cpu->env, ARM_FEATURE_CRC);
129
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
130
+ set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
131
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
132
+ /* For usermode -cpu max we can use a larger and more efficient DCZ
133
+ * blocksize since we don't have to follow what the hardware does.
134
+ */
135
+ cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
136
+ cpu->dcz_blocksize = 7; /* 512 bytes */
137
+#endif
138
}
139
}
140
141
-#ifdef CONFIG_USER_ONLY
142
-static void aarch64_any_initfn(Object *obj)
143
-{
144
- ARMCPU *cpu = ARM_CPU(obj);
145
-
146
- set_feature(&cpu->env, ARM_FEATURE_V8);
147
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
148
- set_feature(&cpu->env, ARM_FEATURE_NEON);
149
- set_feature(&cpu->env, ARM_FEATURE_AARCH64);
150
- set_feature(&cpu->env, ARM_FEATURE_V8_AES);
151
- set_feature(&cpu->env, ARM_FEATURE_V8_SHA1);
152
- set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
153
- set_feature(&cpu->env, ARM_FEATURE_V8_SHA512);
154
- set_feature(&cpu->env, ARM_FEATURE_V8_SHA3);
155
- set_feature(&cpu->env, ARM_FEATURE_V8_SM3);
156
- set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
157
- set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
158
- set_feature(&cpu->env, ARM_FEATURE_CRC);
159
- set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
160
- set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
161
- set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
162
- cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
163
- cpu->dcz_blocksize = 7; /* 512 bytes */
164
-}
165
-#endif
166
-
167
typedef struct ARMCPUInfo {
168
const char *name;
169
void (*initfn)(Object *obj);
170
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo aarch64_cpus[] = {
171
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
172
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
173
{ .name = "max", .initfn = aarch64_max_initfn },
174
-#ifdef CONFIG_USER_ONLY
175
- { .name = "any", .initfn = aarch64_any_initfn },
176
-#endif
177
{ .name = NULL }
178
};
179
180
--
181
2.16.2
182
183
diff view generated by jsdifflib
1
The BCM2836 uses a Cortex-A7, not a Cortex-A15. Update the device to
1
Allow the virt board to support '-cpu max' in the same way
2
use the correct CPU.
2
it already handles '-cpu host'.
3
https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf
4
5
When the BCM2836 was introduced (bad5623690b) the Cortex-A7 was not
6
available, so the very similar Cortex-A15 was used. Since dcf578ed8ce
7
we can model the correct core.
8
3
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Alistair Francis <alistair@alistair23.me>
5
Message-id: 20180308130626.12393-6-peter.maydell@linaro.org
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20180319110215.16755-1-peter.maydell@linaro.org
13
---
8
---
14
hw/arm/bcm2836.c | 2 +-
9
hw/arm/virt.c | 1 +
15
hw/arm/raspi.c | 2 +-
10
1 file changed, 1 insertion(+)
16
2 files changed, 2 insertions(+), 2 deletions(-)
17
11
18
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
12
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/bcm2836.c
14
--- a/hw/arm/virt.c
21
+++ b/hw/arm/bcm2836.c
15
+++ b/hw/arm/virt.c
22
@@ -XXX,XX +XXX,XX @@ struct BCM283XInfo {
16
@@ -XXX,XX +XXX,XX @@ static const char *valid_cpus[] = {
23
static const BCM283XInfo bcm283x_socs[] = {
17
ARM_CPU_TYPE_NAME("cortex-a53"),
24
{
18
ARM_CPU_TYPE_NAME("cortex-a57"),
25
.name = TYPE_BCM2836,
19
ARM_CPU_TYPE_NAME("host"),
26
- .cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"),
20
+ ARM_CPU_TYPE_NAME("max"),
27
+ .cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"),
21
};
28
.clusterid = 0xf,
22
29
},
23
static bool cpu_type_valid(const char *cpu)
30
#ifdef TARGET_AARCH64
31
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/raspi.c
34
+++ b/hw/arm/raspi.c
35
@@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc)
36
mc->no_parallel = 1;
37
mc->no_floppy = 1;
38
mc->no_cdrom = 1;
39
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
40
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
41
mc->max_cpus = BCM283X_NCPUS;
42
mc->min_cpus = BCM283X_NCPUS;
43
mc->default_cpus = BCM283X_NCPUS;
44
--
24
--
45
2.16.2
25
2.16.2
46
26
47
27
diff view generated by jsdifflib
1
From: Wei Huang <wei@redhat.com>
1
Add support for passing 'max' to -machine gic-version. By analogy
2
with the -cpu max option, this picks the "best available" GIC version
3
whether you're using KVM or TCG, so it behaves like 'host' when
4
using KVM, and gives you GICv3 when using TCG.
2
5
3
Instead of using "1.0" as the system version of SMBIOS, we should use
6
Also like '-cpu host', using -machine gic-version=max' means there
4
mc->name for mach-virt machine type to be consistent other architectures.
7
is no guarantee of migration compatibility between QEMU versions;
5
With this patch, "dmidecode -t 1" (e.g., "-M virt-2.12,accel=kvm") will
8
in future 'max' might mean '4'.
6
show:
7
9
8
Handle 0x0100, DMI type 1, 27 bytes
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
System Information
11
Message-id: 20180308130626.12393-7-peter.maydell@linaro.org
10
Manufacturer: QEMU
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Product Name: KVM Virtual Machine
13
---
12
Version: virt-2.12
14
hw/arm/virt.c | 29 +++++++++++++++++++----------
13
Serial Number: Not Specified
15
1 file changed, 19 insertions(+), 10 deletions(-)
14
...
15
16
16
instead of:
17
18
Handle 0x0100, DMI type 1, 27 bytes
19
System Information
20
Manufacturer: QEMU
21
Product Name: KVM Virtual Machine
22
Version: 1.0
23
Serial Number: Not Specified
24
...
25
26
For backward compatibility, we allow older machine types to keep "1.0"
27
as the default system version.
28
29
Signed-off-by: Wei Huang <wei@redhat.com>
30
Reviewed-by: Andrew Jones <drjones@redhat.com>
31
Message-id: 20180322212318.7182-1-wei@redhat.com
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
---
34
include/hw/arm/virt.h | 1 +
35
hw/arm/virt.c | 8 +++++++-
36
2 files changed, 8 insertions(+), 1 deletion(-)
37
38
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/arm/virt.h
41
+++ b/include/hw/arm/virt.h
42
@@ -XXX,XX +XXX,XX @@ typedef struct {
43
bool no_its;
44
bool no_pmu;
45
bool claim_edge_triggered_timers;
46
+ bool smbios_old_sys_ver;
47
} VirtMachineClass;
48
49
typedef struct {
50
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
17
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
51
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/virt.c
19
--- a/hw/arm/virt.c
53
+++ b/hw/arm/virt.c
20
+++ b/hw/arm/virt.c
54
@@ -XXX,XX +XXX,XX @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
21
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
55
22
/* We can probe only here because during property set
56
static void virt_build_smbios(VirtMachineState *vms)
23
* KVM is not available yet
57
{
24
*/
58
+ MachineClass *mc = MACHINE_GET_CLASS(vms);
25
- if (!vms->gic_version) {
59
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
26
+ if (vms->gic_version <= 0) {
60
uint8_t *smbios_tables, *smbios_anchor;
27
+ /* "host" or "max" */
61
size_t smbios_tables_len, smbios_anchor_len;
28
if (!kvm_enabled()) {
62
const char *product = "QEMU Virtual Machine";
29
- error_report("gic-version=host requires KVM");
63
@@ -XXX,XX +XXX,XX @@ static void virt_build_smbios(VirtMachineState *vms)
30
- exit(1);
31
- }
32
-
33
- vms->gic_version = kvm_arm_vgic_probe();
34
- if (!vms->gic_version) {
35
- error_report("Unable to determine GIC version supported by host");
36
- exit(1);
37
+ if (vms->gic_version == 0) {
38
+ error_report("gic-version=host requires KVM");
39
+ exit(1);
40
+ } else {
41
+ /* "max": currently means 3 for TCG */
42
+ vms->gic_version = 3;
43
+ }
44
+ } else {
45
+ vms->gic_version = kvm_arm_vgic_probe();
46
+ if (!vms->gic_version) {
47
+ error_report(
48
+ "Unable to determine GIC version supported by host");
49
+ exit(1);
50
+ }
51
}
64
}
52
}
65
53
66
smbios_set_defaults("QEMU", product,
54
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
67
- "1.0", false, true, SMBIOS_ENTRY_POINT_30);
55
vms->gic_version = 2;
68
+ vmc->smbios_old_sys_ver ? "1.0" : mc->name, false,
56
} else if (!strcmp(value, "host")) {
69
+ true, SMBIOS_ENTRY_POINT_30);
57
vms->gic_version = 0; /* Will probe later */
70
58
+ } else if (!strcmp(value, "max")) {
71
smbios_get_tables(NULL, 0, &smbios_tables, &smbios_tables_len,
59
+ vms->gic_version = -1; /* Will probe later */
72
&smbios_anchor, &smbios_anchor_len);
60
} else {
73
@@ -XXX,XX +XXX,XX @@ static void virt_2_11_instance_init(Object *obj)
61
error_setg(errp, "Invalid gic-version value");
74
62
- error_append_hint(errp, "Valid values are 3, 2, host.\n");
75
static void virt_machine_2_11_options(MachineClass *mc)
63
+ error_append_hint(errp, "Valid values are 3, 2, host, max.\n");
76
{
64
}
77
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
78
+
79
virt_machine_2_12_options(mc);
80
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11);
81
+ vmc->smbios_old_sys_ver = true;
82
}
65
}
83
DEFINE_VIRT_MACHINE(2, 11)
84
66
85
--
67
--
86
2.16.2
68
2.16.2
87
69
88
70
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Acked-by: Alistair Francis <alistair.francis@xilinx.com>
5
Message-id: 20180309153654.13518-2-f4bug@amsat.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
hw/sd/sd.c | 11 ++++++++---
10
1 file changed, 8 insertions(+), 3 deletions(-)
11
12
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/sd/sd.c
15
+++ b/hw/sd/sd.c
16
@@ -XXX,XX +XXX,XX @@ static void sd_lock_command(SDState *sd)
17
sd->card_status &= ~CARD_IS_LOCKED;
18
}
19
20
-static sd_rsp_type_t sd_normal_command(SDState *sd,
21
- SDRequest req)
22
+static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
23
{
24
uint32_t rca = 0x0000;
25
uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
26
27
- trace_sdcard_normal_command(req.cmd, req.arg, sd_state_name(sd->state));
28
+ /* CMD55 precedes an ACMD, so we are not interested in tracing it.
29
+ * However there is no ACMD55, so we want to trace this particular case.
30
+ */
31
+ if (req.cmd != 55 || sd->expecting_acmd) {
32
+ trace_sdcard_normal_command(req.cmd, req.arg,
33
+ sd_state_name(sd->state));
34
+ }
35
36
/* Not interpreting this as an app command */
37
sd->card_status &= ~APP_CMD;
38
--
39
2.16.2
40
41
diff view generated by jsdifflib
New patch
1
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
3
The SDBus will reuse these functions, so we put them in a new source file.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20180309153654.13518-3-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
[PMM: slight wordsmithing of comments, added note that string
9
returned does not need to be freed]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/sd/Makefile.objs | 2 +-
13
hw/sd/sdmmc-internal.h | 24 +++++++++++++++++
14
hw/sd/sd.c | 13 +++++----
15
hw/sd/sdmmc-internal.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
16
hw/sd/trace-events | 8 +++---
17
5 files changed, 109 insertions(+), 10 deletions(-)
18
create mode 100644 hw/sd/sdmmc-internal.c
19
20
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/sd/Makefile.objs
23
+++ b/hw/sd/Makefile.objs
24
@@ -XXX,XX +XXX,XX @@
25
common-obj-$(CONFIG_PL181) += pl181.o
26
common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
27
-common-obj-$(CONFIG_SD) += sd.o core.o
28
+common-obj-$(CONFIG_SD) += sd.o core.o sdmmc-internal.o
29
common-obj-$(CONFIG_SDHCI) += sdhci.o
30
31
obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
32
diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/sd/sdmmc-internal.h
35
+++ b/hw/sd/sdmmc-internal.h
36
@@ -XXX,XX +XXX,XX @@
37
38
#define SDMMC_CMD_MAX 64
39
40
+/**
41
+ * sd_cmd_name:
42
+ * @cmd: A SD "normal" command, up to SDMMC_CMD_MAX.
43
+ *
44
+ * Returns a human-readable name describing the command.
45
+ * The return value is always a static string which does not need
46
+ * to be freed after use.
47
+ *
48
+ * Returns: The command name of @cmd or "UNKNOWN_CMD".
49
+ */
50
+const char *sd_cmd_name(uint8_t cmd);
51
+
52
+/**
53
+ * sd_acmd_name:
54
+ * @cmd: A SD "Application-Specific" command, up to SDMMC_CMD_MAX.
55
+ *
56
+ * Returns a human-readable name describing the application command.
57
+ * The return value is always a static string which does not need
58
+ * to be freed after use.
59
+ *
60
+ * Returns: The application command name of @cmd or "UNKNOWN_ACMD".
61
+ */
62
+const char *sd_acmd_name(uint8_t cmd);
63
+
64
#endif
65
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/sd/sd.c
68
+++ b/hw/sd/sd.c
69
@@ -XXX,XX +XXX,XX @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
70
* However there is no ACMD55, so we want to trace this particular case.
71
*/
72
if (req.cmd != 55 || sd->expecting_acmd) {
73
- trace_sdcard_normal_command(req.cmd, req.arg,
74
- sd_state_name(sd->state));
75
+ trace_sdcard_normal_command(sd_cmd_name(req.cmd), req.cmd,
76
+ req.arg, sd_state_name(sd->state));
77
}
78
79
/* Not interpreting this as an app command */
80
@@ -XXX,XX +XXX,XX @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
81
static sd_rsp_type_t sd_app_command(SDState *sd,
82
SDRequest req)
83
{
84
- trace_sdcard_app_command(req.cmd, req.arg);
85
+ trace_sdcard_app_command(sd_acmd_name(req.cmd),
86
+ req.cmd, req.arg, sd_state_name(sd->state));
87
sd->card_status |= APP_CMD;
88
switch (req.cmd) {
89
case 6:    /* ACMD6: SET_BUS_WIDTH */
90
@@ -XXX,XX +XXX,XX @@ void sd_write_data(SDState *sd, uint8_t value)
91
if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
92
return;
93
94
- trace_sdcard_write_data(sd->current_cmd, value);
95
+ trace_sdcard_write_data(sd_acmd_name(sd->current_cmd),
96
+ sd->current_cmd, value);
97
switch (sd->current_cmd) {
98
case 24:    /* CMD24: WRITE_SINGLE_BLOCK */
99
sd->data[sd->data_offset ++] = value;
100
@@ -XXX,XX +XXX,XX @@ uint8_t sd_read_data(SDState *sd)
101
102
io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
103
104
- trace_sdcard_read_data(sd->current_cmd, io_len);
105
+ trace_sdcard_read_data(sd_acmd_name(sd->current_cmd),
106
+ sd->current_cmd, io_len);
107
switch (sd->current_cmd) {
108
case 6:    /* CMD6: SWITCH_FUNCTION */
109
ret = sd->data[sd->data_offset ++];
110
diff --git a/hw/sd/sdmmc-internal.c b/hw/sd/sdmmc-internal.c
111
new file mode 100644
112
index XXXXXXX..XXXXXXX
113
--- /dev/null
114
+++ b/hw/sd/sdmmc-internal.c
115
@@ -XXX,XX +XXX,XX @@
116
+/*
117
+ * SD/MMC cards common helpers
118
+ *
119
+ * Copyright (c) 2018 Philippe Mathieu-Daudé <f4bug@amsat.org>
120
+ *
121
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
122
+ * See the COPYING file in the top-level directory.
123
+ * SPDX-License-Identifier: GPL-2.0-or-later
124
+ */
125
+
126
+#include "qemu/osdep.h"
127
+#include "sdmmc-internal.h"
128
+
129
+const char *sd_cmd_name(uint8_t cmd)
130
+{
131
+ static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
132
+ [0] = "GO_IDLE_STATE",
133
+ [2] = "ALL_SEND_CID", [3] = "SEND_RELATIVE_ADDR",
134
+ [4] = "SET_DSR", [5] = "IO_SEND_OP_COND",
135
+ [6] = "SWITCH_FUNC", [7] = "SELECT/DESELECT_CARD",
136
+ [8] = "SEND_IF_COND", [9] = "SEND_CSD",
137
+ [10] = "SEND_CID", [11] = "VOLTAGE_SWITCH",
138
+ [12] = "STOP_TRANSMISSION", [13] = "SEND_STATUS",
139
+ [15] = "GO_INACTIVE_STATE",
140
+ [16] = "SET_BLOCKLEN", [17] = "READ_SINGLE_BLOCK",
141
+ [18] = "READ_MULTIPLE_BLOCK", [19] = "SEND_TUNING_BLOCK",
142
+ [20] = "SPEED_CLASS_CONTROL", [21] = "DPS_spec",
143
+ [23] = "SET_BLOCK_COUNT",
144
+ [24] = "WRITE_BLOCK", [25] = "WRITE_MULTIPLE_BLOCK",
145
+ [26] = "MANUF_RSVD", [27] = "PROGRAM_CSD",
146
+ [28] = "SET_WRITE_PROT", [29] = "CLR_WRITE_PROT",
147
+ [30] = "SEND_WRITE_PROT",
148
+ [32] = "ERASE_WR_BLK_START", [33] = "ERASE_WR_BLK_END",
149
+ [34] = "SW_FUNC_RSVD", [35] = "SW_FUNC_RSVD",
150
+ [36] = "SW_FUNC_RSVD", [37] = "SW_FUNC_RSVD",
151
+ [38] = "ERASE",
152
+ [40] = "DPS_spec",
153
+ [42] = "LOCK_UNLOCK", [43] = "Q_MANAGEMENT",
154
+ [44] = "Q_TASK_INFO_A", [45] = "Q_TASK_INFO_B",
155
+ [46] = "Q_RD_TASK", [47] = "Q_WR_TASK",
156
+ [48] = "READ_EXTR_SINGLE", [49] = "WRITE_EXTR_SINGLE",
157
+ [50] = "SW_FUNC_RSVD",
158
+ [52] = "IO_RW_DIRECT", [53] = "IO_RW_EXTENDED",
159
+ [54] = "SDIO_RSVD", [55] = "APP_CMD",
160
+ [56] = "GEN_CMD", [57] = "SW_FUNC_RSVD",
161
+ [58] = "READ_EXTR_MULTI", [59] = "WRITE_EXTR_MULTI",
162
+ [60] = "MANUF_RSVD", [61] = "MANUF_RSVD",
163
+ [62] = "MANUF_RSVD", [63] = "MANUF_RSVD",
164
+ };
165
+ return cmd_abbrev[cmd] ? cmd_abbrev[cmd] : "UNKNOWN_CMD";
166
+}
167
+
168
+const char *sd_acmd_name(uint8_t cmd)
169
+{
170
+ static const char *acmd_abbrev[SDMMC_CMD_MAX] = {
171
+ [6] = "SET_BUS_WIDTH",
172
+ [13] = "SD_STATUS",
173
+ [14] = "DPS_spec", [15] = "DPS_spec",
174
+ [16] = "DPS_spec",
175
+ [18] = "SECU_spec",
176
+ [22] = "SEND_NUM_WR_BLOCKS", [23] = "SET_WR_BLK_ERASE_COUNT",
177
+ [41] = "SD_SEND_OP_COND",
178
+ [42] = "SET_CLR_CARD_DETECT",
179
+ [51] = "SEND_SCR",
180
+ [52] = "SECU_spec", [53] = "SECU_spec",
181
+ [54] = "SECU_spec",
182
+ [56] = "SECU_spec", [57] = "SECU_spec",
183
+ [58] = "SECU_spec", [59] = "SECU_spec",
184
+ };
185
+
186
+ return acmd_abbrev[cmd] ? acmd_abbrev[cmd] : "UNKNOWN_ACMD";
187
+}
188
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
189
index XXXXXXX..XXXXXXX 100644
190
--- a/hw/sd/trace-events
191
+++ b/hw/sd/trace-events
192
@@ -XXX,XX +XXX,XX @@ sdhci_write_dataport(uint16_t data_count) "write buffer filled with %u bytes of
193
sdhci_capareg(const char *desc, uint16_t val) "%s: %u"
194
195
# hw/sd/sd.c
196
-sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d arg 0x%08x (state %s)"
197
-sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x"
198
+sdcard_normal_command(const char *cmd_desc, uint8_t cmd, uint32_t arg, const char *state) "%20s/ CMD%02d arg 0x%08x (state %s)"
199
+sdcard_app_command(const char *acmd_desc, uint8_t acmd, uint32_t arg, const char *state) "%23s/ACMD%02d arg 0x%08x (state %s)"
200
sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
201
sdcard_powerup(void) ""
202
sdcard_inquiry_cmd41(void) ""
203
@@ -XXX,XX +XXX,XX @@ sdcard_lock(void) ""
204
sdcard_unlock(void) ""
205
sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
206
sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
207
-sdcard_write_data(uint8_t cmd, uint8_t value) "CMD%02d value 0x%02x"
208
-sdcard_read_data(uint8_t cmd, int length) "CMD%02d len %d"
209
+sdcard_write_data(const char *cmd_desc, uint8_t cmd, uint8_t value) "%20s/ CMD%02d value 0x%02x"
210
+sdcard_read_data(const char *cmd_desc, uint8_t cmd, int length) "%20s/ CMD%02d len %d"
211
sdcard_set_voltage(uint16_t millivolts) "%u mV"
212
213
# hw/sd/milkymist-memcard.c
214
--
215
2.16.2
216
217
diff view generated by jsdifflib
1
If the GIC has the security extension support enabled, then a
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
non-secure access to ICC_PMR must take account of the non-secure
3
view of interrupt priorities, where real priorities 0x00..0x7f
4
are secure-only and not visible to the non-secure guest, and
5
priorities 0x80..0xff are shown to the guest as if they were
6
0x00..0xff. We had the logic here wrong:
7
* on reads, the priority is in the secure range if bit 7
8
is clear, not if it is set
9
* on writes, we want to set bit 7, not mask everything else
10
2
11
Our ICC_RPR read code had the same error as ICC_PMR.
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180309153654.13518-4-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/sd/sd.c | 14 ++++++++++----
9
hw/sd/trace-events | 8 ++++----
10
2 files changed, 14 insertions(+), 8 deletions(-)
12
11
13
(Compare the GICv3 spec pseudocode functions ICC_RPR_EL1
12
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
14
and ICC_PMR_EL1.)
15
16
Fixes: https://bugs.launchpad.net/qemu/+bug/1748434
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Andrew Jones <drjones@redhat.com>
19
Message-id: 20180315133441.24149-1-peter.maydell@linaro.org
20
---
21
hw/intc/arm_gicv3_cpuif.c | 6 +++---
22
1 file changed, 3 insertions(+), 3 deletions(-)
23
24
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
25
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/arm_gicv3_cpuif.c
14
--- a/hw/sd/sd.c
27
+++ b/hw/intc/arm_gicv3_cpuif.c
15
+++ b/hw/sd/sd.c
28
@@ -XXX,XX +XXX,XX @@ static uint64_t icc_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
16
@@ -XXX,XX +XXX,XX @@ struct SDState {
29
/* NS access and Group 0 is inaccessible to NS: return the
17
qemu_irq readonly_cb;
30
* NS view of the current priority
18
qemu_irq inserted_cb;
31
*/
19
QEMUTimer *ocr_power_timer;
32
- if (value & 0x80) {
20
+ const char *proto_name;
33
+ if ((value & 0x80) == 0) {
21
bool enable;
34
/* Secure priorities not visible to NS */
22
uint8_t dat_lines;
35
value = 0;
23
bool cmd_line;
36
} else if (value != 0xff) {
24
@@ -XXX,XX +XXX,XX @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
37
@@ -XXX,XX +XXX,XX @@ static void icc_pmr_write(CPUARMState *env, const ARMCPRegInfo *ri,
25
* However there is no ACMD55, so we want to trace this particular case.
38
/* Current PMR in the secure range, don't allow NS to change it */
26
*/
39
return;
27
if (req.cmd != 55 || sd->expecting_acmd) {
40
}
28
- trace_sdcard_normal_command(sd_cmd_name(req.cmd), req.cmd,
41
- value = (value >> 1) & 0x80;
29
+ trace_sdcard_normal_command(sd->proto_name,
42
+ value = (value >> 1) | 0x80;
30
+ sd_cmd_name(req.cmd), req.cmd,
31
req.arg, sd_state_name(sd->state));
43
}
32
}
44
cs->icc_pmr_el1 = value;
33
45
gicv3_cpuif_update(cs);
34
@@ -XXX,XX +XXX,XX @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
46
@@ -XXX,XX +XXX,XX @@ static uint64_t icc_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
35
static sd_rsp_type_t sd_app_command(SDState *sd,
47
if (arm_feature(env, ARM_FEATURE_EL3) &&
36
SDRequest req)
48
!arm_is_secure(env) && (env->cp15.scr_el3 & SCR_FIQ)) {
37
{
49
/* NS GIC access and Group 0 is inaccessible to NS */
38
- trace_sdcard_app_command(sd_acmd_name(req.cmd),
50
- if (prio & 0x80) {
39
+ trace_sdcard_app_command(sd->proto_name, sd_acmd_name(req.cmd),
51
+ if ((prio & 0x80) == 0) {
40
req.cmd, req.arg, sd_state_name(sd->state));
52
/* NS mustn't see priorities in the Secure half of the range */
41
sd->card_status |= APP_CMD;
53
prio = 0;
42
switch (req.cmd) {
54
} else if (prio != 0xff) {
43
@@ -XXX,XX +XXX,XX @@ void sd_write_data(SDState *sd, uint8_t value)
44
if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
45
return;
46
47
- trace_sdcard_write_data(sd_acmd_name(sd->current_cmd),
48
+ trace_sdcard_write_data(sd->proto_name,
49
+ sd_acmd_name(sd->current_cmd),
50
sd->current_cmd, value);
51
switch (sd->current_cmd) {
52
case 24:    /* CMD24: WRITE_SINGLE_BLOCK */
53
@@ -XXX,XX +XXX,XX @@ uint8_t sd_read_data(SDState *sd)
54
55
io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
56
57
- trace_sdcard_read_data(sd_acmd_name(sd->current_cmd),
58
+ trace_sdcard_read_data(sd->proto_name,
59
+ sd_acmd_name(sd->current_cmd),
60
sd->current_cmd, io_len);
61
switch (sd->current_cmd) {
62
case 6:    /* CMD6: SWITCH_FUNCTION */
63
@@ -XXX,XX +XXX,XX @@ static void sd_realize(DeviceState *dev, Error **errp)
64
SDState *sd = SD_CARD(dev);
65
int ret;
66
67
+ sd->proto_name = sd->spi ? "SPI" : "SD";
68
+
69
if (sd->blk && blk_is_read_only(sd->blk)) {
70
error_setg(errp, "Cannot use read-only drive as SD card");
71
return;
72
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/sd/trace-events
75
+++ b/hw/sd/trace-events
76
@@ -XXX,XX +XXX,XX @@ sdhci_write_dataport(uint16_t data_count) "write buffer filled with %u bytes of
77
sdhci_capareg(const char *desc, uint16_t val) "%s: %u"
78
79
# hw/sd/sd.c
80
-sdcard_normal_command(const char *cmd_desc, uint8_t cmd, uint32_t arg, const char *state) "%20s/ CMD%02d arg 0x%08x (state %s)"
81
-sdcard_app_command(const char *acmd_desc, uint8_t acmd, uint32_t arg, const char *state) "%23s/ACMD%02d arg 0x%08x (state %s)"
82
+sdcard_normal_command(const char *proto, const char *cmd_desc, uint8_t cmd, uint32_t arg, const char *state) "%s %20s/ CMD%02d arg 0x%08x (state %s)"
83
+sdcard_app_command(const char *proto, const char *acmd_desc, uint8_t acmd, uint32_t arg, const char *state) "%s %23s/ACMD%02d arg 0x%08x (state %s)"
84
sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
85
sdcard_powerup(void) ""
86
sdcard_inquiry_cmd41(void) ""
87
@@ -XXX,XX +XXX,XX @@ sdcard_lock(void) ""
88
sdcard_unlock(void) ""
89
sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
90
sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
91
-sdcard_write_data(const char *cmd_desc, uint8_t cmd, uint8_t value) "%20s/ CMD%02d value 0x%02x"
92
-sdcard_read_data(const char *cmd_desc, uint8_t cmd, int length) "%20s/ CMD%02d len %d"
93
+sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, uint8_t value) "%s %20s/ CMD%02d value 0x%02x"
94
+sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, int length) "%s %20s/ CMD%02d len %d"
95
sdcard_set_voltage(uint16_t millivolts) "%u mV"
96
97
# hw/sd/milkymist-memcard.c
55
--
98
--
56
2.16.2
99
2.16.2
57
100
58
101
diff view generated by jsdifflib
1
From: Trent Piepho <tpiepho@impinj.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Linux does not detect a break from this IMX serial driver as a magic
3
From the "Physical Layer Simplified Specification Version 3.01":
4
sysrq. Nor does it note a break in the port error counts.
5
4
6
The former is because the Linux driver uses the BRCD bit in the USR2
5
A known data block ("Tuning block") can be used to tune sampling
7
register to trigger the RS-232 break handler in the kernel, which is
6
point for tuning required hosts. [...]
8
where sysrq hooks in. The emulated UART was not setting this status
7
This procedure gives the system optimal timing for each specific
9
bit.
8
host and card combination and compensates for static delays in
9
the timing budget including process, voltage and different PCB
10
loads and skews. [...]
11
Data block, carried by DAT[3:0], contains a pattern for tuning
12
sampling position to receive data on the CMD and DAT[3:0] line.
10
13
11
The latter is because the Linux driver expects, in addition to the BRK
14
[based on a patch from Alistair Francis <alistair.francis@xilinx.com>
12
bit, that the ERR bit is set when a break is read in the FIFO. A break
15
from qemu/xilinx tag xilinx-v2015.2]
13
should also count as a frame error, so add that bit too.
16
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
17
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
15
Cc: Andrey Smirnov <andrew.smirnov@gmail.com>
18
Message-id: 20180309153654.13518-5-f4bug@amsat.org
16
Signed-off-by: Trent Piepho <tpiepho@impinj.com>
17
Message-id: 20180320013657.25038-1-tpiepho@impinj.com
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
20
---
21
include/hw/char/imx_serial.h | 1 +
21
hw/sd/sd.c | 29 +++++++++++++++++++++++++++++
22
hw/char/imx_serial.c | 5 ++++-
22
1 file changed, 29 insertions(+)
23
2 files changed, 5 insertions(+), 1 deletion(-)
24
23
25
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
24
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
26
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/char/imx_serial.h
26
--- a/hw/sd/sd.c
28
+++ b/include/hw/char/imx_serial.h
27
+++ b/hw/sd/sd.c
29
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
30
29
}
31
#define URXD_CHARRDY (1<<15) /* character read is valid */
30
break;
32
#define URXD_ERR (1<<14) /* Character has error */
31
33
+#define URXD_FRMERR (1<<12) /* Character has frame error */
32
+ case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */
34
#define URXD_BRK (1<<11) /* Break received */
33
+ if (sd->state == sd_transfer_state) {
35
34
+ sd->state = sd_sendingdata_state;
36
#define USR1_PARTYER (1<<15) /* Parity Error */
35
+ sd->data_offset = 0;
37
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
36
+ return sd_r1;
38
index XXXXXXX..XXXXXXX 100644
37
+ }
39
--- a/hw/char/imx_serial.c
38
+ break;
40
+++ b/hw/char/imx_serial.c
39
+
41
@@ -XXX,XX +XXX,XX @@ static void imx_put_data(void *opaque, uint32_t value)
40
case 23: /* CMD23: SET_BLOCK_COUNT */
42
s->usr2 |= USR2_RDR;
41
switch (sd->state) {
43
s->uts1 &= ~UTS1_RXEMPTY;
42
case sd_transfer_state:
44
s->readbuff = value;
43
@@ -XXX,XX +XXX,XX @@ void sd_write_data(SDState *sd, uint8_t value)
45
+ if (value & URXD_BRK) {
46
+ s->usr2 |= USR2_BRCD;
47
+ }
48
imx_update(s);
49
}
50
51
@@ -XXX,XX +XXX,XX @@ static void imx_receive(void *opaque, const uint8_t *buf, int size)
52
static void imx_event(void *opaque, int event)
53
{
54
if (event == CHR_EVENT_BREAK) {
55
- imx_put_data(opaque, URXD_BRK);
56
+ imx_put_data(opaque, URXD_BRK | URXD_FRMERR | URXD_ERR);
57
}
44
}
58
}
45
}
46
47
+#define SD_TUNING_BLOCK_SIZE 64
48
+
49
+static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = {
50
+ /* See: Physical Layer Simplified Specification Version 3.01, Table 4-2 */
51
+ 0xff, 0x0f, 0xff, 0x00, 0x0f, 0xfc, 0xc3, 0xcc,
52
+ 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
53
+ 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
54
+ 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
55
+ 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
56
+ 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
57
+ 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
58
+ 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
59
+};
60
+
61
uint8_t sd_read_data(SDState *sd)
62
{
63
/* TODO: Append CRCs */
64
@@ -XXX,XX +XXX,XX @@ uint8_t sd_read_data(SDState *sd)
65
}
66
break;
67
68
+ case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */
69
+ if (sd->data_offset >= SD_TUNING_BLOCK_SIZE - 1) {
70
+ sd->state = sd_transfer_state;
71
+ }
72
+ ret = sd_tuning_block_pattern[sd->data_offset++];
73
+ break;
74
+
75
case 22:    /* ACMD22: SEND_NUM_WR_BLOCKS */
76
ret = sd->data[sd->data_offset ++];
59
77
60
--
78
--
61
2.16.2
79
2.16.2
62
80
63
81
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Detected by Coverity (CID 1386072, 1386073, 1386076, 1386077). local_err
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
was unused, and this made the static analyzer unhappy.
5
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-id: 20180320151355.25854-1-pbonzini@redhat.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180309153654.13518-8-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
7
---
11
hw/sd/sdhci.c | 4 ++--
8
hw/sd/sdhci.c | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
9
1 file changed, 2 insertions(+), 2 deletions(-)
13
10
14
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
11
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/sd/sdhci.c
13
--- a/hw/sd/sdhci.c
17
+++ b/hw/sd/sdhci.c
14
+++ b/hw/sd/sdhci.c
18
@@ -XXX,XX +XXX,XX @@ static void sdhci_pci_realize(PCIDevice *dev, Error **errp)
15
@@ -XXX,XX +XXX,XX @@ static void sdhci_read_block_from_card(SDHCIState *s)
19
Error *local_err = NULL;
16
for (index = 0; index < blk_size; index++) {
20
17
data = sdbus_read_data(&s->sdbus);
21
sdhci_initfn(s);
18
if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
22
- sdhci_common_realize(s, errp);
19
- /* Device is not in tunning */
23
+ sdhci_common_realize(s, &local_err);
20
+ /* Device is not in tuning */
24
if (local_err) {
21
s->fifo_buffer[index] = data;
25
error_propagate(errp, local_err);
22
}
26
return;
23
}
27
@@ -XXX,XX +XXX,XX @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
24
28
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
25
if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
29
Error *local_err = NULL;
26
- /* Device is in tunning */
30
27
+ /* Device is in tuning */
31
- sdhci_common_realize(s, errp);
28
s->hostctl2 &= ~R_SDHC_HOSTCTL2_EXECUTE_TUNING_MASK;
32
+ sdhci_common_realize(s, &local_err);
29
s->hostctl2 |= R_SDHC_HOSTCTL2_SAMPLING_CLKSEL_MASK;
33
if (local_err) {
30
s->prnsts &= ~(SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ |
34
error_propagate(errp, local_err);
35
return;
36
--
31
--
37
2.16.2
32
2.16.2
38
33
39
34
diff view generated by jsdifflib
1
From: Victor Kamensky <kamensky@cisco.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
In OE project 4.15 linux kernel boot hang was observed under
3
After spending months studying all the different SD Specifications
4
single cpu aarch64 qemu. Kernel code was in a loop waiting for
4
from the SD Association, voluntarily add myself as maintainer
5
vtimer arrival, spinning in TC generated blocks, while interrupt
5
for the SD code.
6
was pending unprocessed. This happened because when qemu tried to
7
handle vtimer interrupt target had interrupts disabled, as
8
result flag indicating TCG exit, cpu->icount_decr.u16.high,
9
was cleared but arm_cpu_exec_interrupt function did not call
10
arm_cpu_do_interrupt to process interrupt. Later when target
11
reenabled interrupts, it happened without exit into main loop, so
12
following code that waited for result of interrupt execution
13
run in infinite loop.
14
6
15
To solve the problem instructions that operate on CPU sys state
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
(i.e enable/disable interrupt), and marked as DISAS_UPDATE,
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
should be considered as DISAS_EXIT variant, and should be
9
Message-id: 20180309153654.13518-9-f4bug@amsat.org
18
forced to exit back to main loop so qemu will have a chance
19
processing pending CPU state updates, including pending
20
interrupts.
21
22
This change brings consistency with how DISAS_UPDATE is treated
23
in aarch32 case.
24
25
CC: Peter Maydell <peter.maydell@linaro.org>
26
CC: Alex Bennée <alex.bennee@linaro.org>
27
CC: qemu-stable@nongnu.org
28
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Victor Kamensky <kamensky@cisco.com>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 1521526368-1996-1-git-send-email-kamensky@cisco.com
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
---
11
---
34
target/arm/translate-a64.c | 6 +++---
12
MAINTAINERS | 8 ++++++++
35
1 file changed, 3 insertions(+), 3 deletions(-)
13
1 file changed, 8 insertions(+)
36
14
37
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/MAINTAINERS b/MAINTAINERS
38
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-a64.c
17
--- a/MAINTAINERS
40
+++ b/target/arm/translate-a64.c
18
+++ b/MAINTAINERS
41
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
19
@@ -XXX,XX +XXX,XX @@ M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
42
case DISAS_UPDATE:
20
S: Maintained
43
gen_a64_set_pc_im(dc->pc);
21
F: hw/ssi/xilinx_*
44
/* fall through */
22
45
- case DISAS_JUMP:
23
+SD (Secure Card)
46
- tcg_gen_lookup_and_goto_ptr();
24
+M: Philippe Mathieu-Daudé <f4bug@amsat.org>
47
- break;
25
+S: Odd Fixes
48
case DISAS_EXIT:
26
+F: include/hw/sd/sd*
49
tcg_gen_exit_tb(0);
27
+F: hw/sd/core.c
50
break;
28
+F: hw/sd/sd*
51
+ case DISAS_JUMP:
29
+F: tests/sd*
52
+ tcg_gen_lookup_and_goto_ptr();
30
+
53
+ break;
31
USB
54
case DISAS_NORETURN:
32
M: Gerd Hoffmann <kraxel@redhat.com>
55
case DISAS_SWI:
33
S: Maintained
56
break;
57
--
34
--
58
2.16.2
35
2.16.2
59
36
60
37
diff view generated by jsdifflib