1
Arm patch queue -- these are all bug fix patches but we might
1
Arm pullreq for the 2.12 codefreeze...
2
as well put them in to rc0...
3
2
4
thanks
3
thanks
5
-- PMM
4
-- PMM
6
5
7
The following changes since commit 2c8cfc0b52b5a4d123c26c0b5fdf941be24805be:
6
The following changes since commit b39b61e410022f96ceb53d4381d25cba5126ac44:
8
7
9
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2018-03-19 11:44:26 +0000)
8
memory: fix flatview_access_valid RCU read lock/unlock imbalance (2018-03-09 15:55:20 +0000)
10
9
11
are available in the Git repository at:
10
are available in the Git repository at:
12
11
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180319
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180309
14
13
15
for you to fetch changes up to ff72cb6b46b95bb530787add5277c211af3d31c6:
14
for you to fetch changes up to 076a0fc32a73a9b960e0f73f04a531bc1bd94308:
16
15
17
hw/arm/raspi: Provide spin-loop code for AArch64 CPUs (2018-03-19 18:23:24 +0000)
16
MAINTAINERS: Add entries for SD (SDHCI, SDBus, SDCard) (2018-03-09 17:09:45 +0000)
18
17
19
----------------------------------------------------------------
18
----------------------------------------------------------------
20
target-arm queue:
19
target-arm queue:
21
* fsl-imx6: Fix incorrect Ethernet interrupt defines
20
* i.MX: Add i.MX7 SOC implementation and i.MX7 Sabre board
22
* dump: Update correct kdump phys_base field for AArch64
21
* Report the correct core count in A53 L2CTLR on the ZynqMP board
23
* char: i.MX: Add support for "TX complete" interrupt
22
* linux-user: preliminary SVE support work (signal handling)
24
* bcm2836/raspi: Fix various bugs resulting in panics trying
23
* hw/arm/boot: fix memory leak in case of error loading ELF file
25
to boot a Debian Linux kernel on raspi3
24
* hw/arm/boot: avoid reading off end of buffer if passed very
25
small image file
26
* hw/arm: Use more CONFIG switches for the object files
27
* target/arm: Add "-cpu max" support
28
* hw/arm/virt: Support -machine gic-version=max
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
26
32
27
----------------------------------------------------------------
33
----------------------------------------------------------------
28
Andrey Smirnov (2):
34
Alistair Francis (2):
29
char: i.MX: Simplify imx_update()
35
target/arm: Add a core count property
30
char: i.MX: Add support for "TX complete" interrupt
36
hw/arm: Set the core count for Xilinx's ZynqMP
31
37
32
Guenter Roeck (1):
38
Andrey Smirnov (3):
33
fsl-imx6: Swap Ethernet interrupt defines
39
pci: Add support for Designware IP block
40
i.MX: Add i.MX7 SOC implementation.
41
Implement support for i.MX7 Sabre board
34
42
35
Peter Maydell (9):
43
Marc-André Lureau (2):
36
hw/arm/raspi: Don't do board-setup or secure-boot for raspi3
44
arm: fix load ELF error leak
37
hw/arm/boot: assert that secure_boot and secure_board_setup are false for AArch64
45
arm: avoid heap-buffer-overflow in load_aarch64_image
38
hw/arm/boot: If booting a kernel in EL2, set SCR_EL3.HCE
39
hw/arm/bcm2386: Fix parent type of bcm2386
40
hw/arm/bcm2836: Rename bcm2836 type/struct to bcm283x
41
hw/arm/bcm2836: Create proper bcm2837 device
42
hw/arm/bcm2836: Use correct affinity values for BCM2837
43
hw/arm/bcm2836: Hardcode correct CPU type
44
hw/arm/raspi: Provide spin-loop code for AArch64 CPUs
45
46
46
Wei Huang (1):
47
Peter Maydell (6):
47
dump: Update correct kdump phys_base field for AArch64
48
target/arm: Query host CPU features on-demand at instance init
49
target/arm: Move definition of 'host' cpu type into cpu.c
50
target/arm: Add "-cpu max" support
51
target/arm: Make 'any' CPU just an alias for 'max'
52
hw/arm/virt: Add "max" to the list of CPU types "virt" supports
53
hw/arm/virt: Support -machine gic-version=max
48
54
49
include/hw/arm/bcm2836.h | 31 +++++++++++++---
55
Philippe Mathieu-Daudé (6):
50
include/hw/arm/fsl-imx6.h | 4 +-
56
sdcard: Do not trace CMD55, except when we already expect an ACMD
51
include/hw/char/imx_serial.h | 3 ++
57
sdcard: Display command name when tracing CMD/ACMD
52
dump.c | 14 +++++--
58
sdcard: Display which protocol is used when tracing (SD or SPI)
53
hw/arm/bcm2836.c | 87 +++++++++++++++++++++++++++++++-------------
59
sdcard: Add the Tuning Command (CMD19)
54
hw/arm/boot.c | 12 ++++++
60
sdhci: Fix a typo in comment
55
hw/arm/raspi.c | 77 +++++++++++++++++++++++++++++++--------
61
MAINTAINERS: Add entries for SD (SDHCI, SDBus, SDCard)
56
hw/char/imx_serial.c | 44 ++++++++++++++++------
57
hw/net/imx_fec.c | 28 +++++++++++++-
58
9 files changed, 237 insertions(+), 63 deletions(-)
59
62
63
Richard Henderson (5):
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
69
70
Thomas Huth (1):
71
hw/arm: Use more CONFIG switches for the object files
72
73
hw/arm/Makefile.objs | 31 +-
74
hw/pci-host/Makefile.objs | 2 +
75
hw/sd/Makefile.objs | 2 +-
76
hw/sd/sdmmc-internal.h | 24 ++
77
include/hw/arm/fsl-imx7.h | 222 +++++++++++
78
include/hw/pci-host/designware.h | 102 +++++
79
include/hw/pci/pci_ids.h | 2 +
80
linux-user/aarch64/target_syscall.h | 3 +
81
target/arm/cpu-qom.h | 2 +
82
target/arm/cpu.h | 11 +
83
target/arm/kvm_arm.h | 35 +-
84
hw/arm/boot.c | 4 +-
85
hw/arm/fsl-imx7.c | 582 ++++++++++++++++++++++++++++
86
hw/arm/mcimx7d-sabre.c | 90 +++++
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
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
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
2
2
3
Add support for "TX complete"/TXDC interrupt generate by real HW since
3
Add code needed to get a functional PCI subsytem when using in
4
it is needed to support guests other than Linux.
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).
5
7
6
Based on the patch by Bill Paul as found here:
8
Based on "i.MX6 Applications Processor Reference Manual" (Document
7
https://bugs.launchpad.net/qemu/+bug/1753314
9
Number: IMX6DQRM Rev. 4) as well as corresponding dirver in Linux
10
kernel (circa 4.13 - 4.16 found in drivers/pci/dwc/*)
8
11
9
Cc: qemu-devel@nongnu.org
10
Cc: qemu-arm@nongnu.org
11
Cc: Bill Paul <wpaul@windriver.com>
12
Cc: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Bill Paul <wpaul@windriver.com>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
12
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
15
Message-id: 20180315191141.6789-2-andrew.smirnov@gmail.com
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
15
---
19
include/hw/char/imx_serial.h | 3 +++
16
hw/pci-host/Makefile.objs | 2 +
20
hw/char/imx_serial.c | 20 +++++++++++++++++---
17
include/hw/pci-host/designware.h | 102 ++++++
21
2 files changed, 20 insertions(+), 3 deletions(-)
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
22
24
23
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
25
diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
24
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/char/imx_serial.h
27
--- a/hw/pci-host/Makefile.objs
26
+++ b/include/hw/char/imx_serial.h
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
27
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@
28
#define UCR2_RXEN (1<<1) /* Receiver enable */
41
+/*
29
#define UCR2_SRST (1<<0) /* Reset complete */
42
+ * Copyright (c) 2017, Impinj, Inc.
30
43
+ *
31
+#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
44
+ * Designware PCIe IP block emulation
32
+
45
+ *
33
#define UTS1_TXEMPTY (1<<6)
46
+ * This library is free software; you can redistribute it and/or
34
#define UTS1_RXEMPTY (1<<5)
47
+ * modify it under the terms of the GNU Lesser General Public
35
#define UTS1_TXFULL (1<<4)
48
+ * License as published by the Free Software Foundation; either
36
@@ -XXX,XX +XXX,XX @@ typedef struct IMXSerialState {
49
+ * version 2 of the License, or (at your option) any later version.
37
uint32_t ubmr;
50
+ *
38
uint32_t ubrc;
51
+ * This library is distributed in the hope that it will be useful,
39
uint32_t ucr3;
52
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+ uint32_t ucr4;
53
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41
54
+ * Lesser General Public License for more details.
42
qemu_irq irq;
55
+ *
43
CharBackend chr;
56
+ * You should have received a copy of the GNU Lesser General Public
44
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
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
45
index XXXXXXX..XXXXXXX 100644
144
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/char/imx_serial.c
145
--- a/include/hw/pci/pci_ids.h
47
+++ b/hw/char/imx_serial.c
146
+++ b/include/hw/pci/pci_ids.h
48
@@ -XXX,XX +XXX,XX @@
147
@@ -XXX,XX +XXX,XX @@
49
148
#define PCI_VENDOR_ID_VMWARE 0x15ad
50
static const VMStateDescription vmstate_imx_serial = {
149
#define PCI_DEVICE_ID_VMWARE_PVRDMA 0x0820
51
.name = TYPE_IMX_SERIAL,
150
52
- .version_id = 1,
151
+#define PCI_VENDOR_ID_SYNOPSYS 0x16C3
53
- .minimum_version_id = 1,
152
+
54
+ .version_id = 2,
153
#endif
55
+ .minimum_version_id = 2,
154
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
56
.fields = (VMStateField[]) {
155
new file mode 100644
57
VMSTATE_INT32(readbuff, IMXSerialState),
156
index XXXXXXX..XXXXXXX
58
VMSTATE_UINT32(usr1, IMXSerialState),
157
--- /dev/null
59
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_serial = {
158
+++ b/hw/pci-host/designware.c
60
VMSTATE_UINT32(ubmr, IMXSerialState),
159
@@ -XXX,XX +XXX,XX @@
61
VMSTATE_UINT32(ubrc, IMXSerialState),
160
+/*
62
VMSTATE_UINT32(ucr3, IMXSerialState),
161
+ * Copyright (c) 2018, Impinj, Inc.
63
+ VMSTATE_UINT32(ucr4, IMXSerialState),
162
+ *
64
VMSTATE_END_OF_LIST()
163
+ * Designware PCIe IP block emulation
65
},
164
+ *
66
};
165
+ * This library is free software; you can redistribute it and/or
67
@@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s)
166
+ * modify it under the terms of the GNU Lesser General Public
68
* unfortunately.
167
+ * License as published by the Free Software Foundation; either
69
*/
168
+ * version 2 of the License, or (at your option) any later version.
70
mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
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
+
71
+ /*
420
+ /*
72
+ * TCEN and TXDC are both bit 3
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.
73
+ */
424
+ */
74
+ mask |= s->ucr4 & UCR4_TCEN;
425
+ memory_region_set_enabled(other, false);
75
+
426
+ if (enabled) {
76
usr2 = s->usr2 & mask;
427
+ memory_region_set_size(current, size);
77
428
+ memory_region_set_address(current, base);
78
qemu_set_irq(s->irq, usr1 || usr2);
429
+ }
79
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
430
+ memory_region_set_enabled(current, enabled);
80
return s->ucr3;
431
+}
81
432
+
82
case 0x23: /* UCR4 */
433
+static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
83
+ return s->ucr4;
434
+ uint32_t val, int len)
84
+
435
+{
85
case 0x29: /* BRM Incremental */
436
+ DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d);
86
return 0x0; /* TODO */
437
+ DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
87
438
+ DesignwarePCIEViewport *viewport =
88
@@ -XXX,XX +XXX,XX @@ static void imx_serial_write(void *opaque, hwaddr offset,
439
+ designware_pcie_root_get_current_viewport(root);
89
* qemu_chr_fe_write and background I/O callbacks */
440
+
90
qemu_chr_fe_write_all(&s->chr, &ch, 1);
441
+ switch (address) {
91
s->usr1 &= ~USR1_TRDY;
442
+ case DESIGNWARE_PCIE_PORT_LINK_CONTROL:
92
+ s->usr2 &= ~USR2_TXDC;
443
+ case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL:
93
imx_update(s);
444
+ case DESIGNWARE_PCIE_PHY_DEBUG_R1:
94
s->usr1 |= USR1_TRDY;
445
+ /* No-op */
95
+ s->usr2 |= USR2_TXDC;
446
+ break;
96
imx_update(s);
447
+
97
}
448
+ case DESIGNWARE_PCIE_MSI_ADDR_LO:
98
break;
449
+ root->msi.base &= 0xFFFFFFFF00000000ULL;
99
@@ -XXX,XX +XXX,XX @@ static void imx_serial_write(void *opaque, hwaddr offset,
450
+ root->msi.base |= val;
100
s->ucr3 = value & 0xffff;
451
+ break;
101
break;
452
+
102
453
+ case DESIGNWARE_PCIE_MSI_ADDR_HI:
103
- case 0x2d: /* UTS1 */
454
+ root->msi.base &= 0x00000000FFFFFFFFULL;
104
case 0x23: /* UCR4 */
455
+ root->msi.base |= (uint64_t)val << 32;
105
+ s->ucr4 = value & 0xffff;
456
+ break;
106
+ imx_update(s);
457
+
107
+ break;
458
+ case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: {
108
+
459
+ const bool update_msi_mapping = !root->msi.intr[0].enable ^ !!val;
109
+ case 0x2d: /* UTS1 */
460
+
110
qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
461
+ root->msi.intr[0].enable = val;
111
HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
462
+
112
/* TODO */
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
113
--
923
--
114
2.16.2
924
2.16.2
115
925
116
926
diff view generated by jsdifflib
1
From: Wei Huang <wei@redhat.com>
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
2
2
3
For guest kernel that supports KASLR, the load address can change every
3
The following interfaces are partially or fully emulated:
4
time when guest VM runs. To find the physical base address correctly,
5
current QEMU dump searches VMCOREINFO for the string "NUMBER(phys_base)=".
6
However this string pattern is only available on x86_64. AArch64 uses a
7
different field, called "NUMBER(PHYS_OFFSET)=". This patch makes sure
8
QEMU dump uses the correct string on AArch64.
9
4
10
Signed-off-by: Wei Huang <wei@redhat.com>
5
* up to 2 Cortex A9 cores (SMP works with PSCI)
11
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
6
* A7 MPCORE (identical to A15 MPCORE)
12
Message-id: 1520615003-20869-1-git-send-email-wei@redhat.com
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]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
33
---
15
dump.c | 14 +++++++++++---
34
hw/arm/Makefile.objs | 1 +
16
1 file changed, 11 insertions(+), 3 deletions(-)
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
17
41
18
diff --git a/dump.c b/dump.c
42
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
19
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
20
--- a/dump.c
44
--- a/hw/arm/Makefile.objs
21
+++ b/dump.c
45
+++ b/hw/arm/Makefile.objs
22
@@ -XXX,XX +XXX,XX @@ static void vmcoreinfo_update_phys_base(DumpState *s)
46
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2) += mps2.o
23
47
obj-$(CONFIG_MPS2) += mps2-tz.o
24
lines = g_strsplit((char *)vmci, "\n", -1);
48
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
25
for (i = 0; lines[i]; i++) {
49
obj-$(CONFIG_IOTKIT) += iotkit.o
26
- if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) {
50
+obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
27
- if (qemu_strtou64(lines[i] + 18, NULL, 16,
51
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
28
+ const char *prefix = NULL;
52
new file mode 100644
29
+
53
index XXXXXXX..XXXXXXX
30
+ if (s->dump_info.d_machine == EM_X86_64) {
54
--- /dev/null
31
+ prefix = "NUMBER(phys_base)=";
55
+++ b/include/hw/arm/fsl-imx7.h
32
+ } else if (s->dump_info.d_machine == EM_AARCH64) {
56
@@ -XXX,XX +XXX,XX @@
33
+ prefix = "NUMBER(PHYS_OFFSET)=";
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);
34
+ }
494
+ }
35
+
495
+
36
+ if (prefix && g_str_has_prefix(lines[i], prefix)) {
496
+ if (i) {
37
+ if (qemu_strtou64(lines[i] + strlen(prefix), NULL, 16,
497
+ /* Secondary CPUs start in PSCI powered-down state */
38
&phys_base) < 0) {
498
+ object_property_set_bool(o, true,
39
- warn_report("Failed to read NUMBER(phys_base)=");
499
+ "start-powered-off", &error_abort);
40
+ warn_report("Failed to read %s", prefix);
500
+ }
41
} else {
501
+
42
s->dump_info.phys_base = phys_base;
502
+ object_property_set_bool(o, true, "realized", &error_abort);
43
}
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
44
--
879
--
45
2.16.2
880
2.16.2
46
881
47
882
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
2
2
3
Code of imx_update() is slightly confusing since the "flags" variable
3
Implement code needed to set up emulation of MCIMX7SABRE board from
4
doesn't really corespond to anything in real hardware and server as a
4
NXP. For more info about the HW see:
5
kitchensink accumulating events normally reported via USR1 and USR2
6
registers.
7
5
8
Change the code to explicitly evaluate state of interrupts reported
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
9
via USR1 and USR2 against corresponding masking bits and use the to
10
detemine if IRQ line should be asserted or not.
11
7
12
NOTE: Check for UTS1_TXEMPTY being set has been dropped for two
8
Cc: Peter Maydell <peter.maydell@linaro.org>
13
reasons:
9
Cc: Jason Wang <jasowang@redhat.com>
14
10
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
1. Emulation code implements a single character FIFO, so this flag
11
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
16
will always be set since characters are trasmitted as a part of
12
Cc: Michael S. Tsirkin <mst@redhat.com>
17
the code emulating "push" into the FIFO
18
19
2. imx_update() is really just a function doing ORing and maksing
20
of reported events, so checking for UTS1_TXEMPTY should happen,
21
if it's ever really needed should probably happen outside of
22
it.
23
24
Cc: qemu-devel@nongnu.org
13
Cc: qemu-devel@nongnu.org
25
Cc: qemu-arm@nongnu.org
14
Cc: qemu-arm@nongnu.org
26
Cc: Bill Paul <wpaul@windriver.com>
15
Cc: yurovsky@gmail.com
27
Cc: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
17
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
29
Message-id: 20180315191141.6789-1-andrew.smirnov@gmail.com
30
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
---
19
---
33
hw/char/imx_serial.c | 24 ++++++++++++++++--------
20
hw/arm/Makefile.objs | 2 +-
34
1 file changed, 16 insertions(+), 8 deletions(-)
21
hw/arm/mcimx7d-sabre.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++
22
2 files changed, 91 insertions(+), 1 deletion(-)
23
create mode 100644 hw/arm/mcimx7d-sabre.c
35
24
36
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
37
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/char/imx_serial.c
27
--- a/hw/arm/Makefile.objs
39
+++ b/hw/char/imx_serial.c
28
+++ b/hw/arm/Makefile.objs
40
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_serial = {
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2) += mps2.o
41
30
obj-$(CONFIG_MPS2) += mps2-tz.o
42
static void imx_update(IMXSerialState *s)
31
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
43
{
32
obj-$(CONFIG_IOTKIT) += iotkit.o
44
- uint32_t flags;
33
-obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
45
+ uint32_t usr1;
34
+obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
46
+ uint32_t usr2;
35
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
47
+ uint32_t mask;
36
new file mode 100644
48
37
index XXXXXXX..XXXXXXX
49
- flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
38
--- /dev/null
50
- if (s->ucr1 & UCR1_TXMPTYEN) {
39
+++ b/hw/arm/mcimx7d-sabre.c
51
- flags |= (s->uts1 & UTS1_TXEMPTY);
40
@@ -XXX,XX +XXX,XX @@
52
- } else {
41
+/*
53
- flags &= ~USR1_TRDY;
42
+ * Copyright (c) 2018, Impinj, Inc.
54
- }
43
+ *
55
+ /*
44
+ * MCIMX7D_SABRE Board System emulation.
56
+ * Lucky for us TRDY and RRDY has the same offset in both USR1 and
45
+ *
57
+ * UCR1, so we can get away with something as simple as the
46
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
58
+ * following:
47
+ *
59
+ */
48
+ * This code is licensed under the GPL, version 2 or later.
60
+ usr1 = s->usr1 & s->ucr1 & (USR1_TRDY | USR1_RRDY);
49
+ * See the file `COPYING' in the top level directory.
61
+ /*
50
+ *
62
+ * Bits that we want in USR2 are not as conveniently laid out,
51
+ * It (partially) emulates a mcimx7d_sabre board, with a Freescale
63
+ * unfortunately.
52
+ * i.MX7 SoC
64
+ */
53
+ */
65
+ mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
54
+
66
+ usr2 = s->usr2 & mask;
55
+#include "qemu/osdep.h"
67
56
+#include "qapi/error.h"
68
- qemu_set_irq(s->irq, !!flags);
57
+#include "qemu-common.h"
69
+ qemu_set_irq(s->irq, usr1 || usr2);
58
+#include "hw/arm/fsl-imx7.h"
70
}
59
+#include "hw/boards.h"
71
60
+#include "sysemu/sysemu.h"
72
static void imx_serial_reset(IMXSerialState *s)
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)
73
--
131
--
74
2.16.2
132
2.16.2
75
133
76
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
Now we have separate types for BCM2386 and BCM2387, we might as well
1
From: Richard Henderson <richard.henderson@linaro.org>
2
just hard-code the CPU type they use rather than having it passed
2
3
through as an object property. This then lets us put the initialization
3
Depending on the currently selected size of the SVE vector registers,
4
of the CPU object in init rather than realize.
4
we can either store the data within the "standard" allocation, or we
5
5
may beedn to allocate additional space with an EXTRA record.
6
Note that this change means that it's no longer possible on
6
7
the command line to use -cpu to ask for a different kind of
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
CPU than the SoC supports. This was never a supported thing to
8
Message-id: 20180303143823.27055-6-richard.henderson@linaro.org
9
do anyway; we were just not sanity-checking the command line.
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
11
This does require us to only build the bcm2837 object on
12
TARGET_AARCH64 configs, since otherwise it won't instantiate
13
due to the missing cortex-a53 device and "make check" will fail.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Message-id: 20180313153458.26822-9-peter.maydell@linaro.org
19
---
11
---
20
hw/arm/bcm2836.c | 24 +++++++++++++++---------
12
linux-user/signal.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++-----
21
hw/arm/raspi.c | 2 --
13
1 file changed, 192 insertions(+), 18 deletions(-)
22
2 files changed, 15 insertions(+), 11 deletions(-)
14
23
15
diff --git a/linux-user/signal.c b/linux-user/signal.c
24
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/bcm2836.c
17
--- a/linux-user/signal.c
27
+++ b/hw/arm/bcm2836.c
18
+++ b/linux-user/signal.c
28
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ struct target_extra_context {
29
20
uint32_t reserved[3];
30
struct BCM283XInfo {
31
const char *name;
32
+ const char *cpu_type;
33
int clusterid;
34
};
21
};
35
22
36
static const BCM283XInfo bcm283x_socs[] = {
23
+#define TARGET_SVE_MAGIC 0x53564501
37
{
24
+
38
.name = TYPE_BCM2836,
25
+struct target_sve_context {
39
+ .cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"),
26
+ struct target_aarch64_ctx head;
40
.clusterid = 0xf,
27
+ uint16_t vl;
41
},
28
+ uint16_t reserved[3];
42
+#ifdef TARGET_AARCH64
29
+ /* The actual SVE data immediately follows. It is layed out
43
{
30
+ * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
44
.name = TYPE_BCM2837,
31
+ * the original struct pointer.
45
+ .cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
32
+ */
46
.clusterid = 0x0,
33
+};
47
},
34
+
48
+#endif
35
+#define TARGET_SVE_VQ_BYTES 16
49
};
36
+
50
37
+#define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES)
51
static void bcm2836_init(Object *obj)
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);
56
}
57
58
+static void target_setup_sve_record(struct target_sve_context *sve,
59
+ CPUARMState *env, int vq, int size)
60
+{
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
+ }
84
+}
85
+
86
static void target_restore_general_frame(CPUARMState *env,
87
struct target_rt_sigframe *sf)
52
{
88
{
53
BCM283XState *s = BCM283X(obj);
89
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
54
+ BCM283XClass *bc = BCM283X_GET_CLASS(obj);
90
}
55
+ const BCM283XInfo *info = bc->info;
56
+ int n;
57
+
58
+ for (n = 0; n < BCM283X_NCPUS; n++) {
59
+ object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
60
+ info->cpu_type);
61
+ object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
62
+ &error_abort);
63
+ }
64
65
object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL);
66
object_property_add_child(obj, "control", OBJECT(&s->control), NULL);
67
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
68
69
/* common peripherals from bcm2835 */
70
71
- obj = OBJECT(dev);
72
- for (n = 0; n < BCM283X_NCPUS; n++) {
73
- object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
74
- s->cpu_type);
75
- object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
76
- &error_abort);
77
- }
78
-
79
obj = object_property_get_link(OBJECT(dev), "ram", &err);
80
if (obj == NULL) {
81
error_setg(errp, "%s: required ram link not found: %s",
82
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
83
}
91
}
84
92
85
static Property bcm2836_props[] = {
93
+static void target_restore_sve_record(CPUARMState *env,
86
- DEFINE_PROP_STRING("cpu-type", BCM283XState, cpu_type),
94
+ struct target_sve_context *sve, int vq)
87
DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
95
+{
88
BCM283X_NCPUS),
96
+ int i, j;
89
DEFINE_PROP_END_OF_LIST()
97
+
90
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
98
+ /* Note that SVE regs are stored as a byte stream, with each byte element
91
index XXXXXXX..XXXXXXX 100644
99
+ * at a subsequent address. This corresponds to a little-endian load
92
--- a/hw/arm/raspi.c
100
+ * of our 64-bit hunks.
93
+++ b/hw/arm/raspi.c
101
+ */
94
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
102
+ for (i = 0; i < 32; ++i) {
95
/* Setup the SOC */
103
+ uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i);
96
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
104
+ for (j = 0; j < vq * 2; ++j) {
97
&error_abort);
105
+ __get_user_e(env->vfp.zregs[i].d[j], z + j, le);
98
- object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type",
106
+ }
99
- &error_abort);
107
+ }
100
object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
108
+ for (i = 0; i <= 16; ++i) {
101
&error_abort);
109
+ uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i);
102
int board_rev = version == 3 ? 0xa02082 : 0xa21041;
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
+ }
120
+}
121
+
122
static int target_restore_sigframe(CPUARMState *env,
123
struct target_rt_sigframe *sf)
124
{
125
struct target_aarch64_ctx *ctx, *extra = NULL;
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;
137
break;
138
139
+ case TARGET_SVE_MAGIC:
140
+ if (arm_feature(env, ARM_FEATURE_SVE)) {
141
+ vq = (env->vfp.zcr_el[1] & 0xf) + 1;
142
+ sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
143
+ if (!sve && size == sve_size) {
144
+ sve = (struct target_sve_context *)ctx;
145
+ break;
146
+ }
147
+ }
148
+ err = true;
149
+ goto exit;
150
+
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;
166
}
167
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)
194
+{
195
+ /* Make sure there will always be space for the end marker. */
196
+ const int std_size = sizeof(struct target_rt_sigframe)
197
+ - sizeof(struct target_aarch64_ctx);
198
+ int this_loc = l->total_size;
199
+
200
+ if (l->extra_base) {
201
+ /* Once we have begun an extra space, all allocations go there. */
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;
220
+}
221
+
222
static void target_setup_frame(int usig, struct target_sigaction *ka,
223
target_siginfo_t *info, target_sigset_t *set,
224
CPUARMState *env)
225
{
226
- int size = offsetof(struct target_rt_sigframe, uc.tuc_mcontext.__reserved);
227
- int fpsimd_ofs, end1_ofs, fr_ofs, end2_ofs = 0;
228
- int extra_ofs = 0, extra_base = 0, extra_size = 0;
229
+ target_sigframe_layout layout = {
230
+ /* Begin with the size pointing to the reserved space. */
231
+ .total_size = offsetof(struct target_rt_sigframe,
232
+ uc.tuc_mcontext.__reserved),
233
+ };
234
+ int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
235
struct target_rt_sigframe *frame;
236
struct target_rt_frame_record *fr;
237
abi_ulong frame_addr, return_addr;
238
239
- fpsimd_ofs = size;
240
- size += sizeof(struct target_fpsimd_context);
241
- end1_ofs = size;
242
- size += sizeof(struct target_aarch64_ctx);
243
- fr_ofs = size;
244
- size += sizeof(struct target_rt_frame_record);
245
+ /* FPSIMD record is always in the standard space. */
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. */
103
--
305
--
104
2.16.2
306
2.16.2
105
307
106
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
1
If we're directly booting a Linux kernel and the CPU supports both
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
2
EL3 and EL2, we start the kernel in EL2, as it expects. We must also
3
set the SCR_EL3.HCE bit in this situation, so that the HVC
4
instruction is enabled rather than UNDEFing. Otherwise at least some
5
kernels will panic when trying to initialize KVM in the guest.
6
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>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20180313153458.26822-4-peter.maydell@linaro.org
9
---
22
---
10
hw/arm/boot.c | 5 +++++
23
hw/arm/boot.c | 1 +
11
1 file changed, 5 insertions(+)
24
1 file changed, 1 insertion(+)
12
25
13
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
26
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
14
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/boot.c
28
--- a/hw/arm/boot.c
16
+++ b/hw/arm/boot.c
29
+++ b/hw/arm/boot.c
17
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
30
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
18
assert(!info->secure_board_setup);
31
19
}
32
load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err);
20
33
if (err) {
21
+ if (arm_feature(env, ARM_FEATURE_EL2)) {
34
+ error_free(err);
22
+ /* If we have EL2 then Linux expects the HVC insn to work */
35
return ret;
23
+ env->cp15.scr_el3 |= SCR_HCE;
36
}
24
+ }
37
25
+
26
/* Set to non-secure if not a secure boot */
27
if (!info->secure_boot &&
28
(cs != first_cpu || !info->secure_board_setup)) {
29
--
38
--
30
2.16.2
39
2.16.2
31
40
32
41
diff view generated by jsdifflib
1
Add some assertions that if we're about to boot an AArch64 kernel,
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
2
the board code has not mistakenly set either secure_boot or
3
secure_board_setup. It doesn't make sense to set secure_boot,
4
because all AArch64 kernels must be booted in non-secure mode.
5
2
6
It might in theory make sense to set secure_board_setup, but
3
Spotted by ASAN:
7
we don't currently support that, because only the AArch32
8
bootloader[] code calls this hook; bootloader_aarch64[] does not.
9
Since we don't have a current need for this functionality, just
10
assert that we don't try to use it. If it's needed we'll add
11
it later.
12
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>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20180313153458.26822-3-peter.maydell@linaro.org
16
---
22
---
17
hw/arm/boot.c | 7 +++++++
23
hw/arm/boot.c | 3 ++-
18
1 file changed, 7 insertions(+)
24
1 file changed, 2 insertions(+), 1 deletion(-)
19
25
20
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
26
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
21
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/boot.c
28
--- a/hw/arm/boot.c
23
+++ b/hw/arm/boot.c
29
+++ b/hw/arm/boot.c
24
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
30
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
25
} else {
31
}
26
env->pstate = PSTATE_MODE_EL1h;
32
27
}
33
/* check the arm64 magic header value -- very old kernels may not have it */
28
+ /* AArch64 kernels never boot in secure mode */
34
- if (memcmp(buffer + ARM64_MAGIC_OFFSET, "ARM\x64", 4) == 0) {
29
+ assert(!info->secure_boot);
35
+ if (size > ARM64_MAGIC_OFFSET + 4 &&
30
+ /* This hook is only supported for AArch32 currently:
36
+ memcmp(buffer + ARM64_MAGIC_OFFSET, "ARM\x64", 4) == 0) {
31
+ * bootloader_aarch64[] will not call the hook, and
37
uint64_t hdrvals[2];
32
+ * the code above has already dropped us into EL2 or EL1.
38
33
+ */
39
/* The arm64 Image header has text_offset and image_size fields at 8 and
34
+ assert(!info->secure_board_setup);
35
}
36
37
/* Set to non-secure if not a secure boot */
38
--
40
--
39
2.16.2
41
2.16.2
40
42
41
43
diff view generated by jsdifflib
1
The bcm2837 is pretty similar to the bcm2836, but it does have
1
Currently we query the host CPU features in the class init function
2
some differences. Notably, the MPIDR affinity aff1 values it
2
for the TYPE_ARM_HOST_CPU class, so that we can later copy them
3
sets for the CPUs are 0x0, rather than the 0xf that the bcm2836
3
from the class object into the instance object in the object
4
uses, and if this is wrong Linux will not boot.
4
instance init function. This is awkward for implementing "-cpu max",
5
5
which should work like "-cpu host" for KVM but like "cpu with all
6
Rather than trying to have one device with properties that
6
implemented features" for TCG.
7
configure it differently for the two cases, create two
7
8
separate QOM devices for the two SoCs. We use the same approach
8
Move the place where we store the information about the host CPU from
9
as hw/arm/aspeed_soc.c and share code and have a data table
9
a class object to static variables in kvm.c, and then in the instance
10
that might differ per-SoC. For the moment the two types don't
10
init function call a new kvm_arm_set_cpu_features_from_host()
11
actually have different behaviour.
11
function which will query the host kernel if necessary and then
12
fill in the CPU instance fields.
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).
12
26
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
28
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20180313153458.26822-7-peter.maydell@linaro.org
29
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
30
Message-id: 20180308130626.12393-2-peter.maydell@linaro.org
16
---
31
---
17
include/hw/arm/bcm2836.h | 19 +++++++++++++++++++
32
target/arm/cpu.h | 5 +++++
18
hw/arm/bcm2836.c | 37 ++++++++++++++++++++++++++++++++-----
33
target/arm/kvm_arm.h | 35 ++++++++++++++++++++++++-----------
19
hw/arm/raspi.c | 3 ++-
34
target/arm/cpu.c | 13 +++++++++++++
20
3 files changed, 53 insertions(+), 6 deletions(-)
35
target/arm/kvm.c | 36 +++++++++++++++++++-----------------
21
36
target/arm/kvm32.c | 8 ++++----
22
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
37
target/arm/kvm64.c | 8 ++++----
23
index XXXXXXX..XXXXXXX 100644
38
6 files changed, 69 insertions(+), 36 deletions(-)
24
--- a/include/hw/arm/bcm2836.h
39
25
+++ b/include/hw/arm/bcm2836.h
40
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@
41
index XXXXXXX..XXXXXXX 100644
27
42
--- a/target/arm/cpu.h
28
#define BCM283X_NCPUS 4
43
+++ b/target/arm/cpu.h
29
44
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
30
+/* These type names are for specific SoCs; other than instantiating
45
/* Uniprocessor system with MP extensions */
31
+ * them, code using these devices should always handle them via the
46
bool mp_is_up;
32
+ * BCM283x base class, so they have no BCM2836(obj) etc macros.
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)
50
+ */
51
+ bool host_cpu_probe_failed;
52
+
53
/* Specify the number of cores in this CPU cluster. Used for the L2CTLR
54
* register.
55
*/
56
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/kvm_arm.h
59
+++ b/target/arm/kvm_arm.h
60
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
61
void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
62
63
#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
64
-#define ARM_HOST_CPU_CLASS(klass) \
65
- OBJECT_CLASS_CHECK(ARMHostCPUClass, (klass), TYPE_ARM_HOST_CPU)
66
-#define ARM_HOST_CPU_GET_CLASS(obj) \
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)
33
+ */
77
+ */
34
+#define TYPE_BCM2836 "bcm2836"
78
+typedef struct ARMHostCPUFeatures {
35
+#define TYPE_BCM2837 "bcm2837"
79
uint64_t features;
36
+
80
uint32_t target;
37
typedef struct BCM283XState {
81
const char *dtb_compatible;
38
/*< private >*/
82
-} ARMHostCPUClass;
39
DeviceState parent_obj;
83
+} ARMHostCPUFeatures;
40
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XState {
84
41
BCM2835PeripheralState peripherals;
85
/**
42
} BCM283XState;
86
* kvm_arm_get_host_cpu_features:
43
87
@@ -XXX,XX +XXX,XX @@ typedef struct ARMHostCPUClass {
44
+typedef struct BCM283XInfo BCM283XInfo;
88
* Probe the capabilities of the host kernel's preferred CPU and fill
45
+
89
* in the ARMHostCPUClass struct accordingly.
46
+typedef struct BCM283XClass {
90
*/
47
+ DeviceClass parent_class;
91
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc);
48
+ const BCM283XInfo *info;
92
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
49
+} BCM283XClass;
93
50
+
94
+/**
51
+#define BCM283X_CLASS(klass) \
95
+ * kvm_arm_set_cpu_features_from_host:
52
+ OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
96
+ * @cpu: ARMCPU to set the features for
53
+#define BCM283X_GET_CLASS(obj) \
97
+ *
54
+ OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
98
+ * Set up the ARMCPU struct fields up to match the information probed
55
+
99
+ * from the host CPU.
56
#endif /* BCM2836_H */
100
+ */
57
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
101
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
58
index XXXXXXX..XXXXXXX 100644
102
59
--- a/hw/arm/bcm2836.c
103
/**
60
+++ b/hw/arm/bcm2836.c
104
* kvm_arm_sync_mpstate_to_kvm
61
@@ -XXX,XX +XXX,XX @@
105
@@ -XXX,XX +XXX,XX @@ void kvm_arm_pmu_init(CPUState *cs);
62
/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
106
63
#define BCM2836_CONTROL_BASE 0x40000000
107
#else
64
108
65
+struct BCM283XInfo {
109
+static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
66
+ const char *name;
110
+{
67
+};
111
+ /* This should never actually be called in the "not KVM" case,
68
+
112
+ * but set up the fields to indicate an error anyway.
69
+static const BCM283XInfo bcm283x_socs[] = {
113
+ */
70
+ {
114
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
71
+ .name = TYPE_BCM2836,
115
+ cpu->host_cpu_probe_failed = true;
72
+ },
116
+}
73
+ {
117
+
74
+ .name = TYPE_BCM2837,
118
static inline int kvm_arm_vgic_probe(void)
75
+ },
119
{
76
+};
120
return 0;
77
+
121
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
78
static void bcm2836_init(Object *obj)
122
index XXXXXXX..XXXXXXX 100644
79
{
123
--- a/target/arm/cpu.c
80
BCM283XState *s = BCM283X(obj);
124
+++ b/target/arm/cpu.c
81
@@ -XXX,XX +XXX,XX @@ static Property bcm2836_props[] = {
125
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
82
DEFINE_PROP_END_OF_LIST()
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),
83
};
212
};
84
213
85
-static void bcm2836_class_init(ObjectClass *oc, void *data)
214
int kvm_arch_init(MachineState *ms, KVMState *s)
86
+static void bcm283x_class_init(ObjectClass *oc, void *data)
215
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
87
{
216
index XXXXXXX..XXXXXXX 100644
88
DeviceClass *dc = DEVICE_CLASS(oc);
217
--- a/target/arm/kvm32.c
89
+ BCM283XClass *bc = BCM283X_CLASS(oc);
218
+++ b/target/arm/kvm32.c
90
219
@@ -XXX,XX +XXX,XX @@ static inline void set_feature(uint64_t *features, int feature)
91
- dc->props = bcm2836_props;
220
*features |= 1ULL << feature;
92
+ bc->info = data;
221
}
93
dc->realize = bcm2836_realize;
222
94
+ dc->props = bcm2836_props;
223
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
95
}
224
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
96
225
{
97
-static const TypeInfo bcm2836_type_info = {
226
/* Identify the feature bits corresponding to the host CPU, and
98
+static const TypeInfo bcm283x_type_info = {
227
* fill out the ARMHostCPUClass fields accordingly. To do this
99
.name = TYPE_BCM283X,
228
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
100
.parent = TYPE_DEVICE,
229
return false;
101
.instance_size = sizeof(BCM283XState),
230
}
102
.instance_init = bcm2836_init,
231
103
- .class_init = bcm2836_class_init,
232
- ahcc->target = init.target;
104
+ .class_size = sizeof(BCM283XClass),
233
+ ahcf->target = init.target;
105
+ .abstract = true,
234
106
};
235
/* This is not strictly blessed by the device tree binding docs yet,
107
236
* but in practice the kernel does not care about this string so
108
static void bcm2836_register_types(void)
237
* there is no point maintaining an KVM_ARM_TARGET_* -> string table.
109
{
238
*/
110
- type_register_static(&bcm2836_type_info);
239
- ahcc->dtb_compatible = "arm,arm-v7";
111
+ int i;
240
+ ahcf->dtb_compatible = "arm,arm-v7";
112
+
241
113
+ type_register_static(&bcm283x_type_info);
242
for (i = 0; i < ARRAY_SIZE(idregs); i++) {
114
+ for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) {
243
ret = ioctl(fdarray[2], KVM_GET_ONE_REG, &idregs[i]);
115
+ TypeInfo ti = {
244
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
116
+ .name = bcm283x_socs[i].name,
245
set_feature(&features, ARM_FEATURE_VFP4);
117
+ .parent = TYPE_BCM283X,
246
}
118
+ .class_init = bcm283x_class_init,
247
119
+ .class_data = (void *) &bcm283x_socs[i],
248
- ahcc->features = features;
120
+ };
249
+ ahcf->features = features;
121
+ type_register(&ti);
250
122
+ }
251
return true;
123
}
252
}
124
253
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
125
type_init(bcm2836_register_types)
254
index XXXXXXX..XXXXXXX 100644
126
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
255
--- a/target/arm/kvm64.c
127
index XXXXXXX..XXXXXXX 100644
256
+++ b/target/arm/kvm64.c
128
--- a/hw/arm/raspi.c
257
@@ -XXX,XX +XXX,XX @@ static inline void unset_feature(uint64_t *features, int feature)
129
+++ b/hw/arm/raspi.c
258
*features &= ~(1ULL << feature);
130
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
259
}
131
BusState *bus;
260
132
DeviceState *carddev;
261
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
133
262
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
134
- object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM283X);
263
{
135
+ object_initialize(&s->soc, sizeof(s->soc),
264
/* Identify the feature bits corresponding to the host CPU, and
136
+ version == 3 ? TYPE_BCM2837 : TYPE_BCM2836);
265
* fill out the ARMHostCPUClass fields accordingly. To do this
137
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
266
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
138
&error_abort);
267
return false;
139
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
}
140
--
286
--
141
2.16.2
287
2.16.2
142
288
143
289
diff view generated by jsdifflib
1
The raspi3 has AArch64 CPUs, which means that our smpboot
1
Move the definition of the 'host' cpu type into cpu.c, where all the
2
code for keeping the secondary CPUs in a pen needs to have
2
other CPU types are defined. We can do this now we've decoupled it
3
a version for A64 as well as A32. Without this, the
3
from the KVM-specific host feature probing. This means we now create
4
secondary CPUs go into an infinite loop of taking undefined
4
the type unconditionally (assuming we were built with KVM support at
5
instruction exceptions.
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.
6
8
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20180313153458.26822-10-peter.maydell@linaro.org
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Message-id: 20180308130626.12393-3-peter.maydell@linaro.org
10
---
13
---
11
hw/arm/raspi.c | 41 ++++++++++++++++++++++++++++++++++++++++-
14
target/arm/cpu.c | 24 ++++++++++++++++++++++++
12
1 file changed, 40 insertions(+), 1 deletion(-)
15
target/arm/kvm.c | 19 -------------------
16
2 files changed, 24 insertions(+), 19 deletions(-)
13
17
14
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
18
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/raspi.c
20
--- a/target/arm/cpu.c
17
+++ b/hw/arm/raspi.c
21
+++ b/target/arm/cpu.c
18
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
19
#define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
23
#endif
20
#define FIRMWARE_ADDR_2 0x8000 /* Pi 2 loads kernel.img here by default */
21
#define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */
22
+#define SPINTABLE_ADDR 0xd8 /* Pi 3 bootloader spintable */
23
24
/* Table of Linux board IDs for different Pi versions */
25
static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};
26
@@ -XXX,XX +XXX,XX @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
27
info->smp_loader_start);
28
}
24
}
29
25
30
+static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
26
+#ifdef CONFIG_KVM
27
+static void arm_host_initfn(Object *obj)
31
+{
28
+{
32
+ /* Unlike the AArch32 version we don't need to call the board setup hook.
29
+ ARMCPU *cpu = ARM_CPU(obj);
33
+ * The mechanism for doing the spin-table is also entirely different.
34
+ * We must have four 64-bit fields at absolute addresses
35
+ * 0xd8, 0xe0, 0xe8, 0xf0 in RAM, which are the flag variables for
36
+ * our CPUs, and which we must ensure are zero initialized before
37
+ * the primary CPU goes into the kernel. We put these variables inside
38
+ * a rom blob, so that the reset for ROM contents zeroes them for us.
39
+ */
40
+ static const uint32_t smpboot[] = {
41
+ 0xd2801b05, /* mov x5, 0xd8 */
42
+ 0xd53800a6, /* mrs x6, mpidr_el1 */
43
+ 0x924004c6, /* and x6, x6, #0x3 */
44
+ 0xd503205f, /* spin: wfe */
45
+ 0xf86678a4, /* ldr x4, [x5,x6,lsl #3] */
46
+ 0xb4ffffc4, /* cbz x4, spin */
47
+ 0xd2800000, /* mov x0, #0x0 */
48
+ 0xd2800001, /* mov x1, #0x0 */
49
+ 0xd2800002, /* mov x2, #0x0 */
50
+ 0xd2800003, /* mov x3, #0x0 */
51
+ 0xd61f0080, /* br x4 */
52
+ };
53
+
30
+
54
+ static const uint64_t spintables[] = {
31
+ kvm_arm_set_cpu_features_from_host(cpu);
55
+ 0, 0, 0, 0
56
+ };
57
+
58
+ rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
59
+ info->smp_loader_start);
60
+ rom_add_blob_fixed("raspi_spintables", spintables, sizeof(spintables),
61
+ SPINTABLE_ADDR);
62
+}
32
+}
63
+
33
+
64
static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info)
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)
65
{
47
{
66
arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
48
TypeInfo type_info = {
67
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
49
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
68
/* Pi2 and Pi3 requires SMP setup */
50
cpu_register(info);
69
if (version >= 2) {
51
info++;
70
binfo.smp_loader_start = SMPBOOT_ADDR;
71
- binfo.write_secondary_boot = write_smpboot;
72
+ if (version == 2) {
73
+ binfo.write_secondary_boot = write_smpboot;
74
+ } else {
75
+ binfo.write_secondary_boot = write_smpboot64;
76
+ }
77
binfo.secondary_cpu_reset_hook = reset_secondary;
78
}
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
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/kvm.c
63
+++ b/target/arm/kvm.c
64
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
65
env->features = arm_host_cpu_features.features;
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)
86
{
87
/* For ARM interrupt delivery is always asynchronous,
88
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init(MachineState *ms, KVMState *s)
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;
95
}
79
96
80
--
97
--
81
2.16.2
98
2.16.2
82
99
83
100
diff view generated by jsdifflib
1
The TypeInfo and state struct for bcm2386 disagree about what the
1
Add support for "-cpu max" for ARM guests. This CPU type behaves
2
parent class is -- the TypeInfo says it's TYPE_SYS_BUS_DEVICE,
2
like "-cpu host" when KVM is enabled, and like a system CPU with
3
but the BCM2386State struct only defines the parent_obj field
3
the maximum possible feature set otherwise. (Note that this means
4
as DeviceState. This would have caused problems if anything
4
it won't be migratable across versions, as we will likely add
5
actually tried to treat the object as a TYPE_SYS_BUS_DEVICE.
5
features to it in future.)
6
Fix the TypeInfo to use TYPE_DEVICE as the parent, since we don't
7
need any of the additional functionality TYPE_SYS_BUS_DEVICE
8
provides.
9
6
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20180308130626.12393-4-peter.maydell@linaro.org
13
Message-id: 20180313153458.26822-5-peter.maydell@linaro.org
14
---
10
---
15
hw/arm/bcm2836.c | 2 +-
11
target/arm/cpu-qom.h | 2 ++
16
1 file changed, 1 insertion(+), 1 deletion(-)
12
target/arm/cpu.c | 24 ++++++++++++++++++++++++
13
target/arm/cpu64.c | 21 +++++++++++++++++++++
14
3 files changed, 47 insertions(+)
17
15
18
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
16
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/bcm2836.c
18
--- a/target/arm/cpu-qom.h
21
+++ b/hw/arm/bcm2836.c
19
+++ b/target/arm/cpu-qom.h
22
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
20
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info;
23
21
#define ARM_CPU_GET_CLASS(obj) \
24
static const TypeInfo bcm2836_type_info = {
22
OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU)
25
.name = TYPE_BCM2836,
23
26
- .parent = TYPE_SYS_BUS_DEVICE,
24
+#define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU
27
+ .parent = TYPE_DEVICE,
25
+
28
.instance_size = sizeof(BCM2836State),
26
/**
29
.instance_init = bcm2836_init,
27
* ARMCPUClass:
30
.class_init = bcm2836_class_init,
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;
35
}
36
37
+#ifndef TARGET_AARCH64
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.
42
+ */
43
+static void arm_max_initfn(Object *obj)
44
+{
45
+ ARMCPU *cpu = ARM_CPU(obj);
46
+
47
+ if (kvm_enabled()) {
48
+ kvm_arm_set_cpu_features_from_host(cpu);
49
+ } else {
50
+ cortex_a15_initfn(obj);
51
+ /* In future we might add feature bits here even if the
52
+ * real-world A15 doesn't implement them.
53
+ */
54
+ }
55
+}
56
+#endif
57
+
58
#ifdef CONFIG_USER_ONLY
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);
98
+ } else {
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
+ */
103
+ }
104
+}
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 },
116
#endif
31
--
117
--
32
2.16.2
118
2.16.2
33
119
34
120
diff view generated by jsdifflib
1
Our BCM2836 type is really a generic one that can be any of
1
Now we have a working '-cpu max', the linux-user-only
2
the bcm283x family. Rename it accordingly. We change only
2
'any' CPU is pretty much the same thing, so implement it
3
the names which are visible via the header file to the
3
that way.
4
rest of the QEMU code, leaving private function names
5
in bcm2836.c as they are.
6
4
7
This is a preliminary to making bcm283x be an abstract
5
For the moment we don't add any of the extra feature bits
8
parent class to specific types for the bcm2836 and bcm2837.
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
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
11
Message-id: 20180308130626.12393-5-peter.maydell@linaro.org
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20180313153458.26822-6-peter.maydell@linaro.org
14
---
14
---
15
include/hw/arm/bcm2836.h | 12 ++++++------
15
target/arm/cpu.c | 52 +++++++++++++++++++++++++----------------------
16
hw/arm/bcm2836.c | 17 +++++++++--------
16
target/arm/cpu64.c | 59 ++++++++++++++++++++++++++----------------------------
17
hw/arm/raspi.c | 16 ++++++++--------
17
2 files changed, 56 insertions(+), 55 deletions(-)
18
3 files changed, 23 insertions(+), 22 deletions(-)
19
18
20
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
19
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2836.h
21
--- a/target/arm/cpu.c
23
+++ b/include/hw/arm/bcm2836.h
22
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
25
#include "hw/arm/bcm2835_peripherals.h"
24
ObjectClass *oc;
26
#include "hw/intc/bcm2836_control.h"
25
char *typename;
27
26
char **cpuname;
28
-#define TYPE_BCM2836 "bcm2836"
27
+ const char *cpunamestr;
29
-#define BCM2836(obj) OBJECT_CHECK(BCM2836State, (obj), TYPE_BCM2836)
28
30
+#define TYPE_BCM283X "bcm283x"
29
cpuname = g_strsplit(cpu_model, ",", 1);
31
+#define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X)
30
- typename = g_strdup_printf(ARM_CPU_TYPE_NAME("%s"), cpuname[0]);
32
31
+ cpunamestr = cpuname[0];
33
-#define BCM2836_NCPUS 4
32
+#ifdef CONFIG_USER_ONLY
34
+#define BCM283X_NCPUS 4
33
+ /* For backwards compatibility usermode emulation allows "-cpu any",
35
34
+ * which has the same semantics as "-cpu max".
36
-typedef struct BCM2836State {
35
+ */
37
+typedef struct BCM283XState {
36
+ if (!strcmp(cpunamestr, "any")) {
38
/*< private >*/
37
+ cpunamestr = "max";
39
DeviceState parent_obj;
38
+ }
40
/*< public >*/
39
+#endif
41
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2836State {
40
+ typename = g_strdup_printf(ARM_CPU_TYPE_NAME("%s"), cpunamestr);
42
char *cpu_type;
41
oc = object_class_by_name(typename);
43
uint32_t enabled_cpus;
42
g_strfreev(cpuname);
44
43
g_free(typename);
45
- ARMCPU cpus[BCM2836_NCPUS];
44
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
46
+ ARMCPU cpus[BCM283X_NCPUS];
45
kvm_arm_set_cpu_features_from_host(cpu);
47
BCM2836ControlState control;
46
} else {
48
BCM2835PeripheralState peripherals;
47
cortex_a15_initfn(obj);
49
-} BCM2836State;
48
- /* In future we might add feature bits here even if the
50
+} BCM283XState;
49
- * real-world A15 doesn't implement them.
51
50
- */
52
#endif /* BCM2836_H */
51
- }
53
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
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
54
index XXXXXXX..XXXXXXX 100644
100
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/arm/bcm2836.c
101
--- a/target/arm/cpu64.c
56
+++ b/hw/arm/bcm2836.c
102
+++ b/target/arm/cpu64.c
57
@@ -XXX,XX +XXX,XX @@
103
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
58
104
kvm_arm_set_cpu_features_from_host(cpu);
59
static void bcm2836_init(Object *obj)
105
} else {
60
{
106
aarch64_a57_initfn(obj);
61
- BCM2836State *s = BCM2836(obj);
107
- /* In future we might add feature bits here even if the
62
+ BCM283XState *s = BCM283X(obj);
108
- * real-world A57 doesn't implement them.
63
109
+#ifdef CONFIG_USER_ONLY
64
object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL);
110
+ /* We don't set these in system emulation mode for the moment,
65
object_property_add_child(obj, "control", OBJECT(&s->control), NULL);
111
+ * since we don't correctly set the ID registers to advertise them,
66
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
112
+ * and in some cases they're only available in AArch64 and not AArch32,
67
113
+ * whereas the architecture requires them to be present in both if
68
static void bcm2836_realize(DeviceState *dev, Error **errp)
114
+ * present in either.
69
{
70
- BCM2836State *s = BCM2836(dev);
71
+ BCM283XState *s = BCM283X(dev);
72
Object *obj;
73
Error *err = NULL;
74
int n;
75
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
76
/* common peripherals from bcm2835 */
77
78
obj = OBJECT(dev);
79
- for (n = 0; n < BCM2836_NCPUS; n++) {
80
+ for (n = 0; n < BCM283X_NCPUS; n++) {
81
object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
82
s->cpu_type);
83
object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
84
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
85
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
86
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));
87
88
- for (n = 0; n < BCM2836_NCPUS; n++) {
89
+ for (n = 0; n < BCM283X_NCPUS; n++) {
90
/* Mirror bcm2836, which has clusterid set to 0xf
91
* TODO: this should be converted to a property of ARM_CPU
92
*/
115
*/
93
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
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
}
94
}
139
}
95
140
96
static Property bcm2836_props[] = {
141
-#ifdef CONFIG_USER_ONLY
97
- DEFINE_PROP_STRING("cpu-type", BCM2836State, cpu_type),
142
-static void aarch64_any_initfn(Object *obj)
98
- DEFINE_PROP_UINT32("enabled-cpus", BCM2836State, enabled_cpus, BCM2836_NCPUS),
143
-{
99
+ DEFINE_PROP_STRING("cpu-type", BCM283XState, cpu_type),
144
- ARMCPU *cpu = ARM_CPU(obj);
100
+ DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
145
-
101
+ BCM283X_NCPUS),
146
- set_feature(&cpu->env, ARM_FEATURE_V8);
102
DEFINE_PROP_END_OF_LIST()
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 }
103
};
178
};
104
179
105
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
106
}
107
108
static const TypeInfo bcm2836_type_info = {
109
- .name = TYPE_BCM2836,
110
+ .name = TYPE_BCM283X,
111
.parent = TYPE_DEVICE,
112
- .instance_size = sizeof(BCM2836State),
113
+ .instance_size = sizeof(BCM283XState),
114
.instance_init = bcm2836_init,
115
.class_init = bcm2836_class_init,
116
};
117
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/arm/raspi.c
120
+++ b/hw/arm/raspi.c
121
@@ -XXX,XX +XXX,XX @@
122
static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};
123
124
typedef struct RasPiState {
125
- BCM2836State soc;
126
+ BCM283XState soc;
127
MemoryRegion ram;
128
} RasPiState;
129
130
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
131
BusState *bus;
132
DeviceState *carddev;
133
134
- object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM2836);
135
+ object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM283X);
136
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
137
&error_abort);
138
139
@@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc)
140
mc->no_floppy = 1;
141
mc->no_cdrom = 1;
142
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
143
- mc->max_cpus = BCM2836_NCPUS;
144
- mc->min_cpus = BCM2836_NCPUS;
145
- mc->default_cpus = BCM2836_NCPUS;
146
+ mc->max_cpus = BCM283X_NCPUS;
147
+ mc->min_cpus = BCM283X_NCPUS;
148
+ mc->default_cpus = BCM283X_NCPUS;
149
mc->default_ram_size = 1024 * 1024 * 1024;
150
mc->ignore_memory_transaction_failures = true;
151
};
152
@@ -XXX,XX +XXX,XX @@ static void raspi3_machine_init(MachineClass *mc)
153
mc->no_floppy = 1;
154
mc->no_cdrom = 1;
155
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
156
- mc->max_cpus = BCM2836_NCPUS;
157
- mc->min_cpus = BCM2836_NCPUS;
158
- mc->default_cpus = BCM2836_NCPUS;
159
+ mc->max_cpus = BCM283X_NCPUS;
160
+ mc->min_cpus = BCM283X_NCPUS;
161
+ mc->default_cpus = BCM283X_NCPUS;
162
mc->default_ram_size = 1024 * 1024 * 1024;
163
}
164
DEFINE_MACHINE("raspi3", raspi3_machine_init)
165
--
180
--
166
2.16.2
181
2.16.2
167
182
168
183
diff view generated by jsdifflib
1
The BCM2837 sets the Aff1 field of the MPIDR affinity values for the
1
Allow the virt board to support '-cpu max' in the same way
2
CPUs to 0, whereas the BCM2836 uses 0xf. Set this correctly, as it
2
it already handles '-cpu host'.
3
is required for Linux to boot.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
5
Message-id: 20180308130626.12393-6-peter.maydell@linaro.org
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20180313153458.26822-8-peter.maydell@linaro.org
9
---
8
---
10
hw/arm/bcm2836.c | 11 +++++++----
9
hw/arm/virt.c | 1 +
11
1 file changed, 7 insertions(+), 4 deletions(-)
10
1 file changed, 1 insertion(+)
12
11
13
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
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/bcm2836.c
14
--- a/hw/arm/virt.c
16
+++ b/hw/arm/bcm2836.c
15
+++ b/hw/arm/virt.c
17
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static const char *valid_cpus[] = {
18
17
ARM_CPU_TYPE_NAME("cortex-a53"),
19
struct BCM283XInfo {
18
ARM_CPU_TYPE_NAME("cortex-a57"),
20
const char *name;
19
ARM_CPU_TYPE_NAME("host"),
21
+ int clusterid;
20
+ ARM_CPU_TYPE_NAME("max"),
22
};
21
};
23
22
24
static const BCM283XInfo bcm283x_socs[] = {
23
static bool cpu_type_valid(const char *cpu)
25
{
26
.name = TYPE_BCM2836,
27
+ .clusterid = 0xf,
28
},
29
{
30
.name = TYPE_BCM2837,
31
+ .clusterid = 0x0,
32
},
33
};
34
35
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
36
static void bcm2836_realize(DeviceState *dev, Error **errp)
37
{
38
BCM283XState *s = BCM283X(dev);
39
+ BCM283XClass *bc = BCM283X_GET_CLASS(dev);
40
+ const BCM283XInfo *info = bc->info;
41
Object *obj;
42
Error *err = NULL;
43
int n;
44
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
45
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));
46
47
for (n = 0; n < BCM283X_NCPUS; n++) {
48
- /* Mirror bcm2836, which has clusterid set to 0xf
49
- * TODO: this should be converted to a property of ARM_CPU
50
- */
51
- s->cpus[n].mp_affinity = 0xF00 | n;
52
+ /* TODO: this should be converted to a property of ARM_CPU */
53
+ s->cpus[n].mp_affinity = (info->clusterid << 8) | n;
54
55
/* set periphbase/CBAR value for CPU-local registers */
56
object_property_set_int(OBJECT(&s->cpus[n]),
57
--
24
--
58
2.16.2
25
2.16.2
59
26
60
27
diff view generated by jsdifflib
1
For the rpi1 and 2 we want to boot the Linux kernel via some
1
Add support for passing 'max' to -machine gic-version. By analogy
2
custom setup code that makes sure that the SMC instruction
2
with the -cpu max option, this picks the "best available" GIC version
3
acts as a no-op, because it's used for cache maintenance.
3
whether you're using KVM or TCG, so it behaves like 'host' when
4
The rpi3 boots AArch64 kernels, which don't need SMC for
4
using KVM, and gives you GICv3 when using TCG.
5
cache maintenance and always expect to be booted non-secure.
5
6
Don't fill in the aarch32-specific parts of the binfo struct.
6
Also like '-cpu host', using -machine gic-version=max' means there
7
is no guarantee of migration compatibility between QEMU versions;
8
in future 'max' might mean '4'.
7
9
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
11
Message-id: 20180308130626.12393-7-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20180313153458.26822-2-peter.maydell@linaro.org
12
---
13
---
13
hw/arm/raspi.c | 17 +++++++++++++----
14
hw/arm/virt.c | 29 +++++++++++++++++++----------
14
1 file changed, 13 insertions(+), 4 deletions(-)
15
1 file changed, 19 insertions(+), 10 deletions(-)
15
16
16
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
17
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/raspi.c
19
--- a/hw/arm/virt.c
19
+++ b/hw/arm/raspi.c
20
+++ b/hw/arm/virt.c
20
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
21
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
21
binfo.board_id = raspi_boardid[version];
22
/* We can probe only here because during property set
22
binfo.ram_size = ram_size;
23
* KVM is not available yet
23
binfo.nb_cpus = smp_cpus;
24
*/
24
- binfo.board_setup_addr = BOARDSETUP_ADDR;
25
- if (!vms->gic_version) {
25
- binfo.write_board_setup = write_board_setup;
26
+ if (vms->gic_version <= 0) {
26
- binfo.secure_board_setup = true;
27
+ /* "host" or "max" */
27
- binfo.secure_boot = true;
28
if (!kvm_enabled()) {
28
+
29
- error_report("gic-version=host requires KVM");
29
+ if (version <= 2) {
30
- exit(1);
30
+ /* The rpi1 and 2 require some custom setup code to run in Secure
31
- }
31
+ * mode before booting a kernel (to set up the SMC vectors so
32
-
32
+ * that we get a no-op SMC; this is used by Linux to call the
33
- vms->gic_version = kvm_arm_vgic_probe();
33
+ * firmware for some cache maintenance operations.
34
- if (!vms->gic_version) {
34
+ * The rpi3 doesn't need this.
35
- error_report("Unable to determine GIC version supported by host");
35
+ */
36
- exit(1);
36
+ binfo.board_setup_addr = BOARDSETUP_ADDR;
37
+ if (vms->gic_version == 0) {
37
+ binfo.write_board_setup = write_board_setup;
38
+ error_report("gic-version=host requires KVM");
38
+ binfo.secure_board_setup = true;
39
+ exit(1);
39
+ binfo.secure_boot = true;
40
+ } else {
40
+ }
41
+ /* "max": currently means 3 for TCG */
41
42
+ vms->gic_version = 3;
42
/* Pi2 and Pi3 requires SMP setup */
43
+ }
43
if (version >= 2) {
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
}
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
55
vms->gic_version = 2;
56
} else if (!strcmp(value, "host")) {
57
vms->gic_version = 0; /* Will probe later */
58
+ } else if (!strcmp(value, "max")) {
59
+ vms->gic_version = -1; /* Will probe later */
60
} else {
61
error_setg(errp, "Invalid gic-version value");
62
- error_append_hint(errp, "Valid values are 3, 2, host.\n");
63
+ error_append_hint(errp, "Valid values are 3, 2, host, max.\n");
64
}
65
}
66
44
--
67
--
45
2.16.2
68
2.16.2
46
69
47
70
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
The sabrelite machine model used by qemu-system-arm is based on the
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Freescale/NXP i.MX6Q processor. This SoC has an on-board ethernet
4
Acked-by: Alistair Francis <alistair.francis@xilinx.com>
5
controller which is supported in QEMU using the imx_fec.c module
5
Message-id: 20180309153654.13518-2-f4bug@amsat.org
6
(actually called imx.enet for this model.)
7
8
The include/hw/arm/fsm-imx6.h file defines the interrupt vectors for the
9
imx.enet device like this:
10
11
#define FSL_IMX6_ENET_MAC_1588_IRQ 118
12
#define FSL_IMX6_ENET_MAC_IRQ 119
13
14
According to https://www.nxp.com/docs/en/reference-manual/IMX6DQRM.pdf,
15
page 225, in Table 3-1. ARM Cortex A9 domain interrupt summary,
16
interrupts are as follows.
17
18
150 ENET MAC 0 IRQ
19
151 ENET MAC 0 1588 Timer interrupt
20
21
where
22
23
150 - 32 == 118
24
151 - 32 == 119
25
26
In other words, the vector definitions in the fsl-imx6.h file are reversed.
27
28
Fixing the interrupts alone causes problems with older Linux kernels:
29
The Ethernet interface will fail to probe with Linux v4.9 and earlier.
30
Linux v4.1 and earlier will crash due to a bug in Ethernet driver probe
31
error handling. This is a Linux kernel problem, not a qemu problem:
32
the Linux kernel only worked by accident since it requested both interrupts.
33
34
For backward compatibility, generate the Ethernet interrupt on both interrupt
35
lines. This was shown to work from all Linux kernel releases starting with
36
v3.16.
37
38
Link: https://bugs.launchpad.net/qemu/+bug/1753309
39
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
40
Message-id: 1520723090-22130-1-git-send-email-linux@roeck-us.net
41
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
43
---
8
---
44
include/hw/arm/fsl-imx6.h | 4 ++--
9
hw/sd/sd.c | 11 ++++++++---
45
hw/net/imx_fec.c | 28 +++++++++++++++++++++++++++-
10
1 file changed, 8 insertions(+), 3 deletions(-)
46
2 files changed, 29 insertions(+), 3 deletions(-)
47
11
48
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
12
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
49
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/arm/fsl-imx6.h
14
--- a/hw/sd/sd.c
51
+++ b/include/hw/arm/fsl-imx6.h
15
+++ b/hw/sd/sd.c
52
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX6State {
16
@@ -XXX,XX +XXX,XX @@ static void sd_lock_command(SDState *sd)
53
#define FSL_IMX6_HDMI_MASTER_IRQ 115
17
sd->card_status &= ~CARD_IS_LOCKED;
54
#define FSL_IMX6_HDMI_CEC_IRQ 116
18
}
55
#define FSL_IMX6_MLB150_LOW_IRQ 117
19
56
-#define FSL_IMX6_ENET_MAC_1588_IRQ 118
20
-static sd_rsp_type_t sd_normal_command(SDState *sd,
57
-#define FSL_IMX6_ENET_MAC_IRQ 119
21
- SDRequest req)
58
+#define FSL_IMX6_ENET_MAC_IRQ 118
22
+static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
59
+#define FSL_IMX6_ENET_MAC_1588_IRQ 119
60
#define FSL_IMX6_PCIE1_IRQ 120
61
#define FSL_IMX6_PCIE2_IRQ 121
62
#define FSL_IMX6_PCIE3_IRQ 122
63
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/net/imx_fec.c
66
+++ b/hw/net/imx_fec.c
67
@@ -XXX,XX +XXX,XX @@ static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr)
68
69
static void imx_eth_update(IMXFECState *s)
70
{
23
{
71
- if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_TS_TIMER) {
24
uint32_t rca = 0x0000;
72
+ /*
25
uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
73
+ * Previous versions of qemu had the ENET_INT_MAC and ENET_INT_TS_TIMER
26
74
+ * interrupts swapped. This worked with older versions of Linux (4.14
27
- trace_sdcard_normal_command(req.cmd, req.arg, sd_state_name(sd->state));
75
+ * and older) since Linux associated both interrupt lines with Ethernet
28
+ /* CMD55 precedes an ACMD, so we are not interested in tracing it.
76
+ * MAC interrupts. Specifically,
29
+ * However there is no ACMD55, so we want to trace this particular case.
77
+ * - Linux 4.15 and later have separate interrupt handlers for the MAC and
78
+ * timer interrupts. Those versions of Linux fail with versions of QEMU
79
+ * with swapped interrupt assignments.
80
+ * - In linux 4.14, both interrupt lines were registered with the Ethernet
81
+ * MAC interrupt handler. As a result, all versions of qemu happen to
82
+ * work, though that is accidental.
83
+ * - In Linux 4.9 and older, the timer interrupt was registered directly
84
+ * with the Ethernet MAC interrupt handler. The MAC interrupt was
85
+ * redirected to a GPIO interrupt to work around erratum ERR006687.
86
+ * This was implemented using the SOC's IOMUX block. In qemu, this GPIO
87
+ * interrupt never fired since IOMUX is currently not supported in qemu.
88
+ * Linux instead received MAC interrupts on the timer interrupt.
89
+ * As a result, qemu versions with the swapped interrupt assignment work,
90
+ * albeit accidentally, but qemu versions with the correct interrupt
91
+ * assignment fail.
92
+ *
93
+ * To ensure that all versions of Linux work, generate ENET_INT_MAC
94
+ * interrrupts on both interrupt lines. This should be changed if and when
95
+ * qemu supports IOMUX.
96
+ */
30
+ */
97
+ if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] &
31
+ if (req.cmd != 55 || sd->expecting_acmd) {
98
+ (ENET_INT_MAC | ENET_INT_TS_TIMER)) {
32
+ trace_sdcard_normal_command(req.cmd, req.arg,
99
qemu_set_irq(s->irq[1], 1);
33
+ sd_state_name(sd->state));
100
} else {
34
+ }
101
qemu_set_irq(s->irq[1], 0);
35
36
/* Not interpreting this as an app command */
37
sd->card_status &= ~APP_CMD;
102
--
38
--
103
2.16.2
39
2.16.2
104
40
105
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
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
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(-)
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 @@ struct SDState {
17
qemu_irq readonly_cb;
18
qemu_irq inserted_cb;
19
QEMUTimer *ocr_power_timer;
20
+ const char *proto_name;
21
bool enable;
22
uint8_t dat_lines;
23
bool cmd_line;
24
@@ -XXX,XX +XXX,XX @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
25
* However there is no ACMD55, so we want to trace this particular case.
26
*/
27
if (req.cmd != 55 || sd->expecting_acmd) {
28
- trace_sdcard_normal_command(sd_cmd_name(req.cmd), req.cmd,
29
+ trace_sdcard_normal_command(sd->proto_name,
30
+ sd_cmd_name(req.cmd), req.cmd,
31
req.arg, sd_state_name(sd->state));
32
}
33
34
@@ -XXX,XX +XXX,XX @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
35
static sd_rsp_type_t sd_app_command(SDState *sd,
36
SDRequest req)
37
{
38
- trace_sdcard_app_command(sd_acmd_name(req.cmd),
39
+ trace_sdcard_app_command(sd->proto_name, sd_acmd_name(req.cmd),
40
req.cmd, req.arg, sd_state_name(sd->state));
41
sd->card_status |= APP_CMD;
42
switch (req.cmd) {
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
98
--
99
2.16.2
100
101
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
From the "Physical Layer Simplified Specification Version 3.01":
4
5
A known data block ("Tuning block") can be used to tune sampling
6
point for tuning required hosts. [...]
7
This procedure gives the system optimal timing for each specific
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.
13
14
[based on a patch from Alistair Francis <alistair.francis@xilinx.com>
15
from qemu/xilinx tag xilinx-v2015.2]
16
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
18
Message-id: 20180309153654.13518-5-f4bug@amsat.org
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
21
hw/sd/sd.c | 29 +++++++++++++++++++++++++++++
22
1 file changed, 29 insertions(+)
23
24
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/sd/sd.c
27
+++ b/hw/sd/sd.c
28
@@ -XXX,XX +XXX,XX @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
29
}
30
break;
31
32
+ case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */
33
+ if (sd->state == sd_transfer_state) {
34
+ sd->state = sd_sendingdata_state;
35
+ sd->data_offset = 0;
36
+ return sd_r1;
37
+ }
38
+ break;
39
+
40
case 23: /* CMD23: SET_BLOCK_COUNT */
41
switch (sd->state) {
42
case sd_transfer_state:
43
@@ -XXX,XX +XXX,XX @@ void sd_write_data(SDState *sd, uint8_t value)
44
}
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 ++];
77
78
--
79
2.16.2
80
81
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
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180309153654.13518-8-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/sd/sdhci.c | 4 ++--
9
1 file changed, 2 insertions(+), 2 deletions(-)
10
11
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/sd/sdhci.c
14
+++ b/hw/sd/sdhci.c
15
@@ -XXX,XX +XXX,XX @@ static void sdhci_read_block_from_card(SDHCIState *s)
16
for (index = 0; index < blk_size; index++) {
17
data = sdbus_read_data(&s->sdbus);
18
if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
19
- /* Device is not in tunning */
20
+ /* Device is not in tuning */
21
s->fifo_buffer[index] = data;
22
}
23
}
24
25
if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
26
- /* Device is in tunning */
27
+ /* Device is in tuning */
28
s->hostctl2 &= ~R_SDHC_HOSTCTL2_EXECUTE_TUNING_MASK;
29
s->hostctl2 |= R_SDHC_HOSTCTL2_SAMPLING_CLKSEL_MASK;
30
s->prnsts &= ~(SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ |
31
--
32
2.16.2
33
34
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
After spending months studying all the different SD Specifications
4
from the SD Association, voluntarily add myself as maintainer
5
for the SD code.
6
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20180309153654.13518-9-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
MAINTAINERS | 8 ++++++++
13
1 file changed, 8 insertions(+)
14
15
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
17
--- a/MAINTAINERS
18
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
20
S: Maintained
21
F: hw/ssi/xilinx_*
22
23
+SD (Secure Card)
24
+M: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
+S: Odd Fixes
26
+F: include/hw/sd/sd*
27
+F: hw/sd/core.c
28
+F: hw/sd/sd*
29
+F: tests/sd*
30
+
31
USB
32
M: Gerd Hoffmann <kraxel@redhat.com>
33
S: Maintained
34
--
35
2.16.2
36
37
diff view generated by jsdifflib