1
Arm patch queue -- these are all bug fix patches but we might
1
Hi; here's another Arm pullreq: the big thing in here is
2
as well put them in to rc0...
2
Bernhard's imx8mp-evk board model; there's also various cleanup
3
type patches from me, as well as some bugfixes.
3
4
4
thanks
5
thanks
5
-- PMM
6
-- PMM
6
7
7
The following changes since commit 2c8cfc0b52b5a4d123c26c0b5fdf941be24805be:
8
The following changes since commit b69801dd6b1eb4d107f7c2f643adf0a4e3ec9124:
8
9
9
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2018-03-19 11:44:26 +0000)
10
Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging (2025-02-22 05:06:39 +0800)
10
11
11
are available in the Git repository at:
12
are available in the Git repository at:
12
13
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180319
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250225
14
15
15
for you to fetch changes up to ff72cb6b46b95bb530787add5277c211af3d31c6:
16
for you to fetch changes up to 1aaf3478684ff1cd02d1b36c32a00bfac9a5dbd5:
16
17
17
hw/arm/raspi: Provide spin-loop code for AArch64 CPUs (2018-03-19 18:23:24 +0000)
18
hw/arm/fsl-imx8mp: Add on-chip RAM (2025-02-25 17:24:00 +0000)
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
target-arm queue:
21
target-arm queue:
21
* fsl-imx6: Fix incorrect Ethernet interrupt defines
22
* hw/arm/smmuv3: Fill u.f_cd_fetch.addr for SMMU_EVT_F_CD_FETCH
22
* dump: Update correct kdump phys_base field for AArch64
23
* hw/arm/virt: Support larger highmem MMIO regions
23
* char: i.MX: Add support for "TX complete" interrupt
24
* machine: Centralize -machine dumpdtb option handling and report
24
* bcm2836/raspi: Fix various bugs resulting in panics trying
25
attempt to dump nonexistent DTB as an error
25
to boot a Debian Linux kernel on raspi3
26
* fpu: remove target ifdefs and build it only once
27
* target/arm: Refactor to move TCG-only vfp_helper code into tcg/
28
* target/arm/hvf: Disable SME feature
29
* target/arm/hvf: sign extend the data for a load operation when SSE=1
30
* hw/misc/npcm_clk: fix buffer-overflow
31
* hw/arm: Add i.MX 8M Plus EVK board ("imx8mp-evk")
26
32
27
----------------------------------------------------------------
33
----------------------------------------------------------------
28
Andrey Smirnov (2):
34
Bernhard Beschow (16):
29
char: i.MX: Simplify imx_update()
35
hw/usb/hcd-dwc3: Align global registers size with Linux
30
char: i.MX: Add support for "TX complete" interrupt
36
hw/pci-host/designware: Prevent device attachment on internal PCIe root bus
37
hw/gpio/pca955*: Move Kconfig switches next to implementations
38
hw/arm: Add i.MX 8M Plus EVK board
39
hw/arm/fsl-imx8mp: Implement clock tree
40
hw/arm/fsl-imx8mp: Add SNVS
41
hw/arm/fsl-imx8mp: Add USDHC storage controllers
42
hw/arm/fsl-imx8mp: Add PCIe support
43
hw/arm/fsl-imx8mp: Add GPIO controllers
44
hw/arm/fsl-imx8mp: Add I2C controllers
45
hw/arm/fsl-imx8mp: Add SPI controllers
46
hw/arm/fsl-imx8mp: Add watchdog support
47
hw/arm/fsl-imx8mp: Implement general purpose timers
48
hw/arm/fsl-imx8mp: Add Ethernet controller
49
hw/arm/fsl-imx8mp: Add USB support
50
hw/arm/fsl-imx8mp: Add on-chip RAM
31
51
32
Guenter Roeck (1):
52
Joelle van Dyne (2):
33
fsl-imx6: Swap Ethernet interrupt defines
53
target/arm/hvf: Disable SME feature
54
target/arm/hvf: sign extend the data for a load operation when SSE=1
34
55
35
Peter Maydell (9):
56
Matthew R. Ochs (1):
36
hw/arm/raspi: Don't do board-setup or secure-boot for raspi3
57
hw/arm/virt: Support larger highmem MMIO regions
37
hw/arm/boot: assert that secure_boot and secure_board_setup are false for AArch64
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
58
46
Wei Huang (1):
59
Nicolin Chen (1):
47
dump: Update correct kdump phys_base field for AArch64
60
hw/arm/smmuv3: Fill u.f_cd_fetch.addr for SMMU_EVT_F_CD_FETCH
48
61
49
include/hw/arm/bcm2836.h | 31 +++++++++++++---
62
Peter Maydell (22):
50
include/hw/arm/fsl-imx6.h | 4 +-
63
monitor/hmp-cmds.c: Clean up hmp_dumpdtb printf
51
include/hw/char/imx_serial.h | 3 ++
64
hw/openrisc: Support monitor dumpdtb command
52
dump.c | 14 +++++--
65
hw/mips/boston: Check for error return from boston_fdt_filter()
53
hw/arm/bcm2836.c | 87 +++++++++++++++++++++++++++++++-------------
66
hw/mips/boston: Support dumpdtb monitor commands
54
hw/arm/boot.c | 12 ++++++
67
hw: Centralize handling of -machine dumpdtb option
55
hw/arm/raspi.c | 77 +++++++++++++++++++++++++++++++--------
68
hw/core/machine.c: Make -machine dumpdtb=file.dtb with no DTB an error
56
hw/char/imx_serial.c | 44 ++++++++++++++++------
69
fpu: Make targets specify floatx80 default Inf at runtime
57
hw/net/imx_fec.c | 28 +++++++++++++-
70
target/m68k: Avoid using floatx80_infinity global const
58
9 files changed, 237 insertions(+), 63 deletions(-)
71
target/i386: Avoid using floatx80_infinity global const
72
fpu: Pass float_status to floatx80_is_infinity()
73
fpu: Make targets specify whether floatx80 Inf can have Int bit clear
74
fpu: Pass float_status to floatx80_invalid_encoding()
75
fpu: Make floatx80 invalid encoding settable at runtime
76
fpu: Move m68k_denormal fmt flag into floatx80_behaviour
77
fpu: Always decide no_signaling_nans() at runtime
78
fpu: Always decide snan_bit_is_one() at runtime
79
fpu: Don't compile-time disable hardfloat for PPC targets
80
fpu: Build only once
81
target/arm: Move TCG-only VFP code into tcg/ subdir
82
target/arm: Move FPSCR get/set helpers to tcg/vfp_helper.c
83
target/arm: Move softfloat specific FPCR/FPSR handling to tcg/
84
target/arm: Rename vfp_helper.c to vfp_fpscr.c
59
85
86
Pierrick Bouvier (1):
87
hw/misc/npcm_clk: fix buffer-overflow
88
89
MAINTAINERS | 13 +
90
docs/system/arm/imx8mp-evk.rst | 70 ++++
91
docs/system/arm/virt.rst | 4 +
92
docs/system/target-arm.rst | 1 +
93
include/fpu/softfloat-helpers.h | 12 +
94
include/fpu/softfloat-types.h | 51 +++
95
include/fpu/softfloat.h | 91 ++---
96
include/hw/arm/fsl-imx8mp.h | 284 ++++++++++++++
97
include/hw/loader-fit.h | 21 +-
98
include/hw/misc/imx8mp_analog.h | 81 ++++
99
include/hw/misc/imx8mp_ccm.h | 30 ++
100
include/hw/openrisc/boot.h | 3 +-
101
include/hw/pci-host/designware.h | 7 +
102
include/hw/pci-host/fsl_imx8m_phy.h | 28 ++
103
include/hw/timer/imx_gpt.h | 1 +
104
include/hw/usb/hcd-dwc3.h | 2 +-
105
include/system/device_tree.h | 2 -
106
target/arm/internals.h | 9 +
107
fpu/softfloat.c | 23 +-
108
hw/arm/boot.c | 2 -
109
hw/arm/fsl-imx8mp.c | 714 ++++++++++++++++++++++++++++++++++++
110
hw/arm/imx8mp-evk.c | 74 ++++
111
hw/arm/smmuv3.c | 2 +-
112
hw/arm/virt.c | 52 ++-
113
hw/core/loader-fit.c | 38 +-
114
hw/core/machine.c | 23 ++
115
hw/loongarch/virt-fdt-build.c | 1 -
116
hw/mips/boston.c | 16 +-
117
hw/misc/imx8mp_analog.c | 160 ++++++++
118
hw/misc/imx8mp_ccm.c | 175 +++++++++
119
hw/misc/npcm_clk.c | 5 +-
120
hw/openrisc/boot.c | 8 +-
121
hw/openrisc/openrisc_sim.c | 2 +-
122
hw/openrisc/virt.c | 2 +-
123
hw/pci-host/designware.c | 18 +-
124
hw/pci-host/fsl_imx8m_phy.c | 98 +++++
125
hw/ppc/e500.c | 1 -
126
hw/ppc/pegasos2.c | 1 -
127
hw/ppc/pnv.c | 1 -
128
hw/ppc/spapr.c | 1 -
129
hw/riscv/boot.c | 2 -
130
hw/timer/imx_gpt.c | 25 ++
131
hw/usb/hcd-dwc3.c | 5 +
132
monitor/hmp-cmds.c | 2 +-
133
system/device_tree-stub.c | 5 +-
134
system/device_tree.c | 22 +-
135
target/arm/hvf/hvf.c | 16 +
136
target/arm/tcg-stubs.c | 22 ++
137
target/arm/{ => tcg}/vfp_helper.c | 189 +---------
138
target/arm/vfp_fpscr.c | 155 ++++++++
139
target/hppa/fpu_helper.c | 1 +
140
target/i386/tcg/fpu_helper.c | 51 +--
141
target/m68k/cpu.c | 35 ++
142
target/m68k/fpu_helper.c | 2 +-
143
target/m68k/softfloat.c | 47 +--
144
target/sh4/cpu.c | 1 +
145
fpu/softfloat-parts.c.inc | 27 +-
146
fpu/softfloat-specialize.c.inc | 29 +-
147
fpu/meson.build | 2 +-
148
hw/arm/Kconfig | 24 ++
149
hw/arm/meson.build | 2 +
150
hw/gpio/Kconfig | 8 +
151
hw/misc/Kconfig | 14 +-
152
hw/misc/meson.build | 2 +
153
hw/pci-host/Kconfig | 3 +
154
hw/pci-host/meson.build | 1 +
155
target/arm/meson.build | 2 +-
156
target/arm/tcg/meson.build | 1 +
157
68 files changed, 2439 insertions(+), 383 deletions(-)
158
create mode 100644 docs/system/arm/imx8mp-evk.rst
159
create mode 100644 include/hw/arm/fsl-imx8mp.h
160
create mode 100644 include/hw/misc/imx8mp_analog.h
161
create mode 100644 include/hw/misc/imx8mp_ccm.h
162
create mode 100644 include/hw/pci-host/fsl_imx8m_phy.h
163
create mode 100644 hw/arm/fsl-imx8mp.c
164
create mode 100644 hw/arm/imx8mp-evk.c
165
create mode 100644 hw/misc/imx8mp_analog.c
166
create mode 100644 hw/misc/imx8mp_ccm.c
167
create mode 100644 hw/pci-host/fsl_imx8m_phy.c
168
rename target/arm/{ => tcg}/vfp_helper.c (90%)
169
create mode 100644 target/arm/vfp_fpscr.c
diff view generated by jsdifflib
New patch
1
From: Nicolin Chen <nicolinc@nvidia.com>
1
2
3
When we fill in the SMMUEventInfo for SMMU_EVT_F_CD_FETCH we write
4
the address into the f_ste_fetch member of the union, but then when
5
we come to read it back in smmuv3_record_event() we will (correctly)
6
be using the f_cd_fetch member.
7
8
This is more like a cosmetics fix since the f_cd_fetch and f_ste_fetch are
9
basically the same field since they are in the exact same union with exact
10
same type, but it's conceptually wrong. Use the correct union member.
11
12
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
13
Message-id: 20250220213832.80289-1-nicolinc@nvidia.com
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/arm/smmuv3.c | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/smmuv3.c
23
+++ b/hw/arm/smmuv3.c
24
@@ -XXX,XX +XXX,XX @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTransCfg *cfg,
25
qemu_log_mask(LOG_GUEST_ERROR,
26
"Cannot fetch pte at address=0x%"PRIx64"\n", addr);
27
event->type = SMMU_EVT_F_CD_FETCH;
28
- event->u.f_ste_fetch.addr = addr;
29
+ event->u.f_cd_fetch.addr = addr;
30
return -EINVAL;
31
}
32
for (i = 0; i < ARRAY_SIZE(buf->word); i++) {
33
--
34
2.43.0
diff view generated by jsdifflib
New patch
1
From: "Matthew R. Ochs" <mochs@nvidia.com>
1
2
3
The MMIO region size required to support virtualized environments with
4
large PCI BAR regions can exceed the hardcoded limit configured in QEMU.
5
For example, a VM with multiple NVIDIA Grace-Hopper GPUs passed through
6
requires more MMIO memory than the amount provided by VIRT_HIGH_PCIE_MMIO
7
(currently 512GB). Instead of updating VIRT_HIGH_PCIE_MMIO, introduce a
8
new parameter, highmem-mmio-size, that specifies the MMIO size required
9
to support the VM configuration.
10
11
Example usage with 1TB MMIO region size:
12
    -machine virt,gic-version=3,highmem-mmio-size=1T
13
14
Signed-off-by: Matthew R. Ochs <mochs@nvidia.com>
15
Reviewed-by: Gavin Shan <gshan@redhat.com>
16
Reviewed-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
17
Reviewed-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
19
Message-id: 20250221145419.1281890-1-mochs@nvidia.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
docs/system/arm/virt.rst | 4 ++++
24
hw/arm/virt.c | 52 +++++++++++++++++++++++++++++++++++++++-
25
2 files changed, 55 insertions(+), 1 deletion(-)
26
27
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
28
index XXXXXXX..XXXXXXX 100644
29
--- a/docs/system/arm/virt.rst
30
+++ b/docs/system/arm/virt.rst
31
@@ -XXX,XX +XXX,XX @@ highmem-mmio
32
Set ``on``/``off`` to enable/disable the high memory region for PCI MMIO.
33
The default is ``on``.
34
35
+highmem-mmio-size
36
+ Set the high memory region size for PCI MMIO. Must be a power of 2 and
37
+ greater than or equal to the default size (512G).
38
+
39
gic-version
40
Specify the version of the Generic Interrupt Controller (GIC) to provide.
41
Valid values are:
42
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/virt.c
45
+++ b/hw/arm/virt.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "hw/loader.h"
48
#include "qapi/error.h"
49
#include "qemu/bitops.h"
50
+#include "qemu/cutils.h"
51
#include "qemu/error-report.h"
52
#include "qemu/module.h"
53
#include "hw/pci-host/gpex.h"
54
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry base_memmap[] = {
55
[VIRT_MEM] = { GiB, LEGACY_RAMLIMIT_BYTES },
56
};
57
58
+/* Update the docs for highmem-mmio-size when changing this default */
59
+#define DEFAULT_HIGH_PCIE_MMIO_SIZE_GB 512
60
+#define DEFAULT_HIGH_PCIE_MMIO_SIZE (DEFAULT_HIGH_PCIE_MMIO_SIZE_GB * GiB)
61
+
62
/*
63
* Highmem IO Regions: This memory map is floating, located after the RAM.
64
* Each MemMapEntry base (GPA) will be dynamically computed, depending on the
65
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry base_memmap[] = {
66
* PA space for one specific region is always reserved, even if the region
67
* has been disabled or doesn't fit into the PA space. However, the PA space
68
* for the region won't be reserved in these circumstances with compact layout.
69
+ *
70
+ * Note that the highmem-mmio-size property will update the high PCIE MMIO size
71
+ * field in this array.
72
*/
73
static MemMapEntry extended_memmap[] = {
74
/* Additional 64 MB redist region (can contain up to 512 redistributors) */
75
[VIRT_HIGH_GIC_REDIST2] = { 0x0, 64 * MiB },
76
[VIRT_HIGH_PCIE_ECAM] = { 0x0, 256 * MiB },
77
/* Second PCIe window */
78
- [VIRT_HIGH_PCIE_MMIO] = { 0x0, 512 * GiB },
79
+ [VIRT_HIGH_PCIE_MMIO] = { 0x0, DEFAULT_HIGH_PCIE_MMIO_SIZE },
80
};
81
82
static const int a15irqmap[] = {
83
@@ -XXX,XX +XXX,XX @@ static void virt_set_highmem_mmio(Object *obj, bool value, Error **errp)
84
vms->highmem_mmio = value;
85
}
86
87
+static void virt_get_highmem_mmio_size(Object *obj, Visitor *v,
88
+ const char *name, void *opaque,
89
+ Error **errp)
90
+{
91
+ uint64_t size = extended_memmap[VIRT_HIGH_PCIE_MMIO].size;
92
+
93
+ visit_type_size(v, name, &size, errp);
94
+}
95
+
96
+static void virt_set_highmem_mmio_size(Object *obj, Visitor *v,
97
+ const char *name, void *opaque,
98
+ Error **errp)
99
+{
100
+ uint64_t size;
101
+
102
+ if (!visit_type_size(v, name, &size, errp)) {
103
+ return;
104
+ }
105
+
106
+ if (!is_power_of_2(size)) {
107
+ error_setg(errp, "highmem-mmio-size is not a power of 2");
108
+ return;
109
+ }
110
+
111
+ if (size < DEFAULT_HIGH_PCIE_MMIO_SIZE) {
112
+ char *sz = size_to_str(DEFAULT_HIGH_PCIE_MMIO_SIZE);
113
+ error_setg(errp, "highmem-mmio-size cannot be set to a lower value "
114
+ "than the default (%s)", sz);
115
+ g_free(sz);
116
+ return;
117
+ }
118
+
119
+ extended_memmap[VIRT_HIGH_PCIE_MMIO].size = size;
120
+}
121
122
static bool virt_get_its(Object *obj, Error **errp)
123
{
124
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
125
"Set on/off to enable/disable high "
126
"memory region for PCI MMIO");
127
128
+ object_class_property_add(oc, "highmem-mmio-size", "size",
129
+ virt_get_highmem_mmio_size,
130
+ virt_set_highmem_mmio_size,
131
+ NULL, NULL);
132
+ object_class_property_set_description(oc, "highmem-mmio-size",
133
+ "Set the high memory region size "
134
+ "for PCI MMIO");
135
+
136
object_class_property_add_str(oc, "gic-version", virt_get_gic_version,
137
virt_set_gic_version);
138
object_class_property_set_description(oc, "gic-version",
139
--
140
2.43.0
diff view generated by jsdifflib
1
The TypeInfo and state struct for bcm2386 disagree about what the
1
In hmp_dumpdtb(), we print a message when the command succeeds. This
2
parent class is -- the TypeInfo says it's TYPE_SYS_BUS_DEVICE,
2
message is missing the trailing \n, so the HMP command prompt is
3
but the BCM2386State struct only defines the parent_obj field
3
printed immediately after it. We also weren't capitalizing 'DTB', or
4
as DeviceState. This would have caused problems if anything
4
quoting the filename in the message. Fix these nits.
5
actually tried to treat the object as a TYPE_SYS_BUS_DEVICE.
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
5
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Message-id: 20180313153458.26822-5-peter.maydell@linaro.org
9
Message-id: 20250206151214.2947842-2-peter.maydell@linaro.org
14
---
10
---
15
hw/arm/bcm2836.c | 2 +-
11
monitor/hmp-cmds.c | 2 +-
16
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
17
13
18
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
14
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/bcm2836.c
16
--- a/monitor/hmp-cmds.c
21
+++ b/hw/arm/bcm2836.c
17
+++ b/monitor/hmp-cmds.c
22
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
18
@@ -XXX,XX +XXX,XX @@ void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
23
19
return;
24
static const TypeInfo bcm2836_type_info = {
20
}
25
.name = TYPE_BCM2836,
21
26
- .parent = TYPE_SYS_BUS_DEVICE,
22
- monitor_printf(mon, "dtb dumped to %s", filename);
27
+ .parent = TYPE_DEVICE,
23
+ monitor_printf(mon, "DTB dumped to '%s'\n", filename);
28
.instance_size = sizeof(BCM2836State),
24
}
29
.instance_init = bcm2836_init,
25
#endif
30
.class_init = bcm2836_class_init,
31
--
26
--
32
2.16.2
27
2.43.0
33
28
34
29
diff view generated by jsdifflib
New patch
1
The openrisc machines don't set MachineState::fdt to point to their
2
DTB blob. This means that although the command line '-machine
3
dumpdtb=file.dtb' option works, the equivalent QMP and HMP monitor
4
commands do not, but instead produce the error "This machine doesn't
5
have a FDT".
1
6
7
Set MachineState::fdt in openrisc_load_fdt(), when we write it to
8
guest memory.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Message-id: 20250206151214.2947842-3-peter.maydell@linaro.org
14
---
15
include/hw/openrisc/boot.h | 3 ++-
16
hw/openrisc/boot.c | 7 +++++--
17
hw/openrisc/openrisc_sim.c | 2 +-
18
hw/openrisc/virt.c | 2 +-
19
4 files changed, 9 insertions(+), 5 deletions(-)
20
21
diff --git a/include/hw/openrisc/boot.h b/include/hw/openrisc/boot.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/openrisc/boot.h
24
+++ b/include/hw/openrisc/boot.h
25
@@ -XXX,XX +XXX,XX @@
26
#define OPENRISC_BOOT_H
27
28
#include "exec/cpu-defs.h"
29
+#include "hw/boards.h"
30
31
hwaddr openrisc_load_kernel(ram_addr_t ram_size,
32
const char *kernel_filename,
33
@@ -XXX,XX +XXX,XX @@ hwaddr openrisc_load_kernel(ram_addr_t ram_size,
34
hwaddr openrisc_load_initrd(void *fdt, const char *filename,
35
hwaddr load_start, uint64_t mem_size);
36
37
-uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
38
+uint32_t openrisc_load_fdt(MachineState *ms, void *fdt, hwaddr load_start,
39
uint64_t mem_size);
40
41
#endif /* OPENRISC_BOOT_H */
42
diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/openrisc/boot.c
45
+++ b/hw/openrisc/boot.c
46
@@ -XXX,XX +XXX,XX @@ hwaddr openrisc_load_initrd(void *fdt, const char *filename,
47
return start + size;
48
}
49
50
-uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
51
- uint64_t mem_size)
52
+uint32_t openrisc_load_fdt(MachineState *ms, void *fdt,
53
+ hwaddr load_start, uint64_t mem_size)
54
{
55
uint32_t fdt_addr;
56
int ret;
57
@@ -XXX,XX +XXX,XX @@ uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
58
/* copy in the device tree */
59
qemu_fdt_dumpdtb(fdt, fdtsize);
60
61
+ /* Save FDT for dumpdtb monitor command */
62
+ ms->fdt = fdt;
63
+
64
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
65
&address_space_memory);
66
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
67
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/openrisc/openrisc_sim.c
70
+++ b/hw/openrisc/openrisc_sim.c
71
@@ -XXX,XX +XXX,XX @@ static void openrisc_sim_init(MachineState *machine)
72
machine->initrd_filename,
73
load_addr, machine->ram_size);
74
}
75
- boot_info.fdt_addr = openrisc_load_fdt(state->fdt, load_addr,
76
+ boot_info.fdt_addr = openrisc_load_fdt(machine, state->fdt, load_addr,
77
machine->ram_size);
78
}
79
}
80
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/openrisc/virt.c
83
+++ b/hw/openrisc/virt.c
84
@@ -XXX,XX +XXX,XX @@ static void openrisc_virt_init(MachineState *machine)
85
machine->initrd_filename,
86
load_addr, machine->ram_size);
87
}
88
- boot_info.fdt_addr = openrisc_load_fdt(state->fdt, load_addr,
89
+ boot_info.fdt_addr = openrisc_load_fdt(machine, state->fdt, load_addr,
90
machine->ram_size);
91
}
92
}
93
--
94
2.43.0
95
96
diff view generated by jsdifflib
New patch
1
The function boston_fdt_filter() can return NULL on errors (in which
2
case it will print an error message). When we call this from the
3
non-FIT-image codepath, we aren't checking the return value, so we
4
will plough on with a NULL pointer, and segfault in fdt_totalsize().
5
Check for errors here.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20250206151214.2947842-4-peter.maydell@linaro.org
10
---
11
hw/mips/boston.c | 4 ++++
12
1 file changed, 4 insertions(+)
13
14
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/mips/boston.c
17
+++ b/hw/mips/boston.c
18
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
19
20
dtb_load_data = boston_fdt_filter(s, dtb_file_data,
21
NULL, &dtb_vaddr);
22
+ if (!dtb_load_data) {
23
+ /* boston_fdt_filter() already printed the error for us */
24
+ exit(1);
25
+ }
26
27
/* Calculate real fdt size after filter */
28
dt_size = fdt_totalsize(dtb_load_data);
29
--
30
2.43.0
31
32
diff view generated by jsdifflib
New patch
1
1
The boston machine doesn't set MachineState::fdt to the DTB blob that
2
it has loaded or created, which means that the QMP/HMP dumpdtb
3
monitor commands don't work.
4
5
Setting MachineState::fdt is easy in the non-FIT codepath: we can
6
simply do so immediately before loading the DTB into guest memory.
7
The FIT codepath is a bit more awkward as currently the FIT loader
8
throws away the memory that the FDT was in after it loads it into
9
guest memory. So we add a void *pfdt argument to load_fit() for it
10
to store the FDT pointer into.
11
12
There is some readjustment required of the pointer handling in
13
loader-fit.c, so that it applies 'const' only where it should (e.g.
14
the data pointer we get back from fdt_getprop() is const, because
15
it's into the middle of the input FDT data, but the pointer that
16
fit_load_image_alloc() should not be const, because it's freshly
17
allocated memory that the caller can change if it likes).
18
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
21
Message-id: 20250206151214.2947842-5-peter.maydell@linaro.org
22
---
23
include/hw/loader-fit.h | 21 ++++++++++++++++++---
24
hw/core/loader-fit.c | 38 +++++++++++++++++++++-----------------
25
hw/mips/boston.c | 11 +++++++----
26
3 files changed, 46 insertions(+), 24 deletions(-)
27
28
diff --git a/include/hw/loader-fit.h b/include/hw/loader-fit.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/loader-fit.h
31
+++ b/include/hw/loader-fit.h
32
@@ -XXX,XX +XXX,XX @@ struct fit_loader_match {
33
struct fit_loader {
34
const struct fit_loader_match *matches;
35
hwaddr (*addr_to_phys)(void *opaque, uint64_t addr);
36
- const void *(*fdt_filter)(void *opaque, const void *fdt,
37
- const void *match_data, hwaddr *load_addr);
38
+ void *(*fdt_filter)(void *opaque, const void *fdt,
39
+ const void *match_data, hwaddr *load_addr);
40
const void *(*kernel_filter)(void *opaque, const void *kernel,
41
hwaddr *load_addr, hwaddr *entry_addr);
42
};
43
44
-int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque);
45
+/**
46
+ * load_fit: load a FIT format image
47
+ * @ldr: structure defining board specific properties and hooks
48
+ * @filename: image to load
49
+ * @pfdt: pointer to update with address of FDT blob
50
+ * @opaque: opaque value passed back to the hook functions in @ldr
51
+ * Returns: 0 on success, or a negative errno on failure
52
+ *
53
+ * @pfdt is used to tell the caller about the FDT blob. On return, it
54
+ * has been set to point to the FDT blob, and it is now the caller's
55
+ * responsibility to free that memory with g_free(). Usually the caller
56
+ * will want to pass in &machine->fdt here, to record the FDT blob for
57
+ * the dumpdtb option and QMP/HMP commands.
58
+ */
59
+int load_fit(const struct fit_loader *ldr, const char *filename, void **pfdt,
60
+ void *opaque);
61
62
#endif /* HW_LOADER_FIT_H */
63
diff --git a/hw/core/loader-fit.c b/hw/core/loader-fit.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/core/loader-fit.c
66
+++ b/hw/core/loader-fit.c
67
@@ -XXX,XX +XXX,XX @@
68
69
#define FIT_LOADER_MAX_PATH (128)
70
71
-static const void *fit_load_image_alloc(const void *itb, const char *name,
72
- int *poff, size_t *psz, Error **errp)
73
+static void *fit_load_image_alloc(const void *itb, const char *name,
74
+ int *poff, size_t *psz, Error **errp)
75
{
76
const void *data;
77
const char *comp;
78
@@ -XXX,XX +XXX,XX @@ static const void *fit_load_image_alloc(const void *itb, const char *name,
79
return NULL;
80
}
81
82
- data = g_realloc(uncomp_data, uncomp_len);
83
+ uncomp_data = g_realloc(uncomp_data, uncomp_len);
84
if (psz) {
85
*psz = uncomp_len;
86
}
87
- return data;
88
+ return uncomp_data;
89
}
90
91
error_setg(errp, "unknown compression '%s'", comp);
92
@@ -XXX,XX +XXX,XX @@ out:
93
94
static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
95
int cfg, void *opaque, const void *match_data,
96
- hwaddr kernel_end, Error **errp)
97
+ hwaddr kernel_end, void **pfdt, Error **errp)
98
{
99
ERRP_GUARD();
100
Error *err = NULL;
101
const char *name;
102
- const void *data;
103
- const void *load_data;
104
+ void *data;
105
hwaddr load_addr;
106
int img_off;
107
size_t sz;
108
@@ -XXX,XX +XXX,XX @@ static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
109
return 0;
110
}
111
112
- load_data = data = fit_load_image_alloc(itb, name, &img_off, &sz, errp);
113
+ data = fit_load_image_alloc(itb, name, &img_off, &sz, errp);
114
if (!data) {
115
error_prepend(errp, "unable to load FDT image from FIT: ");
116
return -EINVAL;
117
@@ -XXX,XX +XXX,XX @@ static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
118
}
119
120
if (ldr->fdt_filter) {
121
- load_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
122
+ void *filtered_data;
123
+
124
+ filtered_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
125
+ if (filtered_data != data) {
126
+ g_free(data);
127
+ data = filtered_data;
128
+ }
129
}
130
131
load_addr = ldr->addr_to_phys(opaque, load_addr);
132
- sz = fdt_totalsize(load_data);
133
- rom_add_blob_fixed(name, load_data, sz, load_addr);
134
+ sz = fdt_totalsize(data);
135
+ rom_add_blob_fixed(name, data, sz, load_addr);
136
137
- ret = 0;
138
+ *pfdt = data;
139
+ return 0;
140
out:
141
g_free((void *) data);
142
- if (data != load_data) {
143
- g_free((void *) load_data);
144
- }
145
return ret;
146
}
147
148
@@ -XXX,XX +XXX,XX @@ out:
149
return ret;
150
}
151
152
-int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
153
+int load_fit(const struct fit_loader *ldr, const char *filename,
154
+ void **pfdt, void *opaque)
155
{
156
Error *err = NULL;
157
const struct fit_loader_match *match;
158
@@ -XXX,XX +XXX,XX @@ int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
159
goto out;
160
}
161
162
- ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end,
163
+ ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end, pfdt,
164
&err);
165
if (ret) {
166
error_report_err(err);
167
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
168
index XXXXXXX..XXXXXXX 100644
169
--- a/hw/mips/boston.c
170
+++ b/hw/mips/boston.c
171
@@ -XXX,XX +XXX,XX @@ static void gen_firmware(void *p, hwaddr kernel_entry, hwaddr fdt_addr)
172
kernel_entry);
173
}
174
175
-static const void *boston_fdt_filter(void *opaque, const void *fdt_orig,
176
- const void *match_data, hwaddr *load_addr)
177
+static void *boston_fdt_filter(void *opaque, const void *fdt_orig,
178
+ const void *match_data, hwaddr *load_addr)
179
{
180
BostonState *s = BOSTON(opaque);
181
MachineState *machine = s->mach;
182
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
183
if (kernel_size > 0) {
184
int dt_size;
185
g_autofree const void *dtb_file_data = NULL;
186
- g_autofree const void *dtb_load_data = NULL;
187
+ void *dtb_load_data = NULL;
188
hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB);
189
hwaddr dtb_vaddr = cpu_mips_phys_to_kseg0(NULL, dtb_paddr);
190
191
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
192
exit(1);
193
}
194
195
+ machine->fdt = dtb_load_data;
196
+
197
/* Calculate real fdt size after filter */
198
dt_size = fdt_totalsize(dtb_load_data);
199
rom_add_blob_fixed("dtb", dtb_load_data, dt_size, dtb_paddr);
200
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
201
rom_ptr(dtb_paddr, dt_size));
202
} else {
203
/* Try to load file as FIT */
204
- fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
205
+ fit_err = load_fit(&boston_fit_loader, machine->kernel_filename,
206
+ &machine->fdt, s);
207
if (fit_err) {
208
error_report("unable to load kernel image");
209
exit(1);
210
--
211
2.43.0
212
213
diff view generated by jsdifflib
1
If we're directly booting a Linux kernel and the CPU supports both
1
Currently we handle the 'dumpdtb' machine sub-option ad-hoc in every
2
EL3 and EL2, we start the kernel in EL2, as it expects. We must also
2
board model that has an FDT. It's up to the board code to make sure
3
set the SCR_EL3.HCE bit in this situation, so that the HVC
3
it calls qemu_fdt_dumpdtb() in the right place.
4
instruction is enabled rather than UNDEFing. Otherwise at least some
4
5
kernels will panic when trying to initialize KVM in the guest.
5
This means we're inconsistent and often just ignore the user's
6
command line argument:
7
* if the board doesn't have an FDT at all
8
* if the board supports FDT, but there happens not to be one
9
present (usually because of a missing -fdt option)
10
11
This isn't very helpful because it gives the user no clue why their
12
option was ignored.
13
14
However, in order to support the QMP/HMP dumpdtb commands we require
15
now that every FDT machine stores a pointer to the FDT in
16
MachineState::fdt. This means we can handle -machine dumpdtb
17
centrally by calling the qmp_dumpdtb() function, unifying its
18
handling with the QMP/HMP commands. All the board code calls to
19
qemu_fdt_dumpdtb() can then be removed.
20
21
For this commit we retain the existing behaviour that if there
22
is no FDT we silently ignore the -machine dumpdtb option.
6
23
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20180313153458.26822-4-peter.maydell@linaro.org
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
26
---
10
hw/arm/boot.c | 5 +++++
27
include/system/device_tree.h | 2 --
11
1 file changed, 5 insertions(+)
28
hw/arm/boot.c | 2 --
12
29
hw/core/machine.c | 25 +++++++++++++++++++++++++
30
hw/loongarch/virt-fdt-build.c | 1 -
31
hw/mips/boston.c | 1 -
32
hw/openrisc/boot.c | 1 -
33
hw/ppc/e500.c | 1 -
34
hw/ppc/pegasos2.c | 1 -
35
hw/ppc/pnv.c | 1 -
36
hw/ppc/spapr.c | 1 -
37
hw/riscv/boot.c | 2 --
38
system/device_tree.c | 15 ---------------
39
12 files changed, 25 insertions(+), 28 deletions(-)
40
41
diff --git a/include/system/device_tree.h b/include/system/device_tree.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/system/device_tree.h
44
+++ b/include/system/device_tree.h
45
@@ -XXX,XX +XXX,XX @@ int qemu_fdt_add_path(void *fdt, const char *path);
46
sizeof(qdt_tmp)); \
47
} while (0)
48
49
-void qemu_fdt_dumpdtb(void *fdt, int size);
50
-
51
/**
52
* qemu_fdt_setprop_sized_cells_from_array:
53
* @fdt: device tree blob
13
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
54
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
14
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/boot.c
56
--- a/hw/arm/boot.c
16
+++ b/hw/arm/boot.c
57
+++ b/hw/arm/boot.c
17
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
58
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
18
assert(!info->secure_board_setup);
59
binfo->modify_dtb(binfo, fdt);
19
}
60
}
20
61
21
+ if (arm_feature(env, ARM_FEATURE_EL2)) {
62
- qemu_fdt_dumpdtb(fdt, size);
22
+ /* If we have EL2 then Linux expects the HVC insn to work */
63
-
23
+ env->cp15.scr_el3 |= SCR_HCE;
64
/* Put the DTB into the memory map as a ROM image: this will ensure
24
+ }
65
* the DTB is copied again upon reset, even if addr points into RAM.
66
*/
67
diff --git a/hw/core/machine.c b/hw/core/machine.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/core/machine.c
70
+++ b/hw/core/machine.c
71
@@ -XXX,XX +XXX,XX @@
72
#include "qemu/error-report.h"
73
#include "qapi/error.h"
74
#include "qapi/qapi-visit-machine.h"
75
+#include "qapi/qapi-commands-machine.h"
76
#include "qemu/madvise.h"
77
#include "qom/object_interfaces.h"
78
#include "system/cpus.h"
79
@@ -XXX,XX +XXX,XX @@ void qemu_remove_machine_init_done_notifier(Notifier *notify)
80
notifier_remove(notify);
81
}
82
83
+static void handle_machine_dumpdtb(MachineState *ms)
84
+{
85
+ if (!ms->dumpdtb) {
86
+ return;
87
+ }
88
+ if (!ms->fdt) {
89
+ /* Silently ignore dumpdtb option if there is nothing to dump */
90
+ return;
91
+ }
92
+#ifdef CONFIG_FDT
93
+ qmp_dumpdtb(ms->dumpdtb, &error_fatal);
94
+ exit(0);
95
+#else
96
+ error_report("This machine doesn't have an FDT");
97
+ exit(1);
98
+#endif
99
+}
25
+
100
+
26
/* Set to non-secure if not a secure boot */
101
void qdev_machine_creation_done(void)
27
if (!info->secure_boot &&
102
{
28
(cs != first_cpu || !info->secure_board_setup)) {
103
cpu_synchronize_all_post_init();
104
@@ -XXX,XX +XXX,XX @@ void qdev_machine_creation_done(void)
105
phase_advance(PHASE_MACHINE_READY);
106
qdev_assert_realized_properly();
107
108
+ /*
109
+ * If the user used -machine dumpdtb=file.dtb to request that we
110
+ * dump the DTB to a file, do it now, and exit.
111
+ */
112
+ handle_machine_dumpdtb(current_machine);
113
+
114
/* TODO: once all bus devices are qdevified, this should be done
115
* when bus is created by qdev.c */
116
/*
117
diff --git a/hw/loongarch/virt-fdt-build.c b/hw/loongarch/virt-fdt-build.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/loongarch/virt-fdt-build.c
120
+++ b/hw/loongarch/virt-fdt-build.c
121
@@ -XXX,XX +XXX,XX @@ void virt_fdt_setup(LoongArchVirtMachineState *lvms)
122
* Put the FDT into the memory map as a ROM image: this will ensure
123
* the FDT is copied again upon reset, even if addr points into RAM.
124
*/
125
- qemu_fdt_dumpdtb(machine->fdt, lvms->fdt_size);
126
rom_add_blob_fixed_as("fdt", machine->fdt, lvms->fdt_size, FDT_BASE,
127
&address_space_memory);
128
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
129
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/mips/boston.c
132
+++ b/hw/mips/boston.c
133
@@ -XXX,XX +XXX,XX @@ static void *boston_fdt_filter(void *opaque, const void *fdt_orig,
134
1, ram_high_sz);
135
136
fdt = g_realloc(fdt, fdt_totalsize(fdt));
137
- qemu_fdt_dumpdtb(fdt, fdt_sz);
138
139
s->fdt_base = *load_addr;
140
141
diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hw/openrisc/boot.c
144
+++ b/hw/openrisc/boot.c
145
@@ -XXX,XX +XXX,XX @@ uint32_t openrisc_load_fdt(MachineState *ms, void *fdt,
146
/* Should only fail if we've built a corrupted tree */
147
g_assert(ret == 0);
148
/* copy in the device tree */
149
- qemu_fdt_dumpdtb(fdt, fdtsize);
150
151
/* Save FDT for dumpdtb monitor command */
152
ms->fdt = fdt;
153
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/ppc/e500.c
156
+++ b/hw/ppc/e500.c
157
@@ -XXX,XX +XXX,XX @@ static int ppce500_load_device_tree(PPCE500MachineState *pms,
158
159
done:
160
if (!dry_run) {
161
- qemu_fdt_dumpdtb(fdt, fdt_size);
162
cpu_physical_memory_write(addr, fdt, fdt_size);
163
164
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
165
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/hw/ppc/pegasos2.c
168
+++ b/hw/ppc/pegasos2.c
169
@@ -XXX,XX +XXX,XX @@ static void pegasos2_machine_reset(MachineState *machine, ResetType type)
170
d[1] = cpu_to_be64(pm->kernel_size - (pm->kernel_entry - pm->kernel_addr));
171
qemu_fdt_setprop(fdt, "/chosen", "qemu,boot-kernel", d, sizeof(d));
172
173
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
174
g_free(pm->fdt_blob);
175
pm->fdt_blob = fdt;
176
177
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/hw/ppc/pnv.c
180
+++ b/hw/ppc/pnv.c
181
@@ -XXX,XX +XXX,XX @@ static void pnv_reset(MachineState *machine, ResetType type)
182
_FDT((fdt_pack(fdt)));
183
}
184
185
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
186
cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
187
188
/* Update machine->fdt with latest fdt */
189
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/hw/ppc/spapr.c
192
+++ b/hw/ppc/spapr.c
193
@@ -XXX,XX +XXX,XX @@ static void spapr_machine_reset(MachineState *machine, ResetType type)
194
0, fdt_addr, 0);
195
cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
196
}
197
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
198
199
g_free(spapr->fdt_blob);
200
spapr->fdt_size = fdt_totalsize(fdt);
201
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
202
index XXXXXXX..XXXXXXX 100644
203
--- a/hw/riscv/boot.c
204
+++ b/hw/riscv/boot.c
205
@@ -XXX,XX +XXX,XX @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
206
uint32_t fdtsize = fdt_totalsize(fdt);
207
208
/* copy in the device tree */
209
- qemu_fdt_dumpdtb(fdt, fdtsize);
210
-
211
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
212
&address_space_memory);
213
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
214
diff --git a/system/device_tree.c b/system/device_tree.c
215
index XXXXXXX..XXXXXXX 100644
216
--- a/system/device_tree.c
217
+++ b/system/device_tree.c
218
@@ -XXX,XX +XXX,XX @@ int qemu_fdt_add_path(void *fdt, const char *path)
219
return retval;
220
}
221
222
-void qemu_fdt_dumpdtb(void *fdt, int size)
223
-{
224
- const char *dumpdtb = current_machine->dumpdtb;
225
-
226
- if (dumpdtb) {
227
- /* Dump the dtb to a file and quit */
228
- if (g_file_set_contents(dumpdtb, fdt, size, NULL)) {
229
- info_report("dtb dumped to %s. Exiting.", dumpdtb);
230
- exit(0);
231
- }
232
- error_report("%s: Failed dumping dtb to %s", __func__, dumpdtb);
233
- exit(1);
234
- }
235
-}
236
-
237
int qemu_fdt_setprop_sized_cells_from_array(void *fdt,
238
const char *node_path,
239
const char *property,
29
--
240
--
30
2.16.2
241
2.43.0
31
32
diff view generated by jsdifflib
New patch
1
Currently if the user requests via -machine dumpdtb=file.dtb that we
2
dump the DTB, but the machine doesn't have a DTB, we silently ignore
3
the option. This is confusing to users, and is a legacy of the old
4
board-specific implementation of the option, where if the execution
5
codepath didn't go via a call to qemu_fdt_dumpdtb() we would never
6
handle the option.
1
7
8
Now we handle the option in one place in machine.c, we can provide
9
the user with a useful message if they asked us to dump a DTB when
10
none exists. qmp_dumpdtb() already produces this error; remove the
11
logic in handle_machine_dumpdtb() that was there specifically to
12
avoid hitting it.
13
14
While we're here, beef up the error message a bit with a hint, and
15
make it consistent about "an FDT" rather than "a FDT". (In the
16
qmp_dumpdtb() case this needs an ERRP_GUARD to make
17
error_append_hint() work when the caller passes error_fatal.)
18
19
Note that the three places where we might report "doesn't have an
20
FDT" are hit in different situations:
21
22
(1) in handle_machine_dumpdtb(), if CONFIG_FDT is not set: this is
23
because the QEMU binary was built without libfdt at all. The
24
build system will not let you build with a machine type that
25
needs an FDT but no libfdt, so here we know both that the machine
26
doesn't use FDT and that QEMU doesn't have the support:
27
28
(2) in the device_tree-stub.c qmp_dumpdtb(): this is used when
29
we had libfdt at build time but the target architecture didn't
30
enable any machines which did "select DEVICE_TREE", so here we
31
know that the machine doesn't use FDT.
32
33
(3) in qmp_dumpdtb(), if current_machine->fdt is NULL all we know
34
is that this machine never set it. That might be because it doesn't
35
use FDT, or it might be because the user didn't pass an FDT
36
on the command line and the machine doesn't autogenerate an FDT.
37
38
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2733
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
41
Message-id: 20250206151214.2947842-7-peter.maydell@linaro.org
42
---
43
hw/core/machine.c | 6 ++----
44
system/device_tree-stub.c | 5 ++++-
45
system/device_tree.c | 7 ++++++-
46
3 files changed, 12 insertions(+), 6 deletions(-)
47
48
diff --git a/hw/core/machine.c b/hw/core/machine.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/core/machine.c
51
+++ b/hw/core/machine.c
52
@@ -XXX,XX +XXX,XX @@ static void handle_machine_dumpdtb(MachineState *ms)
53
if (!ms->dumpdtb) {
54
return;
55
}
56
- if (!ms->fdt) {
57
- /* Silently ignore dumpdtb option if there is nothing to dump */
58
- return;
59
- }
60
#ifdef CONFIG_FDT
61
qmp_dumpdtb(ms->dumpdtb, &error_fatal);
62
exit(0);
63
#else
64
error_report("This machine doesn't have an FDT");
65
+ error_printf("(this machine type definitely doesn't use FDT, and "
66
+ "this QEMU doesn't have FDT support compiled in)\n");
67
exit(1);
68
#endif
69
}
70
diff --git a/system/device_tree-stub.c b/system/device_tree-stub.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/system/device_tree-stub.c
73
+++ b/system/device_tree-stub.c
74
@@ -XXX,XX +XXX,XX @@
75
#ifdef CONFIG_FDT
76
void qmp_dumpdtb(const char *filename, Error **errp)
77
{
78
- error_setg(errp, "This machine doesn't have a FDT");
79
+ ERRP_GUARD();
80
+
81
+ error_setg(errp, "This machine doesn't have an FDT");
82
+ error_append_hint(errp, "(this machine type definitely doesn't use FDT)\n");
83
}
84
#endif
85
diff --git a/system/device_tree.c b/system/device_tree.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/system/device_tree.c
88
+++ b/system/device_tree.c
89
@@ -XXX,XX +XXX,XX @@ out:
90
91
void qmp_dumpdtb(const char *filename, Error **errp)
92
{
93
+ ERRP_GUARD();
94
+
95
g_autoptr(GError) err = NULL;
96
uint32_t size;
97
98
if (!current_machine->fdt) {
99
- error_setg(errp, "This machine doesn't have a FDT");
100
+ error_setg(errp, "This machine doesn't have an FDT");
101
+ error_append_hint(errp,
102
+ "(Perhaps it doesn't support FDT at all, or perhaps "
103
+ "you need to provide an FDT with the -fdt option?)\n");
104
return;
105
}
106
107
--
108
2.43.0
diff view generated by jsdifflib
1
The raspi3 has AArch64 CPUs, which means that our smpboot
1
Currently we hardcode at compile time whether the floatx80 default
2
code for keeping the secondary CPUs in a pen needs to have
2
Infinity value has the explicit integer bit set or not (x86 sets it;
3
a version for A64 as well as A32. Without this, the
3
m68k does not). To be able to compile softfloat once for all targets
4
secondary CPUs go into an infinite loop of taking undefined
4
we'd like to move this setting to runtime.
5
instruction exceptions.
5
6
Define a new FloatX80Behaviour enum which is a set of flags that
7
define the target's floatx80 handling. Initially we define just one
8
flag, for whether the default Infinity has the Integer bit set or
9
not, but we will expand this in future commits to cover the other
10
floatx80 target specifics that we currently make compile-time
11
settings.
12
13
Define a new function floatx80_default_inf() which returns the
14
appropriate default Infinity value of the given sign, and use it in
15
the code that was previously directly using the compile-time constant
16
floatx80_infinity_{low,high} values when packing an infinity into a
17
floatx80.
18
19
Since floatx80 is highly unlikely to be supported in any new
20
architecture, and the existing code is generally written as "default
21
to like x87, with an ifdef for m68k", we make the default value for
22
the floatx80 behaviour flags be "what x87 does". This means we only
23
need to change the m68k target to specify the behaviour flags.
24
25
(Other users of floatx80 are the Arm NWFPE emulation, which is
26
obsolete and probably not actually doing the right thing anyway, and
27
the PPC xsrqpxp insn. Making the default be "like x87" avoids our
28
needing to review and test for behaviour changes there.)
29
30
We will clean up the remaining uses of the floatx80_infinity global
31
constant in subsequent commits.
6
32
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
34
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180313153458.26822-10-peter.maydell@linaro.org
35
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
36
Message-id: 20250224111524.1101196-2-peter.maydell@linaro.org
37
Message-id: 20250217125055.160887-2-peter.maydell@linaro.org
10
---
38
---
11
hw/arm/raspi.c | 41 ++++++++++++++++++++++++++++++++++++++++-
39
include/fpu/softfloat-helpers.h | 12 ++++++++++++
12
1 file changed, 40 insertions(+), 1 deletion(-)
40
include/fpu/softfloat-types.h | 13 +++++++++++++
41
include/fpu/softfloat.h | 1 +
42
fpu/softfloat.c | 7 +++----
43
target/m68k/cpu.c | 6 ++++++
44
fpu/softfloat-specialize.c.inc | 10 ++++++++++
45
6 files changed, 45 insertions(+), 4 deletions(-)
13
46
14
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
47
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
15
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/raspi.c
49
--- a/include/fpu/softfloat-helpers.h
17
+++ b/hw/arm/raspi.c
50
+++ b/include/fpu/softfloat-helpers.h
18
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@ static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
19
#define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
52
status->floatx80_rounding_precision = val;
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
}
53
}
29
54
30
+static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
55
+static inline void set_floatx80_behaviour(FloatX80Behaviour b,
56
+ float_status *status)
31
+{
57
+{
32
+ /* Unlike the AArch32 version we don't need to call the board setup hook.
58
+ status->floatx80_behaviour = b;
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
+
54
+ static const uint64_t spintables[] = {
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
+}
59
+}
63
+
60
+
64
static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info)
61
static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
62
float_status *status)
65
{
63
{
66
arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
64
@@ -XXX,XX +XXX,XX @@ get_floatx80_rounding_precision(const float_status *status)
67
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
65
return status->floatx80_rounding_precision;
68
/* Pi2 and Pi3 requires SMP setup */
66
}
69
if (version >= 2) {
67
70
binfo.smp_loader_start = SMPBOOT_ADDR;
68
+static inline FloatX80Behaviour
71
- binfo.write_secondary_boot = write_smpboot;
69
+get_floatx80_behaviour(const float_status *status)
72
+ if (version == 2) {
70
+{
73
+ binfo.write_secondary_boot = write_smpboot;
71
+ return status->floatx80_behaviour;
74
+ } else {
72
+}
75
+ binfo.write_secondary_boot = write_smpboot64;
73
+
76
+ }
74
static inline Float2NaNPropRule
77
binfo.secondary_cpu_reset_hook = reset_secondary;
75
get_float_2nan_prop_rule(const float_status *status)
78
}
76
{
79
77
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
78
index XXXXXXX..XXXXXXX 100644
79
--- a/include/fpu/softfloat-types.h
80
+++ b/include/fpu/softfloat-types.h
81
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
82
float_ftz_before_rounding = 1,
83
} FloatFTZDetection;
84
85
+/*
86
+ * floatx80 is primarily used by x86 and m68k, and there are
87
+ * differences in the handling, largely related to the explicit
88
+ * Integer bit which floatx80 has and the other float formats do not.
89
+ * These flag values allow specification of the target's requirements
90
+ * and can be ORed together to set floatx80_behaviour.
91
+ */
92
+typedef enum __attribute__((__packed__)) {
93
+ /* In the default Infinity value, is the Integer bit 0 ? */
94
+ floatx80_default_inf_int_bit_is_zero = 1,
95
+} FloatX80Behaviour;
96
+
97
/*
98
* Floating Point Status. Individual architectures may maintain
99
* several versions of float_status for different functions. The
100
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
101
uint16_t float_exception_flags;
102
FloatRoundMode float_rounding_mode;
103
FloatX80RoundPrec floatx80_rounding_precision;
104
+ FloatX80Behaviour floatx80_behaviour;
105
Float2NaNPropRule float_2nan_prop_rule;
106
Float3NaNPropRule float_3nan_prop_rule;
107
FloatInfZeroNaNRule float_infzeronan_rule;
108
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
109
index XXXXXXX..XXXXXXX 100644
110
--- a/include/fpu/softfloat.h
111
+++ b/include/fpu/softfloat.h
112
@@ -XXX,XX +XXX,XX @@ float128 floatx80_to_float128(floatx80, float_status *status);
113
| The pattern for an extended double-precision inf.
114
*----------------------------------------------------------------------------*/
115
extern const floatx80 floatx80_infinity;
116
+floatx80 floatx80_default_inf(bool zSign, float_status *status);
117
118
/*----------------------------------------------------------------------------
119
| Software IEC/IEEE extended double-precision operations.
120
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/fpu/softfloat.c
123
+++ b/fpu/softfloat.c
124
@@ -XXX,XX +XXX,XX @@ static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
125
126
case float_class_inf:
127
/* x86 and m68k differ in the setting of the integer bit. */
128
- frac = floatx80_infinity_low;
129
+ frac = s->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero ?
130
+ 0 : (1ULL << 63);
131
exp = fmt->exp_max;
132
break;
133
134
@@ -XXX,XX +XXX,XX @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
135
) {
136
return packFloatx80( zSign, 0x7FFE, ~ roundMask );
137
}
138
- return packFloatx80(zSign,
139
- floatx80_infinity_high,
140
- floatx80_infinity_low);
141
+ return floatx80_default_inf(zSign, status);
142
}
143
if ( zExp <= 0 ) {
144
isTiny = status->tininess_before_rounding
145
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/m68k/cpu.c
148
+++ b/target/m68k/cpu.c
149
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
150
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
151
/* Default NaN: sign bit clear, all frac bits set */
152
set_float_default_nan_pattern(0b01111111, &env->fp_status);
153
+ /*
154
+ * m68k-specific floatx80 behaviour:
155
+ * * default Infinity values have a zero Integer bit
156
+ */
157
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
158
+ &env->fp_status);
159
160
nan = floatx80_default_nan(&env->fp_status);
161
for (i = 0; i < 8; i++) {
162
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
163
index XXXXXXX..XXXXXXX 100644
164
--- a/fpu/softfloat-specialize.c.inc
165
+++ b/fpu/softfloat-specialize.c.inc
166
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_default_nan(float_status *status)
167
| The pattern for a default generated extended double-precision inf.
168
*----------------------------------------------------------------------------*/
169
170
+floatx80 floatx80_default_inf(bool zSign, float_status *status)
171
+{
172
+ /*
173
+ * Whether the Integer bit is set in the default Infinity is
174
+ * target dependent.
175
+ */
176
+ bool z = status->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero;
177
+ return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
178
+}
179
+
180
#define floatx80_infinity_high 0x7FFF
181
#if defined(TARGET_M68K)
182
#define floatx80_infinity_low UINT64_C(0x0000000000000000)
80
--
183
--
81
2.16.2
184
2.43.0
82
185
83
186
diff view generated by jsdifflib
New patch
1
The global const floatx80_infinity is (unlike all the other
2
float*_infinity values) target-specific, because whether the explicit
3
Integer bit is set or not varies between m68k and i386. We want to
4
be able to compile softfloat once for multiple targets, so we can't
5
continue to use a single global whose value needs to be different
6
between targets.
1
7
8
Replace the direct uses of floatx80_infinity in target/m68k with
9
calls to the new floatx80_default_inf() function.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Message-id: 20250224111524.1101196-3-peter.maydell@linaro.org
15
Message-id: 20250217125055.160887-3-peter.maydell@linaro.org
16
---
17
target/m68k/softfloat.c | 47 ++++++++++++++---------------------------
18
1 file changed, 16 insertions(+), 31 deletions(-)
19
20
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/m68k/softfloat.c
23
+++ b/target/m68k/softfloat.c
24
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
25
if ((uint64_t) (aSig << 1)) {
26
return propagateFloatx80NaN(a, b, status);
27
}
28
- return packFloatx80(aSign, floatx80_infinity.high,
29
- floatx80_infinity.low);
30
+ return floatx80_default_inf(aSign, status);
31
}
32
if (aExp == 0) {
33
if (aSig == 0) {
34
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
35
float_raise(float_flag_invalid, status);
36
return floatx80_default_nan(status);
37
}
38
- return packFloatx80(0, floatx80_infinity.high, floatx80_infinity.low);
39
+ return floatx80_default_inf(0, status);
40
}
41
42
if (aExp == 0 && aSig == 0) {
43
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
44
if (aSign && aExp >= one_exp) {
45
if (aExp == one_exp && aSig == one_sig) {
46
float_raise(float_flag_divbyzero, status);
47
- return packFloatx80(aSign, floatx80_infinity.high,
48
- floatx80_infinity.low);
49
+ return floatx80_default_inf(aSign, status);
50
}
51
float_raise(float_flag_invalid, status);
52
return floatx80_default_nan(status);
53
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
54
propagateFloatx80NaNOneArg(a, status);
55
}
56
if (aSign == 0) {
57
- return packFloatx80(0, floatx80_infinity.high,
58
- floatx80_infinity.low);
59
+ return floatx80_default_inf(0, status);
60
}
61
}
62
63
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
64
if (aExp == 0) {
65
if (aSig == 0) { /* zero */
66
float_raise(float_flag_divbyzero, status);
67
- return packFloatx80(1, floatx80_infinity.high,
68
- floatx80_infinity.low);
69
+ return floatx80_default_inf(1, status);
70
}
71
if ((aSig & one_sig) == 0) { /* denormal */
72
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
73
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
74
propagateFloatx80NaNOneArg(a, status);
75
}
76
if (aSign == 0) {
77
- return packFloatx80(0, floatx80_infinity.high,
78
- floatx80_infinity.low);
79
+ return floatx80_default_inf(0, status);
80
}
81
}
82
83
if (aExp == 0 && aSig == 0) {
84
float_raise(float_flag_divbyzero, status);
85
- return packFloatx80(1, floatx80_infinity.high,
86
- floatx80_infinity.low);
87
+ return floatx80_default_inf(1, status);
88
}
89
90
if (aSign) {
91
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
92
propagateFloatx80NaNOneArg(a, status);
93
}
94
if (aSign == 0) {
95
- return packFloatx80(0, floatx80_infinity.high,
96
- floatx80_infinity.low);
97
+ return floatx80_default_inf(0, status);
98
}
99
}
100
101
if (aExp == 0) {
102
if (aSig == 0) {
103
float_raise(float_flag_divbyzero, status);
104
- return packFloatx80(1, floatx80_infinity.high,
105
- floatx80_infinity.low);
106
+ return floatx80_default_inf(1, status);
107
}
108
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
109
}
110
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
111
if (aSign) {
112
return packFloatx80(0, 0, 0);
113
}
114
- return packFloatx80(0, floatx80_infinity.high,
115
- floatx80_infinity.low);
116
+ return floatx80_default_inf(0, status);
117
}
118
119
if (aExp == 0 && aSig == 0) {
120
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
121
if (aSign) {
122
return packFloatx80(0, 0, 0);
123
}
124
- return packFloatx80(0, floatx80_infinity.high,
125
- floatx80_infinity.low);
126
+ return floatx80_default_inf(0, status);
127
}
128
129
if (aExp == 0 && aSig == 0) {
130
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
131
if (aSign) {
132
return packFloatx80(0, 0, 0);
133
}
134
- return packFloatx80(0, floatx80_infinity.high,
135
- floatx80_infinity.low);
136
+ return floatx80_default_inf(0, status);
137
}
138
139
if (aExp == 0 && aSig == 0) {
140
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
141
if (compact >= 0x3FFF8000) { /* |X| >= 1 */
142
if (aExp == one_exp && aSig == one_sig) { /* |X| == 1 */
143
float_raise(float_flag_divbyzero, status);
144
- return packFloatx80(aSign, floatx80_infinity.high,
145
- floatx80_infinity.low);
146
+ return floatx80_default_inf(aSign, status);
147
} else { /* |X| > 1 */
148
float_raise(float_flag_invalid, status);
149
return floatx80_default_nan(status);
150
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
151
if (aSign) {
152
return packFloatx80(aSign, one_exp, one_sig);
153
}
154
- return packFloatx80(0, floatx80_infinity.high,
155
- floatx80_infinity.low);
156
+ return floatx80_default_inf(0, status);
157
}
158
159
if (aExp == 0 && aSig == 0) {
160
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
161
if ((uint64_t) (aSig << 1)) {
162
return propagateFloatx80NaNOneArg(a, status);
163
}
164
- return packFloatx80(aSign, floatx80_infinity.high,
165
- floatx80_infinity.low);
166
+ return floatx80_default_inf(aSign, status);
167
}
168
169
if (aExp == 0 && aSig == 0) {
170
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
171
if ((uint64_t) (aSig << 1)) {
172
return propagateFloatx80NaNOneArg(a, status);
173
}
174
- return packFloatx80(0, floatx80_infinity.high,
175
- floatx80_infinity.low);
176
+ return floatx80_default_inf(0, status);
177
}
178
179
if (aExp == 0 && aSig == 0) {
180
--
181
2.43.0
182
183
diff view generated by jsdifflib
New patch
1
The global const floatx80_infinity is (unlike all the other
2
float*_infinity values) target-specific, because whether the explicit
3
Integer bit is set or not varies between m68k and i386. We want to
4
be able to compile softfloat once for multiple targets, so we can't
5
continue to use a single global whose value needs to be different
6
between targets.
1
7
8
Replace the direct uses of floatx80_infinity in target/i386 with
9
calls to the new floatx80_default_inf() function. Note that because
10
we can ask the function for either a negative or positive infinity,
11
we don't need to change the sign of a positive infinity via
12
floatx80_chs() for the negative-Inf case.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
17
Message-id: 20250224111524.1101196-4-peter.maydell@linaro.org
18
Message-id: 20250217125055.160887-4-peter.maydell@linaro.org
19
---
20
target/i386/tcg/fpu_helper.c | 7 +++----
21
1 file changed, 3 insertions(+), 4 deletions(-)
22
23
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/i386/tcg/fpu_helper.c
26
+++ b/target/i386/tcg/fpu_helper.c
27
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
28
} else if (floatx80_is_infinity(ST0)) {
29
fpush(env);
30
ST0 = ST1;
31
- ST1 = floatx80_infinity;
32
+ ST1 = floatx80_default_inf(0, &env->fp_status);
33
} else {
34
int expdif;
35
36
@@ -XXX,XX +XXX,XX @@ void helper_fscale(CPUX86State *env)
37
float_raise(float_flag_invalid, &env->fp_status);
38
ST0 = floatx80_default_nan(&env->fp_status);
39
} else {
40
- ST0 = (floatx80_is_neg(ST0) ?
41
- floatx80_chs(floatx80_infinity) :
42
- floatx80_infinity);
43
+ ST0 = floatx80_default_inf(floatx80_is_neg(ST0),
44
+ &env->fp_status);
45
}
46
}
47
} else {
48
--
49
2.43.0
50
51
diff view generated by jsdifflib
New patch
1
Unlike the other float formats, whether a floatx80 value is
2
considered to be an Infinity is target-dependent. (On x86 if the
3
explicit integer bit is clear this is a "pseudo-infinity" and not a
4
valid infinity; m68k does not care about the value of the integer
5
bit.)
1
6
7
Currently we select this target-specific logic at compile time with
8
an ifdef. We're going to want to do this at runtime, so change the
9
floatx80_is_infinity() function to take a float_status.
10
11
This commit doesn't change any logic; we'll do that in the
12
next commit.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
17
Message-id: 20250224111524.1101196-5-peter.maydell@linaro.org
18
---
19
include/fpu/softfloat.h | 2 +-
20
target/i386/tcg/fpu_helper.c | 20 +++++++++++---------
21
target/m68k/fpu_helper.c | 2 +-
22
3 files changed, 13 insertions(+), 11 deletions(-)
23
24
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/fpu/softfloat.h
27
+++ b/include/fpu/softfloat.h
28
@@ -XXX,XX +XXX,XX @@ static inline floatx80 floatx80_chs(floatx80 a)
29
return a;
30
}
31
32
-static inline bool floatx80_is_infinity(floatx80 a)
33
+static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
34
{
35
#if defined(TARGET_M68K)
36
return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
37
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/i386/tcg/fpu_helper.c
40
+++ b/target/i386/tcg/fpu_helper.c
41
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
42
/* Pass this NaN through. */
43
} else if (floatx80_is_zero(ST1) && !arg0_sign) {
44
/* Pass this zero through. */
45
- } else if (((floatx80_is_infinity(ST0) && !floatx80_is_infinity(ST1)) ||
46
+ } else if (((floatx80_is_infinity(ST0, &env->fp_status) &&
47
+ !floatx80_is_infinity(ST1, &env->fp_status)) ||
48
arg0_exp - arg1_exp >= 80) &&
49
!arg0_sign) {
50
/*
51
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
52
rexp = pi_exp;
53
rsig0 = pi_sig_high;
54
rsig1 = pi_sig_low;
55
- } else if (floatx80_is_infinity(ST1)) {
56
- if (floatx80_is_infinity(ST0)) {
57
+ } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
58
+ if (floatx80_is_infinity(ST0, &env->fp_status)) {
59
if (arg0_sign) {
60
rexp = pi_34_exp;
61
rsig0 = pi_34_sig_high;
62
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
63
rexp = pi_2_exp;
64
rsig0 = pi_2_sig_high;
65
rsig1 = pi_2_sig_low;
66
- } else if (floatx80_is_infinity(ST0) || arg0_exp - arg1_exp >= 80) {
67
+ } else if (floatx80_is_infinity(ST0, &env->fp_status) ||
68
+ arg0_exp - arg1_exp >= 80) {
69
/* ST0 is negative. */
70
rexp = pi_exp;
71
rsig0 = pi_sig_high;
72
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
73
}
74
fpush(env);
75
ST0 = ST1;
76
- } else if (floatx80_is_infinity(ST0)) {
77
+ } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
78
fpush(env);
79
ST0 = ST1;
80
ST1 = floatx80_default_inf(0, &env->fp_status);
81
@@ -XXX,XX +XXX,XX @@ void helper_fyl2x(CPUX86State *env)
82
} else if (arg0_sign && !floatx80_is_zero(ST0)) {
83
float_raise(float_flag_invalid, &env->fp_status);
84
ST1 = floatx80_default_nan(&env->fp_status);
85
- } else if (floatx80_is_infinity(ST1)) {
86
+ } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
87
FloatRelation cmp = floatx80_compare(ST0, floatx80_one,
88
&env->fp_status);
89
switch (cmp) {
90
@@ -XXX,XX +XXX,XX @@ void helper_fyl2x(CPUX86State *env)
91
ST1 = floatx80_default_nan(&env->fp_status);
92
break;
93
}
94
- } else if (floatx80_is_infinity(ST0)) {
95
+ } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
96
if (floatx80_is_zero(ST1)) {
97
float_raise(float_flag_invalid, &env->fp_status);
98
ST1 = floatx80_default_nan(&env->fp_status);
99
@@ -XXX,XX +XXX,XX @@ void helper_fscale(CPUX86State *env)
100
float_raise(float_flag_invalid, &env->fp_status);
101
ST0 = floatx80_silence_nan(ST0, &env->fp_status);
102
}
103
- } else if (floatx80_is_infinity(ST1) &&
104
+ } else if (floatx80_is_infinity(ST1, &env->fp_status) &&
105
!floatx80_invalid_encoding(ST0) &&
106
!floatx80_is_any_nan(ST0)) {
107
if (floatx80_is_neg(ST1)) {
108
- if (floatx80_is_infinity(ST0)) {
109
+ if (floatx80_is_infinity(ST0, &env->fp_status)) {
110
float_raise(float_flag_invalid, &env->fp_status);
111
ST0 = floatx80_default_nan(&env->fp_status);
112
} else {
113
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/m68k/fpu_helper.c
116
+++ b/target/m68k/fpu_helper.c
117
@@ -XXX,XX +XXX,XX @@ void HELPER(ftst)(CPUM68KState *env, FPReg *val)
118
119
if (floatx80_is_any_nan(val->d)) {
120
cc |= FPSR_CC_A;
121
- } else if (floatx80_is_infinity(val->d)) {
122
+ } else if (floatx80_is_infinity(val->d, &env->fp_status)) {
123
cc |= FPSR_CC_I;
124
} else if (floatx80_is_zero(val->d)) {
125
cc |= FPSR_CC_Z;
126
--
127
2.43.0
128
129
diff view generated by jsdifflib
1
Our BCM2836 type is really a generic one that can be any of
1
In Intel terminology, a floatx80 Infinity with the explicit integer
2
the bcm283x family. Rename it accordingly. We change only
2
bit clear is a "pseudo-infinity"; for x86 these are not valid
3
the names which are visible via the header file to the
3
infinity values. m68k is looser and does not care whether the
4
rest of the QEMU code, leaving private function names
4
Integer bit is set or clear in an infinity.
5
in bcm2836.c as they are.
6
5
7
This is a preliminary to making bcm283x be an abstract
6
Move this setting to runtime rather than using an ifdef in
8
parent class to specific types for the bcm2836 and bcm2837.
7
floatx80_is_infinity().
8
9
Since this was the last use of the floatx80_infinity global constant,
10
we remove it and its definition here.
9
11
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Message-id: 20180313153458.26822-6-peter.maydell@linaro.org
15
Message-id: 20250224111524.1101196-6-peter.maydell@linaro.org
16
Message-id: 20250217125055.160887-5-peter.maydell@linaro.org
14
---
17
---
15
include/hw/arm/bcm2836.h | 12 ++++++------
18
include/fpu/softfloat-types.h | 5 +++++
16
hw/arm/bcm2836.c | 17 +++++++++--------
19
include/fpu/softfloat.h | 18 +++++++++++-------
17
hw/arm/raspi.c | 16 ++++++++--------
20
target/m68k/cpu.c | 4 +++-
18
3 files changed, 23 insertions(+), 22 deletions(-)
21
fpu/softfloat-specialize.c.inc | 10 ----------
22
4 files changed, 19 insertions(+), 18 deletions(-)
19
23
20
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
24
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
21
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2836.h
26
--- a/include/fpu/softfloat-types.h
23
+++ b/include/hw/arm/bcm2836.h
27
+++ b/include/fpu/softfloat-types.h
24
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
25
#include "hw/arm/bcm2835_peripherals.h"
29
typedef enum __attribute__((__packed__)) {
26
#include "hw/intc/bcm2836_control.h"
30
/* In the default Infinity value, is the Integer bit 0 ? */
27
31
floatx80_default_inf_int_bit_is_zero = 1,
28
-#define TYPE_BCM2836 "bcm2836"
32
+ /*
29
-#define BCM2836(obj) OBJECT_CHECK(BCM2836State, (obj), TYPE_BCM2836)
33
+ * Are Pseudo-infinities (Inf with the Integer bit zero) valid?
30
+#define TYPE_BCM283X "bcm283x"
34
+ * If so, floatx80_is_infinity() will return true for them.
31
+#define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X)
35
+ */
32
36
+ floatx80_pseudo_inf_valid = 2,
33
-#define BCM2836_NCPUS 4
37
} FloatX80Behaviour;
34
+#define BCM283X_NCPUS 4
38
35
39
/*
36
-typedef struct BCM2836State {
40
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
37
+typedef struct BCM283XState {
38
/*< private >*/
39
DeviceState parent_obj;
40
/*< public >*/
41
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2836State {
42
char *cpu_type;
43
uint32_t enabled_cpus;
44
45
- ARMCPU cpus[BCM2836_NCPUS];
46
+ ARMCPU cpus[BCM283X_NCPUS];
47
BCM2836ControlState control;
48
BCM2835PeripheralState peripherals;
49
-} BCM2836State;
50
+} BCM283XState;
51
52
#endif /* BCM2836_H */
53
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
54
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/arm/bcm2836.c
42
--- a/include/fpu/softfloat.h
56
+++ b/hw/arm/bcm2836.c
43
+++ b/include/fpu/softfloat.h
57
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@ float128 floatx80_to_float128(floatx80, float_status *status);
58
45
/*----------------------------------------------------------------------------
59
static void bcm2836_init(Object *obj)
46
| The pattern for an extended double-precision inf.
47
*----------------------------------------------------------------------------*/
48
-extern const floatx80 floatx80_infinity;
49
floatx80 floatx80_default_inf(bool zSign, float_status *status);
50
51
/*----------------------------------------------------------------------------
52
@@ -XXX,XX +XXX,XX @@ static inline floatx80 floatx80_chs(floatx80 a)
53
54
static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
60
{
55
{
61
- BCM2836State *s = BCM2836(obj);
56
-#if defined(TARGET_M68K)
62
+ BCM283XState *s = BCM283X(obj);
57
- return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
63
58
-#else
64
object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL);
59
- return (a.high & 0x7fff) == floatx80_infinity.high &&
65
object_property_add_child(obj, "control", OBJECT(&s->control), NULL);
60
- a.low == floatx80_infinity.low;
66
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
61
-#endif
67
62
+ /*
68
static void bcm2836_realize(DeviceState *dev, Error **errp)
63
+ * It's target-specific whether the Integer bit is permitted
69
{
64
+ * to be 0 in a valid Infinity value. (x86 says no, m68k says yes).
70
- BCM2836State *s = BCM2836(dev);
65
+ */
71
+ BCM283XState *s = BCM283X(dev);
66
+ bool intbit = a.low >> 63;
72
Object *obj;
67
+
73
Error *err = NULL;
68
+ if (!intbit &&
74
int n;
69
+ !(status->floatx80_behaviour & floatx80_pseudo_inf_valid)) {
75
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
70
+ return false;
76
/* common peripherals from bcm2835 */
71
+ }
77
72
+ return (a.high & 0x7fff) == 0x7fff && !(a.low << 1);
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
*/
93
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
94
}
73
}
95
74
96
static Property bcm2836_props[] = {
75
static inline bool floatx80_is_neg(floatx80 a)
97
- DEFINE_PROP_STRING("cpu-type", BCM2836State, cpu_type),
76
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
98
- DEFINE_PROP_UINT32("enabled-cpus", BCM2836State, enabled_cpus, BCM2836_NCPUS),
77
index XXXXXXX..XXXXXXX 100644
99
+ DEFINE_PROP_STRING("cpu-type", BCM283XState, cpu_type),
78
--- a/target/m68k/cpu.c
100
+ DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
79
+++ b/target/m68k/cpu.c
101
+ BCM283X_NCPUS),
80
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
102
DEFINE_PROP_END_OF_LIST()
81
/*
103
};
82
* m68k-specific floatx80 behaviour:
104
83
* * default Infinity values have a zero Integer bit
105
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
84
+ * * input Infinities may have the Integer bit either 0 or 1
85
*/
86
- set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
87
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
88
+ floatx80_pseudo_inf_valid,
89
&env->fp_status);
90
91
nan = floatx80_default_nan(&env->fp_status);
92
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
93
index XXXXXXX..XXXXXXX 100644
94
--- a/fpu/softfloat-specialize.c.inc
95
+++ b/fpu/softfloat-specialize.c.inc
96
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_default_inf(bool zSign, float_status *status)
97
return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
106
}
98
}
107
99
108
static const TypeInfo bcm2836_type_info = {
100
-#define floatx80_infinity_high 0x7FFF
109
- .name = TYPE_BCM2836,
101
-#if defined(TARGET_M68K)
110
+ .name = TYPE_BCM283X,
102
-#define floatx80_infinity_low UINT64_C(0x0000000000000000)
111
.parent = TYPE_DEVICE,
103
-#else
112
- .instance_size = sizeof(BCM2836State),
104
-#define floatx80_infinity_low UINT64_C(0x8000000000000000)
113
+ .instance_size = sizeof(BCM283XState),
105
-#endif
114
.instance_init = bcm2836_init,
106
-
115
.class_init = bcm2836_class_init,
107
-const floatx80 floatx80_infinity
116
};
108
- = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low);
117
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
109
-
118
index XXXXXXX..XXXXXXX 100644
110
/*----------------------------------------------------------------------------
119
--- a/hw/arm/raspi.c
111
| Returns 1 if the half-precision floating-point value `a' is a quiet
120
+++ b/hw/arm/raspi.c
112
| NaN; otherwise returns 0.
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
--
113
--
166
2.16.2
114
2.43.0
167
115
168
116
diff view generated by jsdifflib
New patch
1
The definition of which floatx80 encodings are invalid is
2
target-specific. Currently we handle this with an ifdef, but we
3
would like to defer this decision to runtime. In preparation, pass a
4
float_status argument to floatx80_invalid_encoding().
1
5
6
We will change the implementation from ifdef to looking at
7
the status argument in the following commit.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20250224111524.1101196-7-peter.maydell@linaro.org
13
---
14
include/fpu/softfloat.h | 2 +-
15
fpu/softfloat.c | 2 +-
16
target/i386/tcg/fpu_helper.c | 24 +++++++++++++-----------
17
3 files changed, 15 insertions(+), 13 deletions(-)
18
19
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/fpu/softfloat.h
22
+++ b/include/fpu/softfloat.h
23
@@ -XXX,XX +XXX,XX @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
24
| pseudo-denormals, which must still be correctly handled as inputs even
25
| if they are never generated as outputs.
26
*----------------------------------------------------------------------------*/
27
-static inline bool floatx80_invalid_encoding(floatx80 a)
28
+static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
29
{
30
#if defined(TARGET_M68K)
31
/*-------------------------------------------------------------------------
32
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/fpu/softfloat.c
35
+++ b/fpu/softfloat.c
36
@@ -XXX,XX +XXX,XX @@ static bool floatx80_unpack_canonical(FloatParts128 *p, floatx80 f,
37
g_assert_not_reached();
38
}
39
40
- if (unlikely(floatx80_invalid_encoding(f))) {
41
+ if (unlikely(floatx80_invalid_encoding(f, s))) {
42
float_raise(float_flag_invalid, s);
43
return false;
44
}
45
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/i386/tcg/fpu_helper.c
48
+++ b/target/i386/tcg/fpu_helper.c
49
@@ -XXX,XX +XXX,XX @@ void helper_f2xm1(CPUX86State *env)
50
int32_t exp = extractFloatx80Exp(ST0);
51
bool sign = extractFloatx80Sign(ST0);
52
53
- if (floatx80_invalid_encoding(ST0)) {
54
+ if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
55
float_raise(float_flag_invalid, &env->fp_status);
56
ST0 = floatx80_default_nan(&env->fp_status);
57
} else if (floatx80_is_any_nan(ST0)) {
58
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
59
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
60
float_raise(float_flag_invalid, &env->fp_status);
61
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
62
- } else if (floatx80_invalid_encoding(ST0) ||
63
- floatx80_invalid_encoding(ST1)) {
64
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
65
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
66
float_raise(float_flag_invalid, &env->fp_status);
67
ST1 = floatx80_default_nan(&env->fp_status);
68
} else if (floatx80_is_any_nan(ST0)) {
69
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
70
&env->fp_status);
71
fpush(env);
72
ST0 = temp.d;
73
- } else if (floatx80_invalid_encoding(ST0)) {
74
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
75
float_raise(float_flag_invalid, &env->fp_status);
76
ST0 = floatx80_default_nan(&env->fp_status);
77
fpush(env);
78
@@ -XXX,XX +XXX,XX @@ static void helper_fprem_common(CPUX86State *env, bool mod)
79
env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
80
if (floatx80_is_zero(ST0) || floatx80_is_zero(ST1) ||
81
exp0 == 0x7fff || exp1 == 0x7fff ||
82
- floatx80_invalid_encoding(ST0) || floatx80_invalid_encoding(ST1)) {
83
+ floatx80_invalid_encoding(ST0, &env->fp_status) ||
84
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
85
ST0 = floatx80_modrem(ST0, ST1, mod, &quotient, &env->fp_status);
86
} else {
87
if (exp0 == 0) {
88
@@ -XXX,XX +XXX,XX @@ void helper_fyl2xp1(CPUX86State *env)
89
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
90
float_raise(float_flag_invalid, &env->fp_status);
91
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
92
- } else if (floatx80_invalid_encoding(ST0) ||
93
- floatx80_invalid_encoding(ST1)) {
94
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
95
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
96
float_raise(float_flag_invalid, &env->fp_status);
97
ST1 = floatx80_default_nan(&env->fp_status);
98
} else if (floatx80_is_any_nan(ST0)) {
99
@@ -XXX,XX +XXX,XX @@ void helper_fyl2x(CPUX86State *env)
100
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
101
float_raise(float_flag_invalid, &env->fp_status);
102
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
103
- } else if (floatx80_invalid_encoding(ST0) ||
104
- floatx80_invalid_encoding(ST1)) {
105
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
106
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
107
float_raise(float_flag_invalid, &env->fp_status);
108
ST1 = floatx80_default_nan(&env->fp_status);
109
} else if (floatx80_is_any_nan(ST0)) {
110
@@ -XXX,XX +XXX,XX @@ void helper_frndint(CPUX86State *env)
111
void helper_fscale(CPUX86State *env)
112
{
113
uint8_t old_flags = save_exception_flags(env);
114
- if (floatx80_invalid_encoding(ST1) || floatx80_invalid_encoding(ST0)) {
115
+ if (floatx80_invalid_encoding(ST1, &env->fp_status) ||
116
+ floatx80_invalid_encoding(ST0, &env->fp_status)) {
117
float_raise(float_flag_invalid, &env->fp_status);
118
ST0 = floatx80_default_nan(&env->fp_status);
119
} else if (floatx80_is_any_nan(ST1)) {
120
@@ -XXX,XX +XXX,XX @@ void helper_fscale(CPUX86State *env)
121
ST0 = floatx80_silence_nan(ST0, &env->fp_status);
122
}
123
} else if (floatx80_is_infinity(ST1, &env->fp_status) &&
124
- !floatx80_invalid_encoding(ST0) &&
125
+ !floatx80_invalid_encoding(ST0, &env->fp_status) &&
126
!floatx80_is_any_nan(ST0)) {
127
if (floatx80_is_neg(ST1)) {
128
if (floatx80_is_infinity(ST0, &env->fp_status)) {
129
--
130
2.43.0
131
132
diff view generated by jsdifflib
1
The bcm2837 is pretty similar to the bcm2836, but it does have
1
Because floatx80 has an explicit integer bit, this permits some
2
some differences. Notably, the MPIDR affinity aff1 values it
2
odd encodings where the integer bit is not set correctly for the
3
sets for the CPUs are 0x0, rather than the 0xf that the bcm2836
3
floating point value type. In In Intel terminology the
4
uses, and if this is wrong Linux will not boot.
4
categories are:
5
exp == 0, int = 0, mantissa == 0 : zeroes
6
exp == 0, int = 0, mantissa != 0 : denormals
7
exp == 0, int = 1 : pseudo-denormals
8
0 < exp < 0x7fff, int = 0 : unnormals
9
0 < exp < 0x7fff, int = 1 : normals
10
exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
11
exp == 0x7fff, int = 1, mantissa == 0 : infinities
12
exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
13
exp == 0x7fff, int = 1, mantissa == 0 : NaNs
5
14
6
Rather than trying to have one device with properties that
15
The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
7
configure it differently for the two cases, create two
16
x87 permits as input also pseudo-denormals.
8
separate QOM devices for the two SoCs. We use the same approach
17
m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
9
as hw/arm/aspeed_soc.c and share code and have a data table
18
10
that might differ per-SoC. For the moment the two types don't
19
Currently we have an ifdef in floatx80_invalid_encoding() to select
11
actually have different behaviour.
20
the x86 vs m68k behaviour. Add new floatx80_behaviour flags to
21
select whether pseudo-NaN and unnormal are valid, and use these
22
(plus the existing pseudo_inf_valid flag) to decide whether these
23
encodings are invalid at runtime.
24
25
We leave pseudo-denormals as always-valid, since both x86 and m68k
26
accept them.
12
27
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20180313153458.26822-7-peter.maydell@linaro.org
30
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
31
Message-id: 20250224111524.1101196-8-peter.maydell@linaro.org
32
Message-id: 20250217125055.160887-6-peter.maydell@linaro.org
16
---
33
---
17
include/hw/arm/bcm2836.h | 19 +++++++++++++++++++
34
include/fpu/softfloat-types.h | 14 ++++++++
18
hw/arm/bcm2836.c | 37 ++++++++++++++++++++++++++++++++-----
35
include/fpu/softfloat.h | 68 ++++++++++++++++++-----------------
19
hw/arm/raspi.c | 3 ++-
36
target/m68k/cpu.c | 28 ++++++++++++++-
20
3 files changed, 53 insertions(+), 6 deletions(-)
37
3 files changed, 77 insertions(+), 33 deletions(-)
21
38
22
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
39
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
23
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/bcm2836.h
41
--- a/include/fpu/softfloat-types.h
25
+++ b/include/hw/arm/bcm2836.h
42
+++ b/include/fpu/softfloat-types.h
26
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
27
44
/*
28
#define BCM283X_NCPUS 4
45
* Are Pseudo-infinities (Inf with the Integer bit zero) valid?
29
46
* If so, floatx80_is_infinity() will return true for them.
30
+/* These type names are for specific SoCs; other than instantiating
47
+ * If not, floatx80_invalid_encoding will return false for them,
31
+ * them, code using these devices should always handle them via the
48
+ * and using them as inputs to a float op will raise Invalid.
32
+ * BCM283x base class, so they have no BCM2836(obj) etc macros.
49
*/
33
+ */
50
floatx80_pseudo_inf_valid = 2,
34
+#define TYPE_BCM2836 "bcm2836"
51
+ /*
35
+#define TYPE_BCM2837 "bcm2837"
52
+ * Are Pseudo-NaNs (NaNs where the Integer bit is zero) valid?
53
+ * If not, floatx80_invalid_encoding() will return false for them,
54
+ * and using them as inputs to a float op will raise Invalid.
55
+ */
56
+ floatx80_pseudo_nan_valid = 4,
57
+ /*
58
+ * Are Unnormals (0 < exp < 0x7fff, Integer bit zero) valid?
59
+ * If not, floatx80_invalid_encoding() will return false for them,
60
+ * and using them as inputs to a float op will raise Invalid.
61
+ */
62
+ floatx80_unnormal_valid = 8,
63
} FloatX80Behaviour;
64
65
/*
66
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
67
index XXXXXXX..XXXXXXX 100644
68
--- a/include/fpu/softfloat.h
69
+++ b/include/fpu/softfloat.h
70
@@ -XXX,XX +XXX,XX @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
71
72
/*----------------------------------------------------------------------------
73
| Return whether the given value is an invalid floatx80 encoding.
74
-| Invalid floatx80 encodings arise when the integer bit is not set, but
75
-| the exponent is not zero. The only times the integer bit is permitted to
76
-| be zero is in subnormal numbers and the value zero.
77
-| This includes what the Intel software developer's manual calls pseudo-NaNs,
78
-| pseudo-infinities and un-normal numbers. It does not include
79
-| pseudo-denormals, which must still be correctly handled as inputs even
80
-| if they are never generated as outputs.
81
+| Invalid floatx80 encodings may arise when the integer bit is not set
82
+| correctly; this is target-specific. In Intel terminology the
83
+| categories are:
84
+| exp == 0, int = 0, mantissa == 0 : zeroes
85
+| exp == 0, int = 0, mantissa != 0 : denormals
86
+| exp == 0, int = 1 : pseudo-denormals
87
+| 0 < exp < 0x7fff, int = 0 : unnormals
88
+| 0 < exp < 0x7fff, int = 1 : normals
89
+| exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
90
+| exp == 0x7fff, int = 1, mantissa == 0 : infinities
91
+| exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
92
+| exp == 0x7fff, int = 1, mantissa == 0 : NaNs
93
+|
94
+| The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
95
+| x87 permits as input also pseudo-denormals.
96
+| m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
97
+|
98
+| Since we don't have a target that handles floatx80 but prohibits
99
+| pseudo-denormals in input, we don't currently have a floatx80_behaviour
100
+| flag for that case, but instead always accept it. Conveniently this
101
+| means that all cases with either exponent 0 or the integer bit set are
102
+| valid for all targets.
103
*----------------------------------------------------------------------------*/
104
static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
105
{
106
-#if defined(TARGET_M68K)
107
- /*-------------------------------------------------------------------------
108
- | With m68k, the explicit integer bit can be zero in the case of:
109
- | - zeros (exp == 0, mantissa == 0)
110
- | - denormalized numbers (exp == 0, mantissa != 0)
111
- | - unnormalized numbers (exp != 0, exp < 0x7FFF)
112
- | - infinities (exp == 0x7FFF, mantissa == 0)
113
- | - not-a-numbers (exp == 0x7FFF, mantissa != 0)
114
- |
115
- | For infinities and NaNs, the explicit integer bit can be either one or
116
- | zero.
117
- |
118
- | The IEEE 754 standard does not define a zero integer bit. Such a number
119
- | is an unnormalized number. Hardware does not directly support
120
- | denormalized and unnormalized numbers, but implicitly supports them by
121
- | trapping them as unimplemented data types, allowing efficient conversion
122
- | in software.
123
- |
124
- | See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
125
- | "1.6 FLOATING-POINT DATA TYPES"
126
- *------------------------------------------------------------------------*/
127
- return false;
128
-#else
129
- return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0;
130
-#endif
131
+ if ((a.low >> 63) || (a.high & 0x7fff) == 0) {
132
+ /* Anything with the Integer bit set or the exponent 0 is valid */
133
+ return false;
134
+ }
36
+
135
+
37
typedef struct BCM283XState {
136
+ if ((a.high & 0x7fff) == 0x7fff) {
38
/*< private >*/
137
+ if (a.low) {
39
DeviceState parent_obj;
138
+ return !(s->floatx80_behaviour & floatx80_pseudo_nan_valid);
40
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XState {
139
+ } else {
41
BCM2835PeripheralState peripherals;
140
+ return !(s->floatx80_behaviour & floatx80_pseudo_inf_valid);
42
} BCM283XState;
141
+ }
43
142
+ } else {
44
+typedef struct BCM283XInfo BCM283XInfo;
143
+ return !(s->floatx80_behaviour & floatx80_unnormal_valid);
45
+
46
+typedef struct BCM283XClass {
47
+ DeviceClass parent_class;
48
+ const BCM283XInfo *info;
49
+} BCM283XClass;
50
+
51
+#define BCM283X_CLASS(klass) \
52
+ OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
53
+#define BCM283X_GET_CLASS(obj) \
54
+ OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
55
+
56
#endif /* BCM2836_H */
57
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/bcm2836.c
60
+++ b/hw/arm/bcm2836.c
61
@@ -XXX,XX +XXX,XX @@
62
/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
63
#define BCM2836_CONTROL_BASE 0x40000000
64
65
+struct BCM283XInfo {
66
+ const char *name;
67
+};
68
+
69
+static const BCM283XInfo bcm283x_socs[] = {
70
+ {
71
+ .name = TYPE_BCM2836,
72
+ },
73
+ {
74
+ .name = TYPE_BCM2837,
75
+ },
76
+};
77
+
78
static void bcm2836_init(Object *obj)
79
{
80
BCM283XState *s = BCM283X(obj);
81
@@ -XXX,XX +XXX,XX @@ static Property bcm2836_props[] = {
82
DEFINE_PROP_END_OF_LIST()
83
};
84
85
-static void bcm2836_class_init(ObjectClass *oc, void *data)
86
+static void bcm283x_class_init(ObjectClass *oc, void *data)
87
{
88
DeviceClass *dc = DEVICE_CLASS(oc);
89
+ BCM283XClass *bc = BCM283X_CLASS(oc);
90
91
- dc->props = bcm2836_props;
92
+ bc->info = data;
93
dc->realize = bcm2836_realize;
94
+ dc->props = bcm2836_props;
95
}
96
97
-static const TypeInfo bcm2836_type_info = {
98
+static const TypeInfo bcm283x_type_info = {
99
.name = TYPE_BCM283X,
100
.parent = TYPE_DEVICE,
101
.instance_size = sizeof(BCM283XState),
102
.instance_init = bcm2836_init,
103
- .class_init = bcm2836_class_init,
104
+ .class_size = sizeof(BCM283XClass),
105
+ .abstract = true,
106
};
107
108
static void bcm2836_register_types(void)
109
{
110
- type_register_static(&bcm2836_type_info);
111
+ int i;
112
+
113
+ type_register_static(&bcm283x_type_info);
114
+ for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) {
115
+ TypeInfo ti = {
116
+ .name = bcm283x_socs[i].name,
117
+ .parent = TYPE_BCM283X,
118
+ .class_init = bcm283x_class_init,
119
+ .class_data = (void *) &bcm283x_socs[i],
120
+ };
121
+ type_register(&ti);
122
+ }
144
+ }
123
}
145
}
124
146
125
type_init(bcm2836_register_types)
147
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
126
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
148
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
127
index XXXXXXX..XXXXXXX 100644
149
index XXXXXXX..XXXXXXX 100644
128
--- a/hw/arm/raspi.c
150
--- a/target/m68k/cpu.c
129
+++ b/hw/arm/raspi.c
151
+++ b/target/m68k/cpu.c
130
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
152
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
131
BusState *bus;
153
* m68k-specific floatx80 behaviour:
132
DeviceState *carddev;
154
* * default Infinity values have a zero Integer bit
133
155
* * input Infinities may have the Integer bit either 0 or 1
134
- object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM283X);
156
+ * * pseudo-denormals supported for input and output
135
+ object_initialize(&s->soc, sizeof(s->soc),
157
+ * * don't raise Invalid for pseudo-NaN/pseudo-Inf/Unnormal
136
+ version == 3 ? TYPE_BCM2837 : TYPE_BCM2836);
158
+ *
137
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
159
+ * With m68k, the explicit integer bit can be zero in the case of:
138
&error_abort);
160
+ * - zeros (exp == 0, mantissa == 0)
139
161
+ * - denormalized numbers (exp == 0, mantissa != 0)
162
+ * - unnormalized numbers (exp != 0, exp < 0x7FFF)
163
+ * - infinities (exp == 0x7FFF, mantissa == 0)
164
+ * - not-a-numbers (exp == 0x7FFF, mantissa != 0)
165
+ *
166
+ * For infinities and NaNs, the explicit integer bit can be either one or
167
+ * zero.
168
+ *
169
+ * The IEEE 754 standard does not define a zero integer bit. Such a number
170
+ * is an unnormalized number. Hardware does not directly support
171
+ * denormalized and unnormalized numbers, but implicitly supports them by
172
+ * trapping them as unimplemented data types, allowing efficient conversion
173
+ * in software.
174
+ *
175
+ * See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
176
+ * "1.6 FLOATING-POINT DATA TYPES"
177
+ *
178
+ * Note though that QEMU's fp emulation does directly handle both
179
+ * denormal and unnormal values, and does not trap to guest software.
180
*/
181
set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
182
- floatx80_pseudo_inf_valid,
183
+ floatx80_pseudo_inf_valid |
184
+ floatx80_pseudo_nan_valid |
185
+ floatx80_unnormal_valid,
186
&env->fp_status);
187
188
nan = floatx80_default_nan(&env->fp_status);
140
--
189
--
141
2.16.2
190
2.43.0
142
191
143
192
diff view generated by jsdifflib
1
The BCM2837 sets the Aff1 field of the MPIDR affinity values for the
1
Currently we compile-time set an 'm68k_denormal' flag in the FloatFmt
2
CPUs to 0, whereas the BCM2836 uses 0xf. Set this correctly, as it
2
for floatx80 for m68k. This controls our handling of what the Intel
3
is required for Linux to boot.
3
documentation calls a "pseudo-denormal": a value where the exponent
4
field is zero and the explicit integer bit is set.
5
6
For x86, the x87 FPU is supposed to accept a pseudo-denormal as
7
input, but never generate one on output. For m68k, these values are
8
permitted on input and may be produced on output.
9
10
Replace the flag in the FloatFmt with a flag indicating whether the
11
float format has an explicit bit (which will be true for floatx80 for
12
all targets, and false for every other float type). Then we can gate
13
the handling of these pseudo-denormals on the setting of a
14
floatx80_behaviour flag.
15
16
As far as I can see from the code we don't actually handle the
17
x86-mandated "accept on input but don't generate" behaviour, because
18
the handling in partsN(canonicalize) looked at fmt->m68k_denormal.
19
So I have added TODO comments to that effect.
20
21
This commit doesn't change any behaviour for any target.
4
22
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20180313153458.26822-8-peter.maydell@linaro.org
26
Message-id: 20250224111524.1101196-9-peter.maydell@linaro.org
27
Message-id: 20250217125055.160887-7-peter.maydell@linaro.org
9
---
28
---
10
hw/arm/bcm2836.c | 11 +++++++----
29
include/fpu/softfloat-types.h | 19 +++++++++++++++++++
11
1 file changed, 7 insertions(+), 4 deletions(-)
30
fpu/softfloat.c | 9 ++++-----
31
target/m68k/cpu.c | 3 ++-
32
fpu/softfloat-parts.c.inc | 27 ++++++++++++++++++++++++---
33
4 files changed, 49 insertions(+), 9 deletions(-)
12
34
13
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
35
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
14
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/bcm2836.c
37
--- a/include/fpu/softfloat-types.h
16
+++ b/hw/arm/bcm2836.c
38
+++ b/include/fpu/softfloat-types.h
17
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
18
40
* and using them as inputs to a float op will raise Invalid.
19
struct BCM283XInfo {
41
*/
20
const char *name;
42
floatx80_unnormal_valid = 8,
21
+ int clusterid;
43
+
22
};
44
+ /*
23
45
+ * If the exponent is 0 and the Integer bit is set, Intel call
24
static const BCM283XInfo bcm283x_socs[] = {
46
+ * this a "pseudo-denormal"; x86 supports that only on input
25
{
47
+ * (treating them as denormals by ignoring the Integer bit).
26
.name = TYPE_BCM2836,
48
+ * For m68k, the integer bit is considered validly part of the
27
+ .clusterid = 0xf,
49
+ * input value when the exponent is 0, and may be 0 or 1,
28
},
50
+ * giving extra range. They may also be generated as outputs.
29
{
51
+ * (The m68k manual actually calls these values part of the
30
.name = TYPE_BCM2837,
52
+ * normalized number range, not the denormalized number range.)
31
+ .clusterid = 0x0,
53
+ *
54
+ * By default you get the Intel behaviour where the Integer
55
+ * bit is ignored; if this is set then the Integer bit value
56
+ * is honoured, m68k-style.
57
+ *
58
+ * Either way, floatx80_invalid_encoding() will always accept
59
+ * pseudo-denormals.
60
+ */
61
+ floatx80_pseudo_denormal_valid = 16,
62
} FloatX80Behaviour;
63
64
/*
65
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/fpu/softfloat.c
68
+++ b/fpu/softfloat.c
69
@@ -XXX,XX +XXX,XX @@ typedef struct {
70
* round_mask: bits below lsb which must be rounded
71
* The following optional modifiers are available:
72
* arm_althp: handle ARM Alternative Half Precision
73
- * m68k_denormal: explicit integer bit for extended precision may be 1
74
+ * has_explicit_bit: has an explicit integer bit; this affects whether
75
+ * the float_status floatx80_behaviour handling applies
76
*/
77
typedef struct {
78
int exp_size;
79
@@ -XXX,XX +XXX,XX @@ typedef struct {
80
int frac_size;
81
int frac_shift;
82
bool arm_althp;
83
- bool m68k_denormal;
84
+ bool has_explicit_bit;
85
uint64_t round_mask;
86
} FloatFmt;
87
88
@@ -XXX,XX +XXX,XX @@ static const FloatFmt floatx80_params[3] = {
89
[floatx80_precision_d] = { FLOATX80_PARAMS(52) },
90
[floatx80_precision_x] = {
91
FLOATX80_PARAMS(64),
92
-#ifdef TARGET_M68K
93
- .m68k_denormal = true,
94
-#endif
95
+ .has_explicit_bit = true,
32
},
96
},
33
};
97
};
34
98
35
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
99
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
36
static void bcm2836_realize(DeviceState *dev, Error **errp)
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/m68k/cpu.c
102
+++ b/target/m68k/cpu.c
103
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
104
set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
105
floatx80_pseudo_inf_valid |
106
floatx80_pseudo_nan_valid |
107
- floatx80_unnormal_valid,
108
+ floatx80_unnormal_valid |
109
+ floatx80_pseudo_denormal_valid,
110
&env->fp_status);
111
112
nan = floatx80_default_nan(&env->fp_status);
113
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
114
index XXXXXXX..XXXXXXX 100644
115
--- a/fpu/softfloat-parts.c.inc
116
+++ b/fpu/softfloat-parts.c.inc
117
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
118
static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
119
const FloatFmt *fmt)
37
{
120
{
38
BCM283XState *s = BCM283X(dev);
121
+ /*
39
+ BCM283XClass *bc = BCM283X_GET_CLASS(dev);
122
+ * It's target-dependent how to handle the case of exponent 0
40
+ const BCM283XInfo *info = bc->info;
123
+ * and Integer bit set. Intel calls these "pseudodenormals",
41
Object *obj;
124
+ * and treats them as if the integer bit was 0, and never
42
Error *err = NULL;
125
+ * produces them on output. This is the default behaviour for QEMU.
43
int n;
126
+ * For m68k, the integer bit is considered validly part of the
44
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
127
+ * input value when the exponent is 0, and may be 0 or 1,
45
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));
128
+ * giving extra range. They may also be generated as outputs.
46
129
+ * (The m68k manual actually calls these values part of the
47
for (n = 0; n < BCM283X_NCPUS; n++) {
130
+ * normalized number range, not the denormalized number range,
48
- /* Mirror bcm2836, which has clusterid set to 0xf
131
+ * but that distinction is not important for us, because
49
- * TODO: this should be converted to a property of ARM_CPU
132
+ * m68k doesn't care about the input_denormal_used status flag.)
50
- */
133
+ * floatx80_pseudo_denormal_valid selects the m68k behaviour,
51
- s->cpus[n].mp_affinity = 0xF00 | n;
134
+ * which changes both how we canonicalize such a value and
52
+ /* TODO: this should be converted to a property of ARM_CPU */
135
+ * how we uncanonicalize results.
53
+ s->cpus[n].mp_affinity = (info->clusterid << 8) | n;
136
+ */
54
137
+ bool has_pseudo_denormals = fmt->has_explicit_bit &&
55
/* set periphbase/CBAR value for CPU-local registers */
138
+ (status->floatx80_behaviour & floatx80_pseudo_denormal_valid);
56
object_property_set_int(OBJECT(&s->cpus[n]),
139
+
140
if (unlikely(p->exp == 0)) {
141
if (likely(frac_eqz(p))) {
142
p->cls = float_class_zero;
143
@@ -XXX,XX +XXX,XX @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
144
int shift = frac_normalize(p);
145
p->cls = float_class_denormal;
146
p->exp = fmt->frac_shift - fmt->exp_bias
147
- - shift + !fmt->m68k_denormal;
148
+ - shift + !has_pseudo_denormals;
149
}
150
} else if (likely(p->exp < fmt->exp_max) || fmt->arm_althp) {
151
p->cls = float_class_normal;
152
@@ -XXX,XX +XXX,XX @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
153
frac_clear(p);
154
} else {
155
bool is_tiny = s->tininess_before_rounding || exp < 0;
156
+ bool has_pseudo_denormals = fmt->has_explicit_bit &&
157
+ (s->floatx80_behaviour & floatx80_pseudo_denormal_valid);
158
159
if (!is_tiny) {
160
FloatPartsN discard;
161
is_tiny = !frac_addi(&discard, p, inc);
162
}
163
164
- frac_shrjam(p, !fmt->m68k_denormal - exp);
165
+ frac_shrjam(p, !has_pseudo_denormals - exp);
166
167
if (p->frac_lo & round_mask) {
168
/* Need to recompute round-to-even/round-to-odd. */
169
@@ -XXX,XX +XXX,XX @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
170
p->frac_lo &= ~round_mask;
171
}
172
173
- exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) && !fmt->m68k_denormal;
174
+ exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) && !has_pseudo_denormals;
175
frac_shr(p, frac_shift);
176
177
if (is_tiny) {
57
--
178
--
58
2.16.2
179
2.43.0
59
180
60
181
diff view generated by jsdifflib
1
Add some assertions that if we're about to boot an AArch64 kernel,
1
Currently we have a compile-time shortcut where we
2
the board code has not mistakenly set either secure_boot or
2
return false from no_signaling_nans() on everything except
3
secure_board_setup. It doesn't make sense to set secure_boot,
3
Xtensa, because we know that's the only target that
4
because all AArch64 kernels must be booted in non-secure mode.
4
might ever set status->no_signaling_nans.
5
5
6
It might in theory make sense to set secure_board_setup, but
6
Remove the ifdef, so we always look at the status flag;
7
we don't currently support that, because only the AArch32
7
this has no behavioural change, but will be necessary
8
bootloader[] code calls this hook; bootloader_aarch64[] does not.
8
if we want to build softfloat once for all targets.
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
9
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Message-id: 20180313153458.26822-3-peter.maydell@linaro.org
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20250224111524.1101196-10-peter.maydell@linaro.org
14
Message-id: 20250217125055.160887-8-peter.maydell@linaro.org
16
---
15
---
17
hw/arm/boot.c | 7 +++++++
16
fpu/softfloat-specialize.c.inc | 4 ----
18
1 file changed, 7 insertions(+)
17
1 file changed, 4 deletions(-)
19
18
20
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
19
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/boot.c
21
--- a/fpu/softfloat-specialize.c.inc
23
+++ b/hw/arm/boot.c
22
+++ b/fpu/softfloat-specialize.c.inc
24
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
23
@@ -XXX,XX +XXX,XX @@ this code that are retained.
25
} else {
24
*/
26
env->pstate = PSTATE_MODE_EL1h;
25
static inline bool no_signaling_nans(float_status *status)
27
}
26
{
28
+ /* AArch64 kernels never boot in secure mode */
27
-#if defined(TARGET_XTENSA)
29
+ assert(!info->secure_boot);
28
return status->no_signaling_nans;
30
+ /* This hook is only supported for AArch32 currently:
29
-#else
31
+ * bootloader_aarch64[] will not call the hook, and
30
- return false;
32
+ * the code above has already dropped us into EL2 or EL1.
31
-#endif
33
+ */
32
}
34
+ assert(!info->secure_board_setup);
33
35
}
34
/* Define how the architecture discriminates signaling NaNs.
36
37
/* Set to non-secure if not a secure boot */
38
--
35
--
39
2.16.2
36
2.43.0
40
37
41
38
diff view generated by jsdifflib
1
Now we have separate types for BCM2386 and BCM2387, we might as well
1
Currently we have a compile-time shortcut where we return a hardcode
2
just hard-code the CPU type they use rather than having it passed
2
value from snan_bit_is_one() on everything except MIPS, because we
3
through as an object property. This then lets us put the initialization
3
know that's the only target that needs to change
4
of the CPU object in init rather than realize.
4
status->no_signaling_nans at runtime.
5
5
6
Note that this change means that it's no longer possible on
6
Remove the ifdef, so we always look at the status flag. This means
7
the command line to use -cpu to ask for a different kind of
7
we must update the two targets (HPPA and SH4) that were previously
8
CPU than the SoC supports. This was never a supported thing to
8
hardcoded to return true so that they set the status flag correctly.
9
do anyway; we were just not sanity-checking the command line.
10
9
11
This does require us to only build the bcm2837 object on
10
This has no behavioural change, but will be necessary if we want to
12
TARGET_AARCH64 configs, since otherwise it won't instantiate
11
build softfloat once for all targets.
13
due to the missing cortex-a53 device and "make check" will fail.
14
12
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20180313153458.26822-9-peter.maydell@linaro.org
16
Message-id: 20250224111524.1101196-11-peter.maydell@linaro.org
17
Message-id: 20250217125055.160887-9-peter.maydell@linaro.org
19
---
18
---
20
hw/arm/bcm2836.c | 24 +++++++++++++++---------
19
target/hppa/fpu_helper.c | 1 +
21
hw/arm/raspi.c | 2 --
20
target/sh4/cpu.c | 1 +
22
2 files changed, 15 insertions(+), 11 deletions(-)
21
fpu/softfloat-specialize.c.inc | 7 -------
22
3 files changed, 2 insertions(+), 7 deletions(-)
23
23
24
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
24
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
25
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/bcm2836.c
26
--- a/target/hppa/fpu_helper.c
27
+++ b/hw/arm/bcm2836.c
27
+++ b/target/hppa/fpu_helper.c
28
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
29
29
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
30
struct BCM283XInfo {
30
/* Default NaN: sign bit clear, msb-1 frac bit set */
31
const char *name;
31
set_float_default_nan_pattern(0b00100000, &env->fp_status);
32
+ const char *cpu_type;
32
+ set_snan_bit_is_one(true, &env->fp_status);
33
int clusterid;
33
/*
34
};
34
* "PA-RISC 2.0 Architecture" says it is IMPDEF whether the flushing
35
35
* enabled by FPSR.D happens before or after rounding. We pick "before"
36
static const BCM283XInfo bcm283x_socs[] = {
36
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
37
{
37
index XXXXXXX..XXXXXXX 100644
38
.name = TYPE_BCM2836,
38
--- a/target/sh4/cpu.c
39
+ .cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"),
39
+++ b/target/sh4/cpu.c
40
.clusterid = 0xf,
40
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
41
},
41
set_flush_to_zero(1, &env->fp_status);
42
+#ifdef TARGET_AARCH64
42
#endif
43
{
43
set_default_nan_mode(1, &env->fp_status);
44
.name = TYPE_BCM2837,
44
+ set_snan_bit_is_one(true, &env->fp_status);
45
+ .cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
45
/* sign bit clear, set all frac bits other than msb */
46
.clusterid = 0x0,
46
set_float_default_nan_pattern(0b00111111, &env->fp_status);
47
},
47
/*
48
+#endif
48
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
49
};
49
index XXXXXXX..XXXXXXX 100644
50
50
--- a/fpu/softfloat-specialize.c.inc
51
static void bcm2836_init(Object *obj)
51
+++ b/fpu/softfloat-specialize.c.inc
52
@@ -XXX,XX +XXX,XX @@ static inline bool no_signaling_nans(float_status *status)
53
* In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008
54
* the msb must be zero. MIPS is (so far) unique in supporting both the
55
* 2008 revision and backward compatibility with their original choice.
56
- * Thus for MIPS we must make the choice at runtime.
57
*/
58
static inline bool snan_bit_is_one(float_status *status)
52
{
59
{
53
BCM283XState *s = BCM283X(obj);
60
-#if defined(TARGET_MIPS)
54
+ BCM283XClass *bc = BCM283X_GET_CLASS(obj);
61
return status->snan_bit_is_one;
55
+ const BCM283XInfo *info = bc->info;
62
-#elif defined(TARGET_HPPA) || defined(TARGET_SH4)
56
+ int n;
63
- return 1;
57
+
64
-#else
58
+ for (n = 0; n < BCM283X_NCPUS; n++) {
65
- return 0;
59
+ object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
66
-#endif
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
}
67
}
84
68
85
static Property bcm2836_props[] = {
69
/*----------------------------------------------------------------------------
86
- DEFINE_PROP_STRING("cpu-type", BCM283XState, cpu_type),
87
DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
88
BCM283X_NCPUS),
89
DEFINE_PROP_END_OF_LIST()
90
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/hw/arm/raspi.c
93
+++ b/hw/arm/raspi.c
94
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
95
/* Setup the SOC */
96
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
97
&error_abort);
98
- object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type",
99
- &error_abort);
100
object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
101
&error_abort);
102
int board_rev = version == 3 ? 0xa02082 : 0xa21041;
103
--
70
--
104
2.16.2
71
2.43.0
105
72
106
73
diff view generated by jsdifflib
New patch
1
We happen to know that for the PPC target the FP status flags (and in
2
particular float_flag_inexact) will always be cleared before a
3
floating point operation, and so can_use_fpu() will always return
4
false. So we speed things up a little by forcing QEMU_NO_HARDFLOAT
5
to true on that target.
1
6
7
We would like to build softfloat once for all targets; that means
8
removing target-specific ifdefs. Remove the check for TARGET_PPC;
9
this won't change behaviour because can_use_fpu() will see that
10
float_flag_inexact is clear and take the softfloat path anyway.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20250224111524.1101196-12-peter.maydell@linaro.org
15
Message-id: 20250217125055.160887-10-peter.maydell@linaro.org
16
---
17
fpu/softfloat.c | 2 --
18
1 file changed, 2 deletions(-)
19
20
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/fpu/softfloat.c
23
+++ b/fpu/softfloat.c
24
@@ -XXX,XX +XXX,XX @@ GEN_INPUT_FLUSH3(float64_input_flush3, float64)
25
* the use of hardfloat, since hardfloat relies on the inexact flag being
26
* already set.
27
*/
28
-#if defined(TARGET_PPC) || defined(__FAST_MATH__)
29
# if defined(__FAST_MATH__)
30
# warning disabling hardfloat due to -ffast-math: hardfloat requires an exact \
31
IEEE implementation
32
-# endif
33
# define QEMU_NO_HARDFLOAT 1
34
# define QEMU_SOFTFLOAT_ATTR QEMU_FLATTEN
35
#else
36
--
37
2.43.0
diff view generated by jsdifflib
1
For the rpi1 and 2 we want to boot the Linux kernel via some
1
Now we have removed all the target-specifics from the softfloat code,
2
custom setup code that makes sure that the SMC instruction
2
we can switch to building it once for the whole system rather than
3
acts as a no-op, because it's used for cache maintenance.
3
once per target.
4
The rpi3 boots AArch64 kernels, which don't need SMC for
5
cache maintenance and always expect to be booted non-secure.
6
Don't fill in the aarch32-specific parts of the binfo struct.
7
4
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
6
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180313153458.26822-2-peter.maydell@linaro.org
8
Message-id: 20250224111524.1101196-13-peter.maydell@linaro.org
9
Message-id: 20250217125055.160887-11-peter.maydell@linaro.org
12
---
10
---
13
hw/arm/raspi.c | 17 +++++++++++++----
11
fpu/softfloat.c | 3 ---
14
1 file changed, 13 insertions(+), 4 deletions(-)
12
fpu/meson.build | 2 +-
13
2 files changed, 1 insertion(+), 4 deletions(-)
15
14
16
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/raspi.c
17
--- a/fpu/softfloat.c
19
+++ b/hw/arm/raspi.c
18
+++ b/fpu/softfloat.c
20
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
19
@@ -XXX,XX +XXX,XX @@ this code that are retained.
21
binfo.board_id = raspi_boardid[version];
20
* version 2 or later. See the COPYING file in the top-level directory.
22
binfo.ram_size = ram_size;
21
*/
23
binfo.nb_cpus = smp_cpus;
22
24
- binfo.board_setup_addr = BOARDSETUP_ADDR;
23
-/* softfloat (and in particular the code in softfloat-specialize.h) is
25
- binfo.write_board_setup = write_board_setup;
24
- * target-dependent and needs the TARGET_* macros.
26
- binfo.secure_board_setup = true;
25
- */
27
- binfo.secure_boot = true;
26
#include "qemu/osdep.h"
28
+
27
#include <math.h>
29
+ if (version <= 2) {
28
#include "qemu/bitops.h"
30
+ /* The rpi1 and 2 require some custom setup code to run in Secure
29
diff --git a/fpu/meson.build b/fpu/meson.build
31
+ * mode before booting a kernel (to set up the SMC vectors so
30
index XXXXXXX..XXXXXXX 100644
32
+ * that we get a no-op SMC; this is used by Linux to call the
31
--- a/fpu/meson.build
33
+ * firmware for some cache maintenance operations.
32
+++ b/fpu/meson.build
34
+ * The rpi3 doesn't need this.
33
@@ -1 +1 @@
35
+ */
34
-specific_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
36
+ binfo.board_setup_addr = BOARDSETUP_ADDR;
35
+common_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
37
+ binfo.write_board_setup = write_board_setup;
38
+ binfo.secure_board_setup = true;
39
+ binfo.secure_boot = true;
40
+ }
41
42
/* Pi2 and Pi3 requires SMP setup */
43
if (version >= 2) {
44
--
36
--
45
2.16.2
37
2.43.0
46
38
47
39
diff view generated by jsdifflib
New patch
1
Most of the target/arm/vfp_helper.c file is purely TCG helper code,
2
guarded by #ifdef CONFIG_TCG. Move this into a new file in
3
target/arm/tcg/.
1
4
5
This leaves only the code relating to getting and setting the
6
FPCR/FPSR/FPSCR in the original file. (Some of this also is
7
TCG-only, but that needs more careful disentangling.)
8
9
Having two vfp_helper.c files might seem a bit confusing,
10
but once we've finished moving all the helper code out
11
of the old file we are going to rename it to vfp_fpscr.c.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20250221190957.811948-2-peter.maydell@linaro.org
16
---
17
target/arm/{ => tcg}/vfp_helper.c | 399 +----------
18
target/arm/vfp_helper.c | 1109 -----------------------------
19
target/arm/tcg/meson.build | 1 +
20
3 files changed, 4 insertions(+), 1505 deletions(-)
21
copy target/arm/{ => tcg}/vfp_helper.c (71%)
22
23
diff --git a/target/arm/vfp_helper.c b/target/arm/tcg/vfp_helper.c
24
similarity index 71%
25
copy from target/arm/vfp_helper.c
26
copy to target/arm/tcg/vfp_helper.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/vfp_helper.c
29
+++ b/target/arm/tcg/vfp_helper.c
30
@@ -XXX,XX +XXX,XX @@
31
#include "internals.h"
32
#include "cpu-features.h"
33
#include "fpu/softfloat.h"
34
-#ifdef CONFIG_TCG
35
#include "qemu/log.h"
36
-#endif
37
-
38
-/* VFP support. We follow the convention used for VFP instructions:
39
- Single precision routines have a "s" suffix, double precision a
40
- "d" suffix. */
41
42
/*
43
- * Set the float_status behaviour to match the Arm defaults:
44
- * * tininess-before-rounding
45
- * * 2-input NaN propagation prefers SNaN over QNaN, and then
46
- * operand A over operand B (see FPProcessNaNs() pseudocode)
47
- * * 3-input NaN propagation prefers SNaN over QNaN, and then
48
- * operand C over A over B (see FPProcessNaNs3() pseudocode,
49
- * but note that for QEMU muladd is a * b + c, whereas for
50
- * the pseudocode function the arguments are in the order c, a, b.
51
- * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
52
- * and the input NaN if it is signalling
53
- * * Default NaN has sign bit clear, msb frac bit set
54
+ * VFP support. We follow the convention used for VFP instructions:
55
+ * Single precision routines have a "s" suffix, double precision a
56
+ * "d" suffix.
57
*/
58
-void arm_set_default_fp_behaviours(float_status *s)
59
-{
60
- set_float_detect_tininess(float_tininess_before_rounding, s);
61
- set_float_ftz_detection(float_ftz_before_rounding, s);
62
- set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
63
- set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
64
- set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
65
- set_float_default_nan_pattern(0b01000000, s);
66
-}
67
-
68
-/*
69
- * Set the float_status behaviour to match the FEAT_AFP
70
- * FPCR.AH=1 requirements:
71
- * * tininess-after-rounding
72
- * * 2-input NaN propagation prefers the first NaN
73
- * * 3-input NaN propagation prefers a over b over c
74
- * * 0 * Inf + NaN always returns the input NaN and doesn't
75
- * set Invalid for a QNaN
76
- * * default NaN has sign bit set, msb frac bit set
77
- */
78
-void arm_set_ah_fp_behaviours(float_status *s)
79
-{
80
- set_float_detect_tininess(float_tininess_after_rounding, s);
81
- set_float_ftz_detection(float_ftz_after_rounding, s);
82
- set_float_2nan_prop_rule(float_2nan_prop_ab, s);
83
- set_float_3nan_prop_rule(float_3nan_prop_abc, s);
84
- set_float_infzeronan_rule(float_infzeronan_dnan_never |
85
- float_infzeronan_suppress_invalid, s);
86
- set_float_default_nan_pattern(0b11000000, s);
87
-}
88
-
89
-#ifdef CONFIG_TCG
90
-
91
-/* Convert host exception flags to vfp form. */
92
-static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
93
-{
94
- uint32_t target_bits = 0;
95
-
96
- if (host_bits & float_flag_invalid) {
97
- target_bits |= FPSR_IOC;
98
- }
99
- if (host_bits & float_flag_divbyzero) {
100
- target_bits |= FPSR_DZC;
101
- }
102
- if (host_bits & float_flag_overflow) {
103
- target_bits |= FPSR_OFC;
104
- }
105
- if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
106
- target_bits |= FPSR_UFC;
107
- }
108
- if (host_bits & float_flag_inexact) {
109
- target_bits |= FPSR_IXC;
110
- }
111
- if (host_bits & float_flag_input_denormal_flushed) {
112
- target_bits |= FPSR_IDC;
113
- }
114
- /*
115
- * With FPCR.AH, IDC is set when an input denormal is used,
116
- * and flushing an output denormal to zero sets both IXC and UFC.
117
- */
118
- if (ah && (host_bits & float_flag_input_denormal_used)) {
119
- target_bits |= FPSR_IDC;
120
- }
121
- if (ah && (host_bits & float_flag_output_denormal_flushed)) {
122
- target_bits |= FPSR_IXC;
123
- }
124
- return target_bits;
125
-}
126
-
127
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
128
-{
129
- uint32_t a32_flags = 0, a64_flags = 0;
130
-
131
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
132
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
133
- /* FZ16 does not generate an input denormal exception. */
134
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
135
- & ~float_flag_input_denormal_flushed);
136
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
137
- & ~float_flag_input_denormal_flushed);
138
-
139
- a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
140
- a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
141
- & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
142
- /*
143
- * We do not merge in flags from FPST_AH or FPST_AH_F16, because
144
- * they are used for insns that must not set the cumulative exception bits.
145
- */
146
-
147
- /*
148
- * Flushing an input denormal *only* because FPCR.FIZ == 1 does
149
- * not set FPSR.IDC; if FPCR.FZ is also set then this takes
150
- * precedence and IDC is set (see the FPUnpackBase pseudocode).
151
- * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
152
- * We only do this for the a64 flags because FIZ has no effect
153
- * on AArch32 even if it is set.
154
- */
155
- if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
156
- a64_flags &= ~float_flag_input_denormal_flushed;
157
- }
158
- return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
159
- vfp_exceptbits_from_host(a32_flags, false);
160
-}
161
-
162
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
163
-{
164
- /*
165
- * Clear out all the exception-flag information in the float_status
166
- * values. The caller should have arranged for env->vfp.fpsr to
167
- * be the architecturally up-to-date exception flag information first.
168
- */
169
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
170
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
171
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
172
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
173
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
174
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
175
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
176
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
177
-}
178
-
179
-static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
180
-{
181
- /*
182
- * Synchronize any pending exception-flag information in the
183
- * float_status values into env->vfp.fpsr, and then clear out
184
- * the float_status data.
185
- */
186
- env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
187
- vfp_clear_float_status_exc_flags(env);
188
-}
189
-
190
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
191
-{
192
- uint64_t changed = env->vfp.fpcr;
193
-
194
- changed ^= val;
195
- changed &= mask;
196
- if (changed & (3 << 22)) {
197
- int i = (val >> 22) & 3;
198
- switch (i) {
199
- case FPROUNDING_TIEEVEN:
200
- i = float_round_nearest_even;
201
- break;
202
- case FPROUNDING_POSINF:
203
- i = float_round_up;
204
- break;
205
- case FPROUNDING_NEGINF:
206
- i = float_round_down;
207
- break;
208
- case FPROUNDING_ZERO:
209
- i = float_round_to_zero;
210
- break;
211
- }
212
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
213
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
214
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
215
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
216
- }
217
- if (changed & FPCR_FZ16) {
218
- bool ftz_enabled = val & FPCR_FZ16;
219
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
220
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
221
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
222
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
223
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
224
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
225
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
226
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
227
- }
228
- if (changed & FPCR_FZ) {
229
- bool ftz_enabled = val & FPCR_FZ;
230
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
231
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
232
- /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
233
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
234
- }
235
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
236
- /*
237
- * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
238
- * both FPCR.AH = 0 and FPCR.FZ = 1.
239
- */
240
- bool fitz_enabled = (val & FPCR_FIZ) ||
241
- (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
242
- set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
243
- }
244
- if (changed & FPCR_DN) {
245
- bool dnan_enabled = val & FPCR_DN;
246
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
247
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
248
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
249
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
250
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
251
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
252
- }
253
- if (changed & FPCR_AH) {
254
- bool ah_enabled = val & FPCR_AH;
255
-
256
- if (ah_enabled) {
257
- /* Change behaviours for A64 FP operations */
258
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
259
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
260
- } else {
261
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
262
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
263
- }
264
- }
265
- /*
266
- * If any bits changed that we look at in vfp_get_fpsr_from_host(),
267
- * we must sync the float_status flags into vfp.fpsr now (under the
268
- * old regime) before we update vfp.fpcr.
269
- */
270
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
271
- vfp_sync_and_clear_float_status_exc_flags(env);
272
- }
273
-}
274
-
275
-#else
276
-
277
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
278
-{
279
- return 0;
280
-}
281
-
282
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
283
-{
284
-}
285
-
286
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
287
-{
288
-}
289
-
290
-#endif
291
-
292
-uint32_t vfp_get_fpcr(CPUARMState *env)
293
-{
294
- uint32_t fpcr = env->vfp.fpcr
295
- | (env->vfp.vec_len << 16)
296
- | (env->vfp.vec_stride << 20);
297
-
298
- /*
299
- * M-profile LTPSIZE is the same bits [18:16] as A-profile Len; whichever
300
- * of the two is not applicable to this CPU will always be zero.
301
- */
302
- fpcr |= env->v7m.ltpsize << 16;
303
-
304
- return fpcr;
305
-}
306
-
307
-uint32_t vfp_get_fpsr(CPUARMState *env)
308
-{
309
- uint32_t fpsr = env->vfp.fpsr;
310
- uint32_t i;
311
-
312
- fpsr |= vfp_get_fpsr_from_host(env);
313
-
314
- i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
315
- fpsr |= i ? FPSR_QC : 0;
316
- return fpsr;
317
-}
318
-
319
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
320
-{
321
- return (vfp_get_fpcr(env) & FPSCR_FPCR_MASK) |
322
- (vfp_get_fpsr(env) & FPSCR_FPSR_MASK);
323
-}
324
-
325
-uint32_t vfp_get_fpscr(CPUARMState *env)
326
-{
327
- return HELPER(vfp_get_fpscr)(env);
328
-}
329
-
330
-void vfp_set_fpsr(CPUARMState *env, uint32_t val)
331
-{
332
- ARMCPU *cpu = env_archcpu(env);
333
-
334
- if (arm_feature(env, ARM_FEATURE_NEON) ||
335
- cpu_isar_feature(aa32_mve, cpu)) {
336
- /*
337
- * The bit we set within vfp.qc[] is arbitrary; the array as a
338
- * whole being zero/non-zero is what counts.
339
- */
340
- env->vfp.qc[0] = val & FPSR_QC;
341
- env->vfp.qc[1] = 0;
342
- env->vfp.qc[2] = 0;
343
- env->vfp.qc[3] = 0;
344
- }
345
-
346
- /*
347
- * NZCV lives only in env->vfp.fpsr. The cumulative exception flags
348
- * IOC|DZC|OFC|UFC|IXC|IDC also live in env->vfp.fpsr, with possible
349
- * extra pending exception information that hasn't yet been folded in
350
- * living in the float_status values (for TCG).
351
- * Since this FPSR write gives us the up to date values of the exception
352
- * flags, we want to store into vfp.fpsr the NZCV and CEXC bits, zeroing
353
- * anything else. We also need to clear out the float_status exception
354
- * information so that the next vfp_get_fpsr does not fold in stale data.
355
- */
356
- val &= FPSR_NZCV_MASK | FPSR_CEXC_MASK;
357
- env->vfp.fpsr = val;
358
- vfp_clear_float_status_exc_flags(env);
359
-}
360
-
361
-static void vfp_set_fpcr_masked(CPUARMState *env, uint32_t val, uint32_t mask)
362
-{
363
- /*
364
- * We only set FPCR bits defined by mask, and leave the others alone.
365
- * We assume the mask is sensible (e.g. doesn't try to set only
366
- * part of a field)
367
- */
368
- ARMCPU *cpu = env_archcpu(env);
369
-
370
- /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
371
- if (!cpu_isar_feature(any_fp16, cpu)) {
372
- val &= ~FPCR_FZ16;
373
- }
374
- if (!cpu_isar_feature(aa64_afp, cpu)) {
375
- val &= ~(FPCR_FIZ | FPCR_AH | FPCR_NEP);
376
- }
377
-
378
- if (!cpu_isar_feature(aa64_ebf16, cpu)) {
379
- val &= ~FPCR_EBF;
380
- }
381
-
382
- vfp_set_fpcr_to_host(env, val, mask);
383
-
384
- if (mask & (FPCR_LEN_MASK | FPCR_STRIDE_MASK)) {
385
- if (!arm_feature(env, ARM_FEATURE_M)) {
386
- /*
387
- * Short-vector length and stride; on M-profile these bits
388
- * are used for different purposes.
389
- * We can't make this conditional be "if MVFR0.FPShVec != 0",
390
- * because in v7A no-short-vector-support cores still had to
391
- * allow Stride/Len to be written with the only effect that
392
- * some insns are required to UNDEF if the guest sets them.
393
- */
394
- env->vfp.vec_len = extract32(val, 16, 3);
395
- env->vfp.vec_stride = extract32(val, 20, 2);
396
- } else if (cpu_isar_feature(aa32_mve, cpu)) {
397
- env->v7m.ltpsize = extract32(val, FPCR_LTPSIZE_SHIFT,
398
- FPCR_LTPSIZE_LENGTH);
399
- }
400
- }
401
-
402
- /*
403
- * We don't implement trapped exception handling, so the
404
- * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
405
- *
406
- * The FPCR bits we keep in vfp.fpcr are AHP, DN, FZ, RMode, EBF, FZ16,
407
- * FIZ, AH, and NEP.
408
- * Len, Stride and LTPSIZE we just handled. Store those bits
409
- * there, and zero any of the other FPCR bits and the RES0 and RAZ/WI
410
- * bits.
411
- */
412
- val &= FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK | FPCR_FZ16 |
413
- FPCR_EBF | FPCR_FIZ | FPCR_AH | FPCR_NEP;
414
- env->vfp.fpcr &= ~mask;
415
- env->vfp.fpcr |= val;
416
-}
417
-
418
-void vfp_set_fpcr(CPUARMState *env, uint32_t val)
419
-{
420
- vfp_set_fpcr_masked(env, val, MAKE_64BIT_MASK(0, 32));
421
-}
422
-
423
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
424
-{
425
- vfp_set_fpcr_masked(env, val, FPSCR_FPCR_MASK);
426
- vfp_set_fpsr(env, val & FPSCR_FPSR_MASK);
427
-}
428
-
429
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
430
-{
431
- HELPER(vfp_set_fpscr)(env, val);
432
-}
433
-
434
-#ifdef CONFIG_TCG
435
436
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
437
438
@@ -XXX,XX +XXX,XX @@ void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
439
440
raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
441
}
442
-
443
-#endif
444
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
445
index XXXXXXX..XXXXXXX 100644
446
--- a/target/arm/vfp_helper.c
447
+++ b/target/arm/vfp_helper.c
448
@@ -XXX,XX +XXX,XX @@
449
#include "internals.h"
450
#include "cpu-features.h"
451
#include "fpu/softfloat.h"
452
-#ifdef CONFIG_TCG
453
-#include "qemu/log.h"
454
-#endif
455
-
456
-/* VFP support. We follow the convention used for VFP instructions:
457
- Single precision routines have a "s" suffix, double precision a
458
- "d" suffix. */
459
460
/*
461
* Set the float_status behaviour to match the Arm defaults:
462
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val)
463
{
464
HELPER(vfp_set_fpscr)(env, val);
465
}
466
-
467
-#ifdef CONFIG_TCG
468
-
469
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
470
-
471
-#define VFP_BINOP(name) \
472
-dh_ctype_f16 VFP_HELPER(name, h)(dh_ctype_f16 a, dh_ctype_f16 b, float_status *fpst) \
473
-{ \
474
- return float16_ ## name(a, b, fpst); \
475
-} \
476
-float32 VFP_HELPER(name, s)(float32 a, float32 b, float_status *fpst) \
477
-{ \
478
- return float32_ ## name(a, b, fpst); \
479
-} \
480
-float64 VFP_HELPER(name, d)(float64 a, float64 b, float_status *fpst) \
481
-{ \
482
- return float64_ ## name(a, b, fpst); \
483
-}
484
-VFP_BINOP(add)
485
-VFP_BINOP(sub)
486
-VFP_BINOP(mul)
487
-VFP_BINOP(div)
488
-VFP_BINOP(min)
489
-VFP_BINOP(max)
490
-VFP_BINOP(minnum)
491
-VFP_BINOP(maxnum)
492
-#undef VFP_BINOP
493
-
494
-dh_ctype_f16 VFP_HELPER(sqrt, h)(dh_ctype_f16 a, float_status *fpst)
495
-{
496
- return float16_sqrt(a, fpst);
497
-}
498
-
499
-float32 VFP_HELPER(sqrt, s)(float32 a, float_status *fpst)
500
-{
501
- return float32_sqrt(a, fpst);
502
-}
503
-
504
-float64 VFP_HELPER(sqrt, d)(float64 a, float_status *fpst)
505
-{
506
- return float64_sqrt(a, fpst);
507
-}
508
-
509
-static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp)
510
-{
511
- uint32_t flags;
512
- switch (cmp) {
513
- case float_relation_equal:
514
- flags = 0x6;
515
- break;
516
- case float_relation_less:
517
- flags = 0x8;
518
- break;
519
- case float_relation_greater:
520
- flags = 0x2;
521
- break;
522
- case float_relation_unordered:
523
- flags = 0x3;
524
- break;
525
- default:
526
- g_assert_not_reached();
527
- }
528
- env->vfp.fpsr = deposit64(env->vfp.fpsr, 28, 4, flags); /* NZCV */
529
-}
530
-
531
-/* XXX: check quiet/signaling case */
532
-#define DO_VFP_cmp(P, FLOATTYPE, ARGTYPE, FPST) \
533
-void VFP_HELPER(cmp, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
534
-{ \
535
- softfloat_to_vfp_compare(env, \
536
- FLOATTYPE ## _compare_quiet(a, b, &env->vfp.fp_status[FPST])); \
537
-} \
538
-void VFP_HELPER(cmpe, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
539
-{ \
540
- softfloat_to_vfp_compare(env, \
541
- FLOATTYPE ## _compare(a, b, &env->vfp.fp_status[FPST])); \
542
-}
543
-DO_VFP_cmp(h, float16, dh_ctype_f16, FPST_A32_F16)
544
-DO_VFP_cmp(s, float32, float32, FPST_A32)
545
-DO_VFP_cmp(d, float64, float64, FPST_A32)
546
-#undef DO_VFP_cmp
547
-
548
-/* Integer to float and float to integer conversions */
549
-
550
-#define CONV_ITOF(name, ftype, fsz, sign) \
551
-ftype HELPER(name)(uint32_t x, float_status *fpst) \
552
-{ \
553
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
554
-}
555
-
556
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
557
-sign##int32_t HELPER(name)(ftype x, float_status *fpst) \
558
-{ \
559
- if (float##fsz##_is_any_nan(x)) { \
560
- float_raise(float_flag_invalid, fpst); \
561
- return 0; \
562
- } \
563
- return float##fsz##_to_##sign##int32##round(x, fpst); \
564
-}
565
-
566
-#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
567
- CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
568
- CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
569
- CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
570
-
571
-FLOAT_CONVS(si, h, uint32_t, 16, )
572
-FLOAT_CONVS(si, s, float32, 32, )
573
-FLOAT_CONVS(si, d, float64, 64, )
574
-FLOAT_CONVS(ui, h, uint32_t, 16, u)
575
-FLOAT_CONVS(ui, s, float32, 32, u)
576
-FLOAT_CONVS(ui, d, float64, 64, u)
577
-
578
-#undef CONV_ITOF
579
-#undef CONV_FTOI
580
-#undef FLOAT_CONVS
581
-
582
-/* floating point conversion */
583
-float64 VFP_HELPER(fcvtd, s)(float32 x, float_status *status)
584
-{
585
- return float32_to_float64(x, status);
586
-}
587
-
588
-float32 VFP_HELPER(fcvts, d)(float64 x, float_status *status)
589
-{
590
- return float64_to_float32(x, status);
591
-}
592
-
593
-uint32_t HELPER(bfcvt)(float32 x, float_status *status)
594
-{
595
- return float32_to_bfloat16(x, status);
596
-}
597
-
598
-uint32_t HELPER(bfcvt_pair)(uint64_t pair, float_status *status)
599
-{
600
- bfloat16 lo = float32_to_bfloat16(extract64(pair, 0, 32), status);
601
- bfloat16 hi = float32_to_bfloat16(extract64(pair, 32, 32), status);
602
- return deposit32(lo, 16, 16, hi);
603
-}
604
-
605
-/*
606
- * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
607
- * must always round-to-nearest; the AArch64 ones honour the FPSCR
608
- * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
609
- * round-to-nearest so either helper will work.) AArch32 float-to-fix
610
- * must round-to-zero.
611
- */
612
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
613
-ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
614
- float_status *fpst) \
615
-{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpst); }
616
-
617
-#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
618
- ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
619
- uint32_t shift, \
620
- float_status *fpst) \
621
- { \
622
- ftype ret; \
623
- FloatRoundMode oldmode = fpst->float_rounding_mode; \
624
- fpst->float_rounding_mode = float_round_nearest_even; \
625
- ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpst); \
626
- fpst->float_rounding_mode = oldmode; \
627
- return ret; \
628
- }
629
-
630
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
631
-uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
632
- float_status *fpst) \
633
-{ \
634
- if (unlikely(float##fsz##_is_any_nan(x))) { \
635
- float_raise(float_flag_invalid, fpst); \
636
- return 0; \
637
- } \
638
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
639
-}
640
-
641
-#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
642
-VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
643
-VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
644
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
645
- float_round_to_zero, _round_to_zero) \
646
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
647
- get_float_rounding_mode(fpst), )
648
-
649
-#define VFP_CONV_FIX_A64(name, p, fsz, ftype, isz, itype) \
650
-VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
651
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
652
- get_float_rounding_mode(fpst), )
653
-
654
-VFP_CONV_FIX(sh, d, 64, float64, 64, int16)
655
-VFP_CONV_FIX(sl, d, 64, float64, 64, int32)
656
-VFP_CONV_FIX_A64(sq, d, 64, float64, 64, int64)
657
-VFP_CONV_FIX(uh, d, 64, float64, 64, uint16)
658
-VFP_CONV_FIX(ul, d, 64, float64, 64, uint32)
659
-VFP_CONV_FIX_A64(uq, d, 64, float64, 64, uint64)
660
-VFP_CONV_FIX(sh, s, 32, float32, 32, int16)
661
-VFP_CONV_FIX(sl, s, 32, float32, 32, int32)
662
-VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64)
663
-VFP_CONV_FIX(uh, s, 32, float32, 32, uint16)
664
-VFP_CONV_FIX(ul, s, 32, float32, 32, uint32)
665
-VFP_CONV_FIX_A64(uq, s, 32, float32, 64, uint64)
666
-VFP_CONV_FIX(sh, h, 16, dh_ctype_f16, 32, int16)
667
-VFP_CONV_FIX(sl, h, 16, dh_ctype_f16, 32, int32)
668
-VFP_CONV_FIX_A64(sq, h, 16, dh_ctype_f16, 64, int64)
669
-VFP_CONV_FIX(uh, h, 16, dh_ctype_f16, 32, uint16)
670
-VFP_CONV_FIX(ul, h, 16, dh_ctype_f16, 32, uint32)
671
-VFP_CONV_FIX_A64(uq, h, 16, dh_ctype_f16, 64, uint64)
672
-VFP_CONV_FLOAT_FIX_ROUND(sq, d, 64, float64, 64, int64,
673
- float_round_to_zero, _round_to_zero)
674
-VFP_CONV_FLOAT_FIX_ROUND(uq, d, 64, float64, 64, uint64,
675
- float_round_to_zero, _round_to_zero)
676
-
677
-#undef VFP_CONV_FIX
678
-#undef VFP_CONV_FIX_FLOAT
679
-#undef VFP_CONV_FLOAT_FIX_ROUND
680
-#undef VFP_CONV_FIX_A64
681
-
682
-/* Set the current fp rounding mode and return the old one.
683
- * The argument is a softfloat float_round_ value.
684
- */
685
-uint32_t HELPER(set_rmode)(uint32_t rmode, float_status *fp_status)
686
-{
687
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
688
- set_float_rounding_mode(rmode, fp_status);
689
-
690
- return prev_rmode;
691
-}
692
-
693
-/* Half precision conversions. */
694
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, float_status *fpst,
695
- uint32_t ahp_mode)
696
-{
697
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
698
- * it would affect flushing input denormals.
699
- */
700
- bool save = get_flush_inputs_to_zero(fpst);
701
- set_flush_inputs_to_zero(false, fpst);
702
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
703
- set_flush_inputs_to_zero(save, fpst);
704
- return r;
705
-}
706
-
707
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, float_status *fpst,
708
- uint32_t ahp_mode)
709
-{
710
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
711
- * it would affect flushing output denormals.
712
- */
713
- bool save = get_flush_to_zero(fpst);
714
- set_flush_to_zero(false, fpst);
715
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
716
- set_flush_to_zero(save, fpst);
717
- return r;
718
-}
719
-
720
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, float_status *fpst,
721
- uint32_t ahp_mode)
722
-{
723
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
724
- * it would affect flushing input denormals.
725
- */
726
- bool save = get_flush_inputs_to_zero(fpst);
727
- set_flush_inputs_to_zero(false, fpst);
728
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
729
- set_flush_inputs_to_zero(save, fpst);
730
- return r;
731
-}
732
-
733
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, float_status *fpst,
734
- uint32_t ahp_mode)
735
-{
736
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
737
- * it would affect flushing output denormals.
738
- */
739
- bool save = get_flush_to_zero(fpst);
740
- set_flush_to_zero(false, fpst);
741
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
742
- set_flush_to_zero(save, fpst);
743
- return r;
744
-}
745
-
746
-/* NEON helpers. */
747
-
748
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
749
- * int->float conversions at run-time. */
750
-#define float64_256 make_float64(0x4070000000000000LL)
751
-#define float64_512 make_float64(0x4080000000000000LL)
752
-#define float16_maxnorm make_float16(0x7bff)
753
-#define float32_maxnorm make_float32(0x7f7fffff)
754
-#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
755
-
756
-/* Reciprocal functions
757
- *
758
- * The algorithm that must be used to calculate the estimate
759
- * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
760
- */
761
-
762
-/* See RecipEstimate()
763
- *
764
- * input is a 9 bit fixed point number
765
- * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
766
- * result range 256 .. 511 for a number from 1.0 to 511/256.
767
- */
768
-
769
-static int recip_estimate(int input)
770
-{
771
- int a, b, r;
772
- assert(256 <= input && input < 512);
773
- a = (input * 2) + 1;
774
- b = (1 << 19) / a;
775
- r = (b + 1) >> 1;
776
- assert(256 <= r && r < 512);
777
- return r;
778
-}
779
-
780
-/*
781
- * Increased precision version:
782
- * input is a 13 bit fixed point number
783
- * input range 2048 .. 4095 for a number from 0.5 <= x < 1.0.
784
- * result range 4096 .. 8191 for a number from 1.0 to 2.0
785
- */
786
-static int recip_estimate_incprec(int input)
787
-{
788
- int a, b, r;
789
- assert(2048 <= input && input < 4096);
790
- a = (input * 2) + 1;
791
- /*
792
- * The pseudocode expresses this as an operation on infinite
793
- * precision reals where it calculates 2^25 / a and then looks
794
- * at the error between that and the rounded-down-to-integer
795
- * value to see if it should instead round up. We instead
796
- * follow the same approach as the pseudocode for the 8-bit
797
- * precision version, and calculate (2 * (2^25 / a)) as an
798
- * integer so we can do the "add one and halve" to round it.
799
- * So the 1 << 26 here is correct.
800
- */
801
- b = (1 << 26) / a;
802
- r = (b + 1) >> 1;
803
- assert(4096 <= r && r < 8192);
804
- return r;
805
-}
806
-
807
-/*
808
- * Common wrapper to call recip_estimate
809
- *
810
- * The parameters are exponent and 64 bit fraction (without implicit
811
- * bit) where the binary point is nominally at bit 52. Returns a
812
- * float64 which can then be rounded to the appropriate size by the
813
- * callee.
814
- */
815
-
816
-static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac,
817
- bool increasedprecision)
818
-{
819
- uint32_t scaled, estimate;
820
- uint64_t result_frac;
821
- int result_exp;
822
-
823
- /* Handle sub-normals */
824
- if (*exp == 0) {
825
- if (extract64(frac, 51, 1) == 0) {
826
- *exp = -1;
827
- frac <<= 2;
828
- } else {
829
- frac <<= 1;
830
- }
831
- }
832
-
833
- if (increasedprecision) {
834
- /* scaled = UInt('1':fraction<51:41>) */
835
- scaled = deposit32(1 << 11, 0, 11, extract64(frac, 41, 11));
836
- estimate = recip_estimate_incprec(scaled);
837
- } else {
838
- /* scaled = UInt('1':fraction<51:44>) */
839
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
840
- estimate = recip_estimate(scaled);
841
- }
842
-
843
- result_exp = exp_off - *exp;
844
- if (increasedprecision) {
845
- result_frac = deposit64(0, 40, 12, estimate);
846
- } else {
847
- result_frac = deposit64(0, 44, 8, estimate);
848
- }
849
- if (result_exp == 0) {
850
- result_frac = deposit64(result_frac >> 1, 51, 1, 1);
851
- } else if (result_exp == -1) {
852
- result_frac = deposit64(result_frac >> 2, 50, 2, 1);
853
- result_exp = 0;
854
- }
855
-
856
- *exp = result_exp;
857
-
858
- return result_frac;
859
-}
860
-
861
-static bool round_to_inf(float_status *fpst, bool sign_bit)
862
-{
863
- switch (fpst->float_rounding_mode) {
864
- case float_round_nearest_even: /* Round to Nearest */
865
- return true;
866
- case float_round_up: /* Round to +Inf */
867
- return !sign_bit;
868
- case float_round_down: /* Round to -Inf */
869
- return sign_bit;
870
- case float_round_to_zero: /* Round to Zero */
871
- return false;
872
- default:
873
- g_assert_not_reached();
874
- }
875
-}
876
-
877
-uint32_t HELPER(recpe_f16)(uint32_t input, float_status *fpst)
878
-{
879
- float16 f16 = float16_squash_input_denormal(input, fpst);
880
- uint32_t f16_val = float16_val(f16);
881
- uint32_t f16_sign = float16_is_neg(f16);
882
- int f16_exp = extract32(f16_val, 10, 5);
883
- uint32_t f16_frac = extract32(f16_val, 0, 10);
884
- uint64_t f64_frac;
885
-
886
- if (float16_is_any_nan(f16)) {
887
- float16 nan = f16;
888
- if (float16_is_signaling_nan(f16, fpst)) {
889
- float_raise(float_flag_invalid, fpst);
890
- if (!fpst->default_nan_mode) {
891
- nan = float16_silence_nan(f16, fpst);
892
- }
893
- }
894
- if (fpst->default_nan_mode) {
895
- nan = float16_default_nan(fpst);
896
- }
897
- return nan;
898
- } else if (float16_is_infinity(f16)) {
899
- return float16_set_sign(float16_zero, float16_is_neg(f16));
900
- } else if (float16_is_zero(f16)) {
901
- float_raise(float_flag_divbyzero, fpst);
902
- return float16_set_sign(float16_infinity, float16_is_neg(f16));
903
- } else if (float16_abs(f16) < (1 << 8)) {
904
- /* Abs(value) < 2.0^-16 */
905
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
906
- if (round_to_inf(fpst, f16_sign)) {
907
- return float16_set_sign(float16_infinity, f16_sign);
908
- } else {
909
- return float16_set_sign(float16_maxnorm, f16_sign);
910
- }
911
- } else if (f16_exp >= 29 && fpst->flush_to_zero) {
912
- float_raise(float_flag_underflow, fpst);
913
- return float16_set_sign(float16_zero, float16_is_neg(f16));
914
- }
915
-
916
- f64_frac = call_recip_estimate(&f16_exp, 29,
917
- ((uint64_t) f16_frac) << (52 - 10), false);
918
-
919
- /* result = sign : result_exp<4:0> : fraction<51:42> */
920
- f16_val = deposit32(0, 15, 1, f16_sign);
921
- f16_val = deposit32(f16_val, 10, 5, f16_exp);
922
- f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
923
- return make_float16(f16_val);
924
-}
925
-
926
-/*
927
- * FEAT_RPRES means the f32 FRECPE has an "increased precision" variant
928
- * which is used when FPCR.AH == 1.
929
- */
930
-static float32 do_recpe_f32(float32 input, float_status *fpst, bool rpres)
931
-{
932
- float32 f32 = float32_squash_input_denormal(input, fpst);
933
- uint32_t f32_val = float32_val(f32);
934
- bool f32_sign = float32_is_neg(f32);
935
- int f32_exp = extract32(f32_val, 23, 8);
936
- uint32_t f32_frac = extract32(f32_val, 0, 23);
937
- uint64_t f64_frac;
938
-
939
- if (float32_is_any_nan(f32)) {
940
- float32 nan = f32;
941
- if (float32_is_signaling_nan(f32, fpst)) {
942
- float_raise(float_flag_invalid, fpst);
943
- if (!fpst->default_nan_mode) {
944
- nan = float32_silence_nan(f32, fpst);
945
- }
946
- }
947
- if (fpst->default_nan_mode) {
948
- nan = float32_default_nan(fpst);
949
- }
950
- return nan;
951
- } else if (float32_is_infinity(f32)) {
952
- return float32_set_sign(float32_zero, float32_is_neg(f32));
953
- } else if (float32_is_zero(f32)) {
954
- float_raise(float_flag_divbyzero, fpst);
955
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
956
- } else if (float32_abs(f32) < (1ULL << 21)) {
957
- /* Abs(value) < 2.0^-128 */
958
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
959
- if (round_to_inf(fpst, f32_sign)) {
960
- return float32_set_sign(float32_infinity, f32_sign);
961
- } else {
962
- return float32_set_sign(float32_maxnorm, f32_sign);
963
- }
964
- } else if (f32_exp >= 253 && fpst->flush_to_zero) {
965
- float_raise(float_flag_underflow, fpst);
966
- return float32_set_sign(float32_zero, float32_is_neg(f32));
967
- }
968
-
969
- f64_frac = call_recip_estimate(&f32_exp, 253,
970
- ((uint64_t) f32_frac) << (52 - 23), rpres);
971
-
972
- /* result = sign : result_exp<7:0> : fraction<51:29> */
973
- f32_val = deposit32(0, 31, 1, f32_sign);
974
- f32_val = deposit32(f32_val, 23, 8, f32_exp);
975
- f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
976
- return make_float32(f32_val);
977
-}
978
-
979
-float32 HELPER(recpe_f32)(float32 input, float_status *fpst)
980
-{
981
- return do_recpe_f32(input, fpst, false);
982
-}
983
-
984
-float32 HELPER(recpe_rpres_f32)(float32 input, float_status *fpst)
985
-{
986
- return do_recpe_f32(input, fpst, true);
987
-}
988
-
989
-float64 HELPER(recpe_f64)(float64 input, float_status *fpst)
990
-{
991
- float64 f64 = float64_squash_input_denormal(input, fpst);
992
- uint64_t f64_val = float64_val(f64);
993
- bool f64_sign = float64_is_neg(f64);
994
- int f64_exp = extract64(f64_val, 52, 11);
995
- uint64_t f64_frac = extract64(f64_val, 0, 52);
996
-
997
- /* Deal with any special cases */
998
- if (float64_is_any_nan(f64)) {
999
- float64 nan = f64;
1000
- if (float64_is_signaling_nan(f64, fpst)) {
1001
- float_raise(float_flag_invalid, fpst);
1002
- if (!fpst->default_nan_mode) {
1003
- nan = float64_silence_nan(f64, fpst);
1004
- }
1005
- }
1006
- if (fpst->default_nan_mode) {
1007
- nan = float64_default_nan(fpst);
1008
- }
1009
- return nan;
1010
- } else if (float64_is_infinity(f64)) {
1011
- return float64_set_sign(float64_zero, float64_is_neg(f64));
1012
- } else if (float64_is_zero(f64)) {
1013
- float_raise(float_flag_divbyzero, fpst);
1014
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
1015
- } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
1016
- /* Abs(value) < 2.0^-1024 */
1017
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
1018
- if (round_to_inf(fpst, f64_sign)) {
1019
- return float64_set_sign(float64_infinity, f64_sign);
1020
- } else {
1021
- return float64_set_sign(float64_maxnorm, f64_sign);
1022
- }
1023
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
1024
- float_raise(float_flag_underflow, fpst);
1025
- return float64_set_sign(float64_zero, float64_is_neg(f64));
1026
- }
1027
-
1028
- f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac, false);
1029
-
1030
- /* result = sign : result_exp<10:0> : fraction<51:0>; */
1031
- f64_val = deposit64(0, 63, 1, f64_sign);
1032
- f64_val = deposit64(f64_val, 52, 11, f64_exp);
1033
- f64_val = deposit64(f64_val, 0, 52, f64_frac);
1034
- return make_float64(f64_val);
1035
-}
1036
-
1037
-/* The algorithm that must be used to calculate the estimate
1038
- * is specified by the ARM ARM.
1039
- */
1040
-
1041
-static int do_recip_sqrt_estimate(int a)
1042
-{
1043
- int b, estimate;
1044
-
1045
- assert(128 <= a && a < 512);
1046
- if (a < 256) {
1047
- a = a * 2 + 1;
1048
- } else {
1049
- a = (a >> 1) << 1;
1050
- a = (a + 1) * 2;
1051
- }
1052
- b = 512;
1053
- while (a * (b + 1) * (b + 1) < (1 << 28)) {
1054
- b += 1;
1055
- }
1056
- estimate = (b + 1) / 2;
1057
- assert(256 <= estimate && estimate < 512);
1058
-
1059
- return estimate;
1060
-}
1061
-
1062
-static int do_recip_sqrt_estimate_incprec(int a)
1063
-{
1064
- /*
1065
- * The Arm ARM describes the 12-bit precision version of RecipSqrtEstimate
1066
- * in terms of an infinite-precision floating point calculation of a
1067
- * square root. We implement this using the same kind of pure integer
1068
- * algorithm as the 8-bit mantissa, to get the same bit-for-bit result.
1069
- */
1070
- int64_t b, estimate;
1071
-
1072
- assert(1024 <= a && a < 4096);
1073
- if (a < 2048) {
1074
- a = a * 2 + 1;
1075
- } else {
1076
- a = (a >> 1) << 1;
1077
- a = (a + 1) * 2;
1078
- }
1079
- b = 8192;
1080
- while (a * (b + 1) * (b + 1) < (1ULL << 39)) {
1081
- b += 1;
1082
- }
1083
- estimate = (b + 1) / 2;
1084
-
1085
- assert(4096 <= estimate && estimate < 8192);
1086
-
1087
- return estimate;
1088
-}
1089
-
1090
-static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac,
1091
- bool increasedprecision)
1092
-{
1093
- int estimate;
1094
- uint32_t scaled;
1095
-
1096
- if (*exp == 0) {
1097
- while (extract64(frac, 51, 1) == 0) {
1098
- frac = frac << 1;
1099
- *exp -= 1;
1100
- }
1101
- frac = extract64(frac, 0, 51) << 1;
1102
- }
1103
-
1104
- if (increasedprecision) {
1105
- if (*exp & 1) {
1106
- /* scaled = UInt('01':fraction<51:42>) */
1107
- scaled = deposit32(1 << 10, 0, 10, extract64(frac, 42, 10));
1108
- } else {
1109
- /* scaled = UInt('1':fraction<51:41>) */
1110
- scaled = deposit32(1 << 11, 0, 11, extract64(frac, 41, 11));
1111
- }
1112
- estimate = do_recip_sqrt_estimate_incprec(scaled);
1113
- } else {
1114
- if (*exp & 1) {
1115
- /* scaled = UInt('01':fraction<51:45>) */
1116
- scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
1117
- } else {
1118
- /* scaled = UInt('1':fraction<51:44>) */
1119
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1120
- }
1121
- estimate = do_recip_sqrt_estimate(scaled);
1122
- }
1123
-
1124
- *exp = (exp_off - *exp) / 2;
1125
- if (increasedprecision) {
1126
- return extract64(estimate, 0, 12) << 40;
1127
- } else {
1128
- return extract64(estimate, 0, 8) << 44;
1129
- }
1130
-}
1131
-
1132
-uint32_t HELPER(rsqrte_f16)(uint32_t input, float_status *s)
1133
-{
1134
- float16 f16 = float16_squash_input_denormal(input, s);
1135
- uint16_t val = float16_val(f16);
1136
- bool f16_sign = float16_is_neg(f16);
1137
- int f16_exp = extract32(val, 10, 5);
1138
- uint16_t f16_frac = extract32(val, 0, 10);
1139
- uint64_t f64_frac;
1140
-
1141
- if (float16_is_any_nan(f16)) {
1142
- float16 nan = f16;
1143
- if (float16_is_signaling_nan(f16, s)) {
1144
- float_raise(float_flag_invalid, s);
1145
- if (!s->default_nan_mode) {
1146
- nan = float16_silence_nan(f16, s);
1147
- }
1148
- }
1149
- if (s->default_nan_mode) {
1150
- nan = float16_default_nan(s);
1151
- }
1152
- return nan;
1153
- } else if (float16_is_zero(f16)) {
1154
- float_raise(float_flag_divbyzero, s);
1155
- return float16_set_sign(float16_infinity, f16_sign);
1156
- } else if (f16_sign) {
1157
- float_raise(float_flag_invalid, s);
1158
- return float16_default_nan(s);
1159
- } else if (float16_is_infinity(f16)) {
1160
- return float16_zero;
1161
- }
1162
-
1163
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1164
- * preserving the parity of the exponent. */
1165
-
1166
- f64_frac = ((uint64_t) f16_frac) << (52 - 10);
1167
-
1168
- f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac, false);
1169
-
1170
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
1171
- val = deposit32(0, 15, 1, f16_sign);
1172
- val = deposit32(val, 10, 5, f16_exp);
1173
- val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
1174
- return make_float16(val);
1175
-}
1176
-
1177
-/*
1178
- * FEAT_RPRES means the f32 FRSQRTE has an "increased precision" variant
1179
- * which is used when FPCR.AH == 1.
1180
- */
1181
-static float32 do_rsqrte_f32(float32 input, float_status *s, bool rpres)
1182
-{
1183
- float32 f32 = float32_squash_input_denormal(input, s);
1184
- uint32_t val = float32_val(f32);
1185
- uint32_t f32_sign = float32_is_neg(f32);
1186
- int f32_exp = extract32(val, 23, 8);
1187
- uint32_t f32_frac = extract32(val, 0, 23);
1188
- uint64_t f64_frac;
1189
-
1190
- if (float32_is_any_nan(f32)) {
1191
- float32 nan = f32;
1192
- if (float32_is_signaling_nan(f32, s)) {
1193
- float_raise(float_flag_invalid, s);
1194
- if (!s->default_nan_mode) {
1195
- nan = float32_silence_nan(f32, s);
1196
- }
1197
- }
1198
- if (s->default_nan_mode) {
1199
- nan = float32_default_nan(s);
1200
- }
1201
- return nan;
1202
- } else if (float32_is_zero(f32)) {
1203
- float_raise(float_flag_divbyzero, s);
1204
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
1205
- } else if (float32_is_neg(f32)) {
1206
- float_raise(float_flag_invalid, s);
1207
- return float32_default_nan(s);
1208
- } else if (float32_is_infinity(f32)) {
1209
- return float32_zero;
1210
- }
1211
-
1212
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1213
- * preserving the parity of the exponent. */
1214
-
1215
- f64_frac = ((uint64_t) f32_frac) << 29;
1216
-
1217
- f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac, rpres);
1218
-
1219
- /*
1220
- * result = sign : result_exp<7:0> : estimate<7:0> : Zeros(15)
1221
- * or for increased precision
1222
- * result = sign : result_exp<7:0> : estimate<11:0> : Zeros(11)
1223
- */
1224
- val = deposit32(0, 31, 1, f32_sign);
1225
- val = deposit32(val, 23, 8, f32_exp);
1226
- if (rpres) {
1227
- val = deposit32(val, 11, 12, extract64(f64_frac, 52 - 12, 12));
1228
- } else {
1229
- val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
1230
- }
1231
- return make_float32(val);
1232
-}
1233
-
1234
-float32 HELPER(rsqrte_f32)(float32 input, float_status *s)
1235
-{
1236
- return do_rsqrte_f32(input, s, false);
1237
-}
1238
-
1239
-float32 HELPER(rsqrte_rpres_f32)(float32 input, float_status *s)
1240
-{
1241
- return do_rsqrte_f32(input, s, true);
1242
-}
1243
-
1244
-float64 HELPER(rsqrte_f64)(float64 input, float_status *s)
1245
-{
1246
- float64 f64 = float64_squash_input_denormal(input, s);
1247
- uint64_t val = float64_val(f64);
1248
- bool f64_sign = float64_is_neg(f64);
1249
- int f64_exp = extract64(val, 52, 11);
1250
- uint64_t f64_frac = extract64(val, 0, 52);
1251
-
1252
- if (float64_is_any_nan(f64)) {
1253
- float64 nan = f64;
1254
- if (float64_is_signaling_nan(f64, s)) {
1255
- float_raise(float_flag_invalid, s);
1256
- if (!s->default_nan_mode) {
1257
- nan = float64_silence_nan(f64, s);
1258
- }
1259
- }
1260
- if (s->default_nan_mode) {
1261
- nan = float64_default_nan(s);
1262
- }
1263
- return nan;
1264
- } else if (float64_is_zero(f64)) {
1265
- float_raise(float_flag_divbyzero, s);
1266
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
1267
- } else if (float64_is_neg(f64)) {
1268
- float_raise(float_flag_invalid, s);
1269
- return float64_default_nan(s);
1270
- } else if (float64_is_infinity(f64)) {
1271
- return float64_zero;
1272
- }
1273
-
1274
- f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac, false);
1275
-
1276
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
1277
- val = deposit64(0, 61, 1, f64_sign);
1278
- val = deposit64(val, 52, 11, f64_exp);
1279
- val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
1280
- return make_float64(val);
1281
-}
1282
-
1283
-uint32_t HELPER(recpe_u32)(uint32_t a)
1284
-{
1285
- int input, estimate;
1286
-
1287
- if ((a & 0x80000000) == 0) {
1288
- return 0xffffffff;
1289
- }
1290
-
1291
- input = extract32(a, 23, 9);
1292
- estimate = recip_estimate(input);
1293
-
1294
- return deposit32(0, (32 - 9), 9, estimate);
1295
-}
1296
-
1297
-uint32_t HELPER(rsqrte_u32)(uint32_t a)
1298
-{
1299
- int estimate;
1300
-
1301
- if ((a & 0xc0000000) == 0) {
1302
- return 0xffffffff;
1303
- }
1304
-
1305
- estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
1306
-
1307
- return deposit32(0, 23, 9, estimate);
1308
-}
1309
-
1310
-/* VFPv4 fused multiply-accumulate */
1311
-dh_ctype_f16 VFP_HELPER(muladd, h)(dh_ctype_f16 a, dh_ctype_f16 b,
1312
- dh_ctype_f16 c, float_status *fpst)
1313
-{
1314
- return float16_muladd(a, b, c, 0, fpst);
1315
-}
1316
-
1317
-float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c,
1318
- float_status *fpst)
1319
-{
1320
- return float32_muladd(a, b, c, 0, fpst);
1321
-}
1322
-
1323
-float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c,
1324
- float_status *fpst)
1325
-{
1326
- return float64_muladd(a, b, c, 0, fpst);
1327
-}
1328
-
1329
-/* ARMv8 round to integral */
1330
-dh_ctype_f16 HELPER(rinth_exact)(dh_ctype_f16 x, float_status *fp_status)
1331
-{
1332
- return float16_round_to_int(x, fp_status);
1333
-}
1334
-
1335
-float32 HELPER(rints_exact)(float32 x, float_status *fp_status)
1336
-{
1337
- return float32_round_to_int(x, fp_status);
1338
-}
1339
-
1340
-float64 HELPER(rintd_exact)(float64 x, float_status *fp_status)
1341
-{
1342
- return float64_round_to_int(x, fp_status);
1343
-}
1344
-
1345
-dh_ctype_f16 HELPER(rinth)(dh_ctype_f16 x, float_status *fp_status)
1346
-{
1347
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1348
- float16 ret;
1349
-
1350
- ret = float16_round_to_int(x, fp_status);
1351
-
1352
- /* Suppress any inexact exceptions the conversion produced */
1353
- if (!(old_flags & float_flag_inexact)) {
1354
- new_flags = get_float_exception_flags(fp_status);
1355
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1356
- }
1357
-
1358
- return ret;
1359
-}
1360
-
1361
-float32 HELPER(rints)(float32 x, float_status *fp_status)
1362
-{
1363
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1364
- float32 ret;
1365
-
1366
- ret = float32_round_to_int(x, fp_status);
1367
-
1368
- /* Suppress any inexact exceptions the conversion produced */
1369
- if (!(old_flags & float_flag_inexact)) {
1370
- new_flags = get_float_exception_flags(fp_status);
1371
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1372
- }
1373
-
1374
- return ret;
1375
-}
1376
-
1377
-float64 HELPER(rintd)(float64 x, float_status *fp_status)
1378
-{
1379
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1380
- float64 ret;
1381
-
1382
- ret = float64_round_to_int(x, fp_status);
1383
-
1384
- /* Suppress any inexact exceptions the conversion produced */
1385
- if (!(old_flags & float_flag_inexact)) {
1386
- new_flags = get_float_exception_flags(fp_status);
1387
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1388
- }
1389
-
1390
- return ret;
1391
-}
1392
-
1393
-/* Convert ARM rounding mode to softfloat */
1394
-const FloatRoundMode arm_rmode_to_sf_map[] = {
1395
- [FPROUNDING_TIEEVEN] = float_round_nearest_even,
1396
- [FPROUNDING_POSINF] = float_round_up,
1397
- [FPROUNDING_NEGINF] = float_round_down,
1398
- [FPROUNDING_ZERO] = float_round_to_zero,
1399
- [FPROUNDING_TIEAWAY] = float_round_ties_away,
1400
- [FPROUNDING_ODD] = float_round_to_odd,
1401
-};
1402
-
1403
-/*
1404
- * Implement float64 to int32_t conversion without saturation;
1405
- * the result is supplied modulo 2^32.
1406
- */
1407
-uint64_t HELPER(fjcvtzs)(float64 value, float_status *status)
1408
-{
1409
- uint32_t frac, e_old, e_new;
1410
- bool inexact;
1411
-
1412
- e_old = get_float_exception_flags(status);
1413
- set_float_exception_flags(0, status);
1414
- frac = float64_to_int32_modulo(value, float_round_to_zero, status);
1415
- e_new = get_float_exception_flags(status);
1416
- set_float_exception_flags(e_old | e_new, status);
1417
-
1418
- /* Normal inexact, denormal with flush-to-zero, or overflow or NaN */
1419
- inexact = e_new & (float_flag_inexact |
1420
- float_flag_input_denormal_flushed |
1421
- float_flag_invalid);
1422
-
1423
- /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
1424
- inexact |= value == float64_chs(float64_zero);
1425
-
1426
- /* Pack the result and the env->ZF representation of Z together. */
1427
- return deposit64(frac, 32, 32, inexact);
1428
-}
1429
-
1430
-uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
1431
-{
1432
- uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status[FPST_A32]);
1433
- uint32_t result = pair;
1434
- uint32_t z = (pair >> 32) == 0;
1435
-
1436
- /* Store Z, clear NCV, in FPSCR.NZCV. */
1437
- env->vfp.fpsr = (env->vfp.fpsr & ~FPSR_NZCV_MASK) | (z * FPSR_Z);
1438
-
1439
- return result;
1440
-}
1441
-
1442
-/* Round a float32 to an integer that fits in int32_t or int64_t. */
1443
-static float32 frint_s(float32 f, float_status *fpst, int intsize)
1444
-{
1445
- int old_flags = get_float_exception_flags(fpst);
1446
- uint32_t exp = extract32(f, 23, 8);
1447
-
1448
- if (unlikely(exp == 0xff)) {
1449
- /* NaN or Inf. */
1450
- goto overflow;
1451
- }
1452
-
1453
- /* Round and re-extract the exponent. */
1454
- f = float32_round_to_int(f, fpst);
1455
- exp = extract32(f, 23, 8);
1456
-
1457
- /* Validate the range of the result. */
1458
- if (exp < 126 + intsize) {
1459
- /* abs(F) <= INT{N}_MAX */
1460
- return f;
1461
- }
1462
- if (exp == 126 + intsize) {
1463
- uint32_t sign = extract32(f, 31, 1);
1464
- uint32_t frac = extract32(f, 0, 23);
1465
- if (sign && frac == 0) {
1466
- /* F == INT{N}_MIN */
1467
- return f;
1468
- }
1469
- }
1470
-
1471
- overflow:
1472
- /*
1473
- * Raise Invalid and return INT{N}_MIN as a float. Revert any
1474
- * inexact exception float32_round_to_int may have raised.
1475
- */
1476
- set_float_exception_flags(old_flags | float_flag_invalid, fpst);
1477
- return (0x100u + 126u + intsize) << 23;
1478
-}
1479
-
1480
-float32 HELPER(frint32_s)(float32 f, float_status *fpst)
1481
-{
1482
- return frint_s(f, fpst, 32);
1483
-}
1484
-
1485
-float32 HELPER(frint64_s)(float32 f, float_status *fpst)
1486
-{
1487
- return frint_s(f, fpst, 64);
1488
-}
1489
-
1490
-/* Round a float64 to an integer that fits in int32_t or int64_t. */
1491
-static float64 frint_d(float64 f, float_status *fpst, int intsize)
1492
-{
1493
- int old_flags = get_float_exception_flags(fpst);
1494
- uint32_t exp = extract64(f, 52, 11);
1495
-
1496
- if (unlikely(exp == 0x7ff)) {
1497
- /* NaN or Inf. */
1498
- goto overflow;
1499
- }
1500
-
1501
- /* Round and re-extract the exponent. */
1502
- f = float64_round_to_int(f, fpst);
1503
- exp = extract64(f, 52, 11);
1504
-
1505
- /* Validate the range of the result. */
1506
- if (exp < 1022 + intsize) {
1507
- /* abs(F) <= INT{N}_MAX */
1508
- return f;
1509
- }
1510
- if (exp == 1022 + intsize) {
1511
- uint64_t sign = extract64(f, 63, 1);
1512
- uint64_t frac = extract64(f, 0, 52);
1513
- if (sign && frac == 0) {
1514
- /* F == INT{N}_MIN */
1515
- return f;
1516
- }
1517
- }
1518
-
1519
- overflow:
1520
- /*
1521
- * Raise Invalid and return INT{N}_MIN as a float. Revert any
1522
- * inexact exception float64_round_to_int may have raised.
1523
- */
1524
- set_float_exception_flags(old_flags | float_flag_invalid, fpst);
1525
- return (uint64_t)(0x800 + 1022 + intsize) << 52;
1526
-}
1527
-
1528
-float64 HELPER(frint32_d)(float64 f, float_status *fpst)
1529
-{
1530
- return frint_d(f, fpst, 32);
1531
-}
1532
-
1533
-float64 HELPER(frint64_d)(float64 f, float_status *fpst)
1534
-{
1535
- return frint_d(f, fpst, 64);
1536
-}
1537
-
1538
-void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
1539
-{
1540
- uint32_t syndrome;
1541
-
1542
- switch (reg) {
1543
- case ARM_VFP_MVFR0:
1544
- case ARM_VFP_MVFR1:
1545
- case ARM_VFP_MVFR2:
1546
- if (!(arm_hcr_el2_eff(env) & HCR_TID3)) {
1547
- return;
1548
- }
1549
- break;
1550
- case ARM_VFP_FPSID:
1551
- if (!(arm_hcr_el2_eff(env) & HCR_TID0)) {
1552
- return;
1553
- }
1554
- break;
1555
- default:
1556
- g_assert_not_reached();
1557
- }
1558
-
1559
- syndrome = ((EC_FPIDTRAP << ARM_EL_EC_SHIFT)
1560
- | ARM_EL_IL
1561
- | (1 << 24) | (0xe << 20) | (7 << 14)
1562
- | (reg << 10) | (rt << 5) | 1);
1563
-
1564
- raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
1565
-}
1566
-
1567
-#endif
1568
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
1569
index XXXXXXX..XXXXXXX 100644
1570
--- a/target/arm/tcg/meson.build
1571
+++ b/target/arm/tcg/meson.build
1572
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
1573
'vec_helper.c',
1574
'tlb-insns.c',
1575
'arith_helper.c',
1576
+ 'vfp_helper.c',
1577
))
1578
1579
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
1580
--
1581
2.43.0
diff view generated by jsdifflib
New patch
1
Currently the helper_vfp_get_fpscr() and helper_vfp_set_fpscr()
2
functions do the actual work of updating the FPSCR, and we have
3
wrappers vfp_get_fpscr() and vfp_set_fpscr() which we use for calls
4
from other QEMU C code.
1
5
6
Flip these around so that it is vfp_get_fpscr() and vfp_set_fpscr()
7
which do the actual work, and helper_vfp_get_fpscr() and
8
helper_vfp_set_fpscr() which are the wrappers; this allows us to move
9
them to tcg/vfp_helper.c.
10
11
Since this is the last HELPER() we had in arm/vfp_helper.c, we can
12
drop the include of helper-proto.h.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20250221190957.811948-3-peter.maydell@linaro.org
17
---
18
target/arm/tcg/vfp_helper.c | 10 ++++++++++
19
target/arm/vfp_helper.c | 15 ++-------------
20
2 files changed, 12 insertions(+), 13 deletions(-)
21
22
diff --git a/target/arm/tcg/vfp_helper.c b/target/arm/tcg/vfp_helper.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/tcg/vfp_helper.c
25
+++ b/target/arm/tcg/vfp_helper.c
26
@@ -XXX,XX +XXX,XX @@ void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
27
28
raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
29
}
30
+
31
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
32
+{
33
+ return vfp_get_fpscr(env);
34
+}
35
+
36
+void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
37
+{
38
+ vfp_set_fpscr(env, val);
39
+}
40
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/vfp_helper.c
43
+++ b/target/arm/vfp_helper.c
44
@@ -XXX,XX +XXX,XX @@
45
46
#include "qemu/osdep.h"
47
#include "cpu.h"
48
-#include "exec/helper-proto.h"
49
#include "internals.h"
50
#include "cpu-features.h"
51
#include "fpu/softfloat.h"
52
@@ -XXX,XX +XXX,XX @@ uint32_t vfp_get_fpsr(CPUARMState *env)
53
return fpsr;
54
}
55
56
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
57
+uint32_t vfp_get_fpscr(CPUARMState *env)
58
{
59
return (vfp_get_fpcr(env) & FPSCR_FPCR_MASK) |
60
(vfp_get_fpsr(env) & FPSCR_FPSR_MASK);
61
}
62
63
-uint32_t vfp_get_fpscr(CPUARMState *env)
64
-{
65
- return HELPER(vfp_get_fpscr)(env);
66
-}
67
-
68
void vfp_set_fpsr(CPUARMState *env, uint32_t val)
69
{
70
ARMCPU *cpu = env_archcpu(env);
71
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpcr(CPUARMState *env, uint32_t val)
72
vfp_set_fpcr_masked(env, val, MAKE_64BIT_MASK(0, 32));
73
}
74
75
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
76
+void vfp_set_fpscr(CPUARMState *env, uint32_t val)
77
{
78
vfp_set_fpcr_masked(env, val, FPSCR_FPCR_MASK);
79
vfp_set_fpsr(env, val & FPSCR_FPSR_MASK);
80
}
81
-
82
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
83
-{
84
- HELPER(vfp_set_fpscr)(env, val);
85
-}
86
--
87
2.43.0
diff view generated by jsdifflib
New patch
1
The softfloat (i.e. TCG) specific handling for the FPCR
2
and FPSR is abstracted behind five functions:
3
arm_set_default_fp_behaviours
4
arm_set_ah_fp_behaviours
5
vfp_get_fpsr_from_host
6
vfp_clear_float_status_exc_flags
7
vfp_set_fpsr_to_host
1
8
9
Currently we rely on the first two calling softfloat functions that
10
work even in a KVM-only compile because they're defined as inline in
11
the softfloat header file, and we provide stub versions of the last
12
three in arm/vfp_helper.c if CONFIG_TCG isn't defined.
13
14
Move the softfloat-specific versions of these functions to
15
tcg/vfp_helper.c, and provide the non-TCG stub versions in
16
tcg-stubs.c.
17
18
This lets us drop the softfloat header include and the last
19
set of CONFIG_TCG ifdefs from arm/vfp_helper.c.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20250221190957.811948-4-peter.maydell@linaro.org
24
---
25
target/arm/internals.h | 9 ++
26
target/arm/tcg-stubs.c | 22 ++++
27
target/arm/tcg/vfp_helper.c | 228 +++++++++++++++++++++++++++++++++
28
target/arm/vfp_helper.c | 248 ------------------------------------
29
4 files changed, 259 insertions(+), 248 deletions(-)
30
31
diff --git a/target/arm/internals.h b/target/arm/internals.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/internals.h
34
+++ b/target/arm/internals.h
35
@@ -XXX,XX +XXX,XX @@ int alle1_tlbmask(CPUARMState *env);
36
void arm_set_default_fp_behaviours(float_status *s);
37
/* Set the float_status behaviour to match Arm FPCR.AH=1 behaviour */
38
void arm_set_ah_fp_behaviours(float_status *s);
39
+/* Read the float_status info and return the appropriate FPSR value */
40
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env);
41
+/* Clear the exception status flags from all float_status fields */
42
+void vfp_clear_float_status_exc_flags(CPUARMState *env);
43
+/*
44
+ * Update float_status fields to handle the bits of the FPCR
45
+ * specified by mask changing to the values in val.
46
+ */
47
+void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask);
48
49
#endif
50
diff --git a/target/arm/tcg-stubs.c b/target/arm/tcg-stubs.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/tcg-stubs.c
53
+++ b/target/arm/tcg-stubs.c
54
@@ -XXX,XX +XXX,XX @@ void assert_hflags_rebuild_correctly(CPUARMState *env)
55
void define_tlb_insn_regs(ARMCPU *cpu)
56
{
57
}
58
+
59
+/* With KVM, we never use float_status, so these can be no-ops */
60
+void arm_set_default_fp_behaviours(float_status *s)
61
+{
62
+}
63
+
64
+void arm_set_ah_fp_behaviours(float_status *s)
65
+{
66
+}
67
+
68
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
69
+{
70
+ return 0;
71
+}
72
+
73
+void vfp_clear_float_status_exc_flags(CPUARMState *env)
74
+{
75
+}
76
+
77
+void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
78
+{
79
+}
80
diff --git a/target/arm/tcg/vfp_helper.c b/target/arm/tcg/vfp_helper.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/tcg/vfp_helper.c
83
+++ b/target/arm/tcg/vfp_helper.c
84
@@ -XXX,XX +XXX,XX @@
85
#include "fpu/softfloat.h"
86
#include "qemu/log.h"
87
88
+/*
89
+ * Set the float_status behaviour to match the Arm defaults:
90
+ * * tininess-before-rounding
91
+ * * 2-input NaN propagation prefers SNaN over QNaN, and then
92
+ * operand A over operand B (see FPProcessNaNs() pseudocode)
93
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
94
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
95
+ * but note that for QEMU muladd is a * b + c, whereas for
96
+ * the pseudocode function the arguments are in the order c, a, b.
97
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
98
+ * and the input NaN if it is signalling
99
+ * * Default NaN has sign bit clear, msb frac bit set
100
+ */
101
+void arm_set_default_fp_behaviours(float_status *s)
102
+{
103
+ set_float_detect_tininess(float_tininess_before_rounding, s);
104
+ set_float_ftz_detection(float_ftz_before_rounding, s);
105
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
106
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
107
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
108
+ set_float_default_nan_pattern(0b01000000, s);
109
+}
110
+
111
+/*
112
+ * Set the float_status behaviour to match the FEAT_AFP
113
+ * FPCR.AH=1 requirements:
114
+ * * tininess-after-rounding
115
+ * * 2-input NaN propagation prefers the first NaN
116
+ * * 3-input NaN propagation prefers a over b over c
117
+ * * 0 * Inf + NaN always returns the input NaN and doesn't
118
+ * set Invalid for a QNaN
119
+ * * default NaN has sign bit set, msb frac bit set
120
+ */
121
+void arm_set_ah_fp_behaviours(float_status *s)
122
+{
123
+ set_float_detect_tininess(float_tininess_after_rounding, s);
124
+ set_float_ftz_detection(float_ftz_after_rounding, s);
125
+ set_float_2nan_prop_rule(float_2nan_prop_ab, s);
126
+ set_float_3nan_prop_rule(float_3nan_prop_abc, s);
127
+ set_float_infzeronan_rule(float_infzeronan_dnan_never |
128
+ float_infzeronan_suppress_invalid, s);
129
+ set_float_default_nan_pattern(0b11000000, s);
130
+}
131
+
132
+/* Convert host exception flags to vfp form. */
133
+static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
134
+{
135
+ uint32_t target_bits = 0;
136
+
137
+ if (host_bits & float_flag_invalid) {
138
+ target_bits |= FPSR_IOC;
139
+ }
140
+ if (host_bits & float_flag_divbyzero) {
141
+ target_bits |= FPSR_DZC;
142
+ }
143
+ if (host_bits & float_flag_overflow) {
144
+ target_bits |= FPSR_OFC;
145
+ }
146
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
147
+ target_bits |= FPSR_UFC;
148
+ }
149
+ if (host_bits & float_flag_inexact) {
150
+ target_bits |= FPSR_IXC;
151
+ }
152
+ if (host_bits & float_flag_input_denormal_flushed) {
153
+ target_bits |= FPSR_IDC;
154
+ }
155
+ /*
156
+ * With FPCR.AH, IDC is set when an input denormal is used,
157
+ * and flushing an output denormal to zero sets both IXC and UFC.
158
+ */
159
+ if (ah && (host_bits & float_flag_input_denormal_used)) {
160
+ target_bits |= FPSR_IDC;
161
+ }
162
+ if (ah && (host_bits & float_flag_output_denormal_flushed)) {
163
+ target_bits |= FPSR_IXC;
164
+ }
165
+ return target_bits;
166
+}
167
+
168
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
169
+{
170
+ uint32_t a32_flags = 0, a64_flags = 0;
171
+
172
+ a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
173
+ a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
174
+ /* FZ16 does not generate an input denormal exception. */
175
+ a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
176
+ & ~float_flag_input_denormal_flushed);
177
+ a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
178
+ & ~float_flag_input_denormal_flushed);
179
+
180
+ a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
181
+ a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
182
+ & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
183
+ /*
184
+ * We do not merge in flags from FPST_AH or FPST_AH_F16, because
185
+ * they are used for insns that must not set the cumulative exception bits.
186
+ */
187
+
188
+ /*
189
+ * Flushing an input denormal *only* because FPCR.FIZ == 1 does
190
+ * not set FPSR.IDC; if FPCR.FZ is also set then this takes
191
+ * precedence and IDC is set (see the FPUnpackBase pseudocode).
192
+ * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
193
+ * We only do this for the a64 flags because FIZ has no effect
194
+ * on AArch32 even if it is set.
195
+ */
196
+ if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
197
+ a64_flags &= ~float_flag_input_denormal_flushed;
198
+ }
199
+ return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
200
+ vfp_exceptbits_from_host(a32_flags, false);
201
+}
202
+
203
+void vfp_clear_float_status_exc_flags(CPUARMState *env)
204
+{
205
+ /*
206
+ * Clear out all the exception-flag information in the float_status
207
+ * values. The caller should have arranged for env->vfp.fpsr to
208
+ * be the architecturally up-to-date exception flag information first.
209
+ */
210
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
211
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
212
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
213
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
214
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
215
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
216
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
217
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
218
+}
219
+
220
+static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
221
+{
222
+ /*
223
+ * Synchronize any pending exception-flag information in the
224
+ * float_status values into env->vfp.fpsr, and then clear out
225
+ * the float_status data.
226
+ */
227
+ env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
228
+ vfp_clear_float_status_exc_flags(env);
229
+}
230
+
231
+void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
232
+{
233
+ uint64_t changed = env->vfp.fpcr;
234
+
235
+ changed ^= val;
236
+ changed &= mask;
237
+ if (changed & (3 << 22)) {
238
+ int i = (val >> 22) & 3;
239
+ switch (i) {
240
+ case FPROUNDING_TIEEVEN:
241
+ i = float_round_nearest_even;
242
+ break;
243
+ case FPROUNDING_POSINF:
244
+ i = float_round_up;
245
+ break;
246
+ case FPROUNDING_NEGINF:
247
+ i = float_round_down;
248
+ break;
249
+ case FPROUNDING_ZERO:
250
+ i = float_round_to_zero;
251
+ break;
252
+ }
253
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
254
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
255
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
256
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
257
+ }
258
+ if (changed & FPCR_FZ16) {
259
+ bool ftz_enabled = val & FPCR_FZ16;
260
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
261
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
262
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
263
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
264
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
265
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
266
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
267
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
268
+ }
269
+ if (changed & FPCR_FZ) {
270
+ bool ftz_enabled = val & FPCR_FZ;
271
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
272
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
273
+ /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
274
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
275
+ }
276
+ if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
277
+ /*
278
+ * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
279
+ * both FPCR.AH = 0 and FPCR.FZ = 1.
280
+ */
281
+ bool fitz_enabled = (val & FPCR_FIZ) ||
282
+ (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
283
+ set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
284
+ }
285
+ if (changed & FPCR_DN) {
286
+ bool dnan_enabled = val & FPCR_DN;
287
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
288
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
289
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
290
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
291
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
292
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
293
+ }
294
+ if (changed & FPCR_AH) {
295
+ bool ah_enabled = val & FPCR_AH;
296
+
297
+ if (ah_enabled) {
298
+ /* Change behaviours for A64 FP operations */
299
+ arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
300
+ arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
301
+ } else {
302
+ arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
303
+ arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
304
+ }
305
+ }
306
+ /*
307
+ * If any bits changed that we look at in vfp_get_fpsr_from_host(),
308
+ * we must sync the float_status flags into vfp.fpsr now (under the
309
+ * old regime) before we update vfp.fpcr.
310
+ */
311
+ if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
312
+ vfp_sync_and_clear_float_status_exc_flags(env);
313
+ }
314
+}
315
+
316
/*
317
* VFP support. We follow the convention used for VFP instructions:
318
* Single precision routines have a "s" suffix, double precision a
319
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
320
index XXXXXXX..XXXXXXX 100644
321
--- a/target/arm/vfp_helper.c
322
+++ b/target/arm/vfp_helper.c
323
@@ -XXX,XX +XXX,XX @@
324
#include "cpu.h"
325
#include "internals.h"
326
#include "cpu-features.h"
327
-#include "fpu/softfloat.h"
328
-
329
-/*
330
- * Set the float_status behaviour to match the Arm defaults:
331
- * * tininess-before-rounding
332
- * * 2-input NaN propagation prefers SNaN over QNaN, and then
333
- * operand A over operand B (see FPProcessNaNs() pseudocode)
334
- * * 3-input NaN propagation prefers SNaN over QNaN, and then
335
- * operand C over A over B (see FPProcessNaNs3() pseudocode,
336
- * but note that for QEMU muladd is a * b + c, whereas for
337
- * the pseudocode function the arguments are in the order c, a, b.
338
- * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
339
- * and the input NaN if it is signalling
340
- * * Default NaN has sign bit clear, msb frac bit set
341
- */
342
-void arm_set_default_fp_behaviours(float_status *s)
343
-{
344
- set_float_detect_tininess(float_tininess_before_rounding, s);
345
- set_float_ftz_detection(float_ftz_before_rounding, s);
346
- set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
347
- set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
348
- set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
349
- set_float_default_nan_pattern(0b01000000, s);
350
-}
351
-
352
-/*
353
- * Set the float_status behaviour to match the FEAT_AFP
354
- * FPCR.AH=1 requirements:
355
- * * tininess-after-rounding
356
- * * 2-input NaN propagation prefers the first NaN
357
- * * 3-input NaN propagation prefers a over b over c
358
- * * 0 * Inf + NaN always returns the input NaN and doesn't
359
- * set Invalid for a QNaN
360
- * * default NaN has sign bit set, msb frac bit set
361
- */
362
-void arm_set_ah_fp_behaviours(float_status *s)
363
-{
364
- set_float_detect_tininess(float_tininess_after_rounding, s);
365
- set_float_ftz_detection(float_ftz_after_rounding, s);
366
- set_float_2nan_prop_rule(float_2nan_prop_ab, s);
367
- set_float_3nan_prop_rule(float_3nan_prop_abc, s);
368
- set_float_infzeronan_rule(float_infzeronan_dnan_never |
369
- float_infzeronan_suppress_invalid, s);
370
- set_float_default_nan_pattern(0b11000000, s);
371
-}
372
-
373
-#ifdef CONFIG_TCG
374
-
375
-/* Convert host exception flags to vfp form. */
376
-static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
377
-{
378
- uint32_t target_bits = 0;
379
-
380
- if (host_bits & float_flag_invalid) {
381
- target_bits |= FPSR_IOC;
382
- }
383
- if (host_bits & float_flag_divbyzero) {
384
- target_bits |= FPSR_DZC;
385
- }
386
- if (host_bits & float_flag_overflow) {
387
- target_bits |= FPSR_OFC;
388
- }
389
- if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
390
- target_bits |= FPSR_UFC;
391
- }
392
- if (host_bits & float_flag_inexact) {
393
- target_bits |= FPSR_IXC;
394
- }
395
- if (host_bits & float_flag_input_denormal_flushed) {
396
- target_bits |= FPSR_IDC;
397
- }
398
- /*
399
- * With FPCR.AH, IDC is set when an input denormal is used,
400
- * and flushing an output denormal to zero sets both IXC and UFC.
401
- */
402
- if (ah && (host_bits & float_flag_input_denormal_used)) {
403
- target_bits |= FPSR_IDC;
404
- }
405
- if (ah && (host_bits & float_flag_output_denormal_flushed)) {
406
- target_bits |= FPSR_IXC;
407
- }
408
- return target_bits;
409
-}
410
-
411
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
412
-{
413
- uint32_t a32_flags = 0, a64_flags = 0;
414
-
415
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
416
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
417
- /* FZ16 does not generate an input denormal exception. */
418
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
419
- & ~float_flag_input_denormal_flushed);
420
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
421
- & ~float_flag_input_denormal_flushed);
422
-
423
- a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
424
- a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
425
- & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
426
- /*
427
- * We do not merge in flags from FPST_AH or FPST_AH_F16, because
428
- * they are used for insns that must not set the cumulative exception bits.
429
- */
430
-
431
- /*
432
- * Flushing an input denormal *only* because FPCR.FIZ == 1 does
433
- * not set FPSR.IDC; if FPCR.FZ is also set then this takes
434
- * precedence and IDC is set (see the FPUnpackBase pseudocode).
435
- * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
436
- * We only do this for the a64 flags because FIZ has no effect
437
- * on AArch32 even if it is set.
438
- */
439
- if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
440
- a64_flags &= ~float_flag_input_denormal_flushed;
441
- }
442
- return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
443
- vfp_exceptbits_from_host(a32_flags, false);
444
-}
445
-
446
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
447
-{
448
- /*
449
- * Clear out all the exception-flag information in the float_status
450
- * values. The caller should have arranged for env->vfp.fpsr to
451
- * be the architecturally up-to-date exception flag information first.
452
- */
453
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
454
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
455
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
456
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
457
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
458
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
459
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
460
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
461
-}
462
-
463
-static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
464
-{
465
- /*
466
- * Synchronize any pending exception-flag information in the
467
- * float_status values into env->vfp.fpsr, and then clear out
468
- * the float_status data.
469
- */
470
- env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
471
- vfp_clear_float_status_exc_flags(env);
472
-}
473
-
474
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
475
-{
476
- uint64_t changed = env->vfp.fpcr;
477
-
478
- changed ^= val;
479
- changed &= mask;
480
- if (changed & (3 << 22)) {
481
- int i = (val >> 22) & 3;
482
- switch (i) {
483
- case FPROUNDING_TIEEVEN:
484
- i = float_round_nearest_even;
485
- break;
486
- case FPROUNDING_POSINF:
487
- i = float_round_up;
488
- break;
489
- case FPROUNDING_NEGINF:
490
- i = float_round_down;
491
- break;
492
- case FPROUNDING_ZERO:
493
- i = float_round_to_zero;
494
- break;
495
- }
496
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
497
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
498
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
499
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
500
- }
501
- if (changed & FPCR_FZ16) {
502
- bool ftz_enabled = val & FPCR_FZ16;
503
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
504
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
505
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
506
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
507
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
508
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
509
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
510
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
511
- }
512
- if (changed & FPCR_FZ) {
513
- bool ftz_enabled = val & FPCR_FZ;
514
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
515
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
516
- /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
517
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
518
- }
519
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
520
- /*
521
- * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
522
- * both FPCR.AH = 0 and FPCR.FZ = 1.
523
- */
524
- bool fitz_enabled = (val & FPCR_FIZ) ||
525
- (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
526
- set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
527
- }
528
- if (changed & FPCR_DN) {
529
- bool dnan_enabled = val & FPCR_DN;
530
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
531
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
532
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
533
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
534
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
535
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
536
- }
537
- if (changed & FPCR_AH) {
538
- bool ah_enabled = val & FPCR_AH;
539
-
540
- if (ah_enabled) {
541
- /* Change behaviours for A64 FP operations */
542
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
543
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
544
- } else {
545
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
546
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
547
- }
548
- }
549
- /*
550
- * If any bits changed that we look at in vfp_get_fpsr_from_host(),
551
- * we must sync the float_status flags into vfp.fpsr now (under the
552
- * old regime) before we update vfp.fpcr.
553
- */
554
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
555
- vfp_sync_and_clear_float_status_exc_flags(env);
556
- }
557
-}
558
-
559
-#else
560
-
561
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
562
-{
563
- return 0;
564
-}
565
-
566
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
567
-{
568
-}
569
-
570
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
571
-{
572
-}
573
-
574
-#endif
575
576
uint32_t vfp_get_fpcr(CPUARMState *env)
577
{
578
--
579
2.43.0
diff view generated by jsdifflib
New patch
1
The vfp_helper.c in the target/arm directory now only has
2
code for handling FPSCR/FPCR/FPSR in it, and no helper
3
functions. Rename it to vfp_fpscr.c; this helps keep it
4
distinct from tcg/vfp_helper.c.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20250221190957.811948-5-peter.maydell@linaro.org
9
---
10
target/arm/{vfp_helper.c => vfp_fpscr.c} | 2 +-
11
target/arm/meson.build | 2 +-
12
2 files changed, 2 insertions(+), 2 deletions(-)
13
rename target/arm/{vfp_helper.c => vfp_fpscr.c} (98%)
14
15
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_fpscr.c
16
similarity index 98%
17
rename from target/arm/vfp_helper.c
18
rename to target/arm/vfp_fpscr.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/vfp_helper.c
21
+++ b/target/arm/vfp_fpscr.c
22
@@ -XXX,XX +XXX,XX @@
23
/*
24
- * ARM VFP floating-point operations
25
+ * ARM VFP floating-point: handling of FPSCR/FPCR/FPSR
26
*
27
* Copyright (c) 2003 Fabrice Bellard
28
*
29
diff --git a/target/arm/meson.build b/target/arm/meson.build
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/meson.build
32
+++ b/target/arm/meson.build
33
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
34
'debug_helper.c',
35
'gdbstub.c',
36
'helper.c',
37
- 'vfp_helper.c',
38
+ 'vfp_fpscr.c',
39
))
40
arm_ss.add(zlib)
41
42
--
43
2.43.0
diff view generated by jsdifflib
New patch
1
From: Joelle van Dyne <j@getutm.app>
1
2
3
macOS 15.2's Hypervisor.framework exposes SME feature on M4 Macs.
4
However, QEMU's hvf accelerator code does not properly support it
5
yet, causing QEMU to fail to start when hvf accelerator is used on
6
these systems, with the error message:
7
8
qemu-aarch64-softmmu: cannot disable sme4224
9
All SME vector lengths are disabled.
10
With SME enabled, at least one vector length must be enabled.
11
12
Ideally we would have SME support on these hosts; however, until that
13
point, we must suppress the SME feature in the ID registers, so that
14
users can at least run non-SME guests.
15
16
Cc: qemu-stable@nongnu.org
17
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2665
18
Signed-off-by: Joelle van Dyne <j@getutm.app>
19
Message-id: 20250224165735.36792-1-j@getutm.app
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
[PMM: expanded commit message, comment]
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
target/arm/hvf/hvf.c | 12 ++++++++++++
25
1 file changed, 12 insertions(+)
26
27
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/hvf/hvf.c
30
+++ b/target/arm/hvf/hvf.c
31
@@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
32
33
clamp_id_aa64mmfr0_parange_to_ipa_size(&host_isar.id_aa64mmfr0);
34
35
+ /*
36
+ * Disable SME, which is not properly handled by QEMU hvf yet.
37
+ * To allow this through we would need to:
38
+ * - make sure that the SME state is correctly handled in the
39
+ * get_registers/put_registers functions
40
+ * - get the SME-specific CPU properties to work with accelerators
41
+ * other than TCG
42
+ * - fix any assumptions we made that SME implies SVE (since
43
+ * on the M4 there is SME but not SVE)
44
+ */
45
+ host_isar.id_aa64pfr1 &= ~R_ID_AA64PFR1_SME_MASK;
46
+
47
ahcf->isar = host_isar;
48
49
/*
50
--
51
2.43.0
diff view generated by jsdifflib
New patch
1
From: Joelle van Dyne <j@getutm.app>
1
2
3
In the syndrome value for a data abort, bit 21 is SSE, which is
4
set to indicate that the abort was on a sign-extending load. When
5
we handle the data abort from the guest via address_space_read(),
6
we forgot to handle this and so would return the wrong value if
7
the guest did a sign-extending load to an MMIO region. Add the
8
sign-extension of the returned data.
9
10
Cc: qemu-stable@nongnu.org
11
Signed-off-by: Joelle van Dyne <j@getutm.app>
12
Message-id: 20250224184123.50780-1-j@getutm.app
13
[PMM: Drop an unnecessary check on 'len'; expand commit message]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/hvf/hvf.c | 4 ++++
18
1 file changed, 4 insertions(+)
19
20
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/hvf/hvf.c
23
+++ b/target/arm/hvf/hvf.c
24
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
25
bool isv = syndrome & ARM_EL_ISV;
26
bool iswrite = (syndrome >> 6) & 1;
27
bool s1ptw = (syndrome >> 7) & 1;
28
+ bool sse = (syndrome >> 21) & 1;
29
uint32_t sas = (syndrome >> 22) & 3;
30
uint32_t len = 1 << sas;
31
uint32_t srt = (syndrome >> 16) & 0x1f;
32
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
33
address_space_read(&address_space_memory,
34
hvf_exit->exception.physical_address,
35
MEMTXATTRS_UNSPECIFIED, &val, len);
36
+ if (sse) {
37
+ val = sextract64(val, 0, len * 8);
38
+ }
39
hvf_set_reg(cpu, srt, val);
40
}
41
42
--
43
2.43.0
diff view generated by jsdifflib
New patch
1
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
1
2
3
Regression introduced by cf76c4
4
(hw/misc: Add nr_regs and cold_reset_values to NPCM CLK)
5
6
cold_reset_values has a different size, depending on device used
7
(NPCM7xx vs NPCM8xx). However, s->regs has a fixed size, which matches
8
NPCM8xx. Thus, when initializing a NPCM7xx, we go past cold_reset_values
9
ending.
10
11
Report by asan:
12
==2066==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55d68a3e97f0 at pc 0x7fcaf2b2d14b bp 0x7ffff0cc3890 sp 0x7ffff0cc3040
13
READ of size 196 at 0x55d68a3e97f0 thread T0
14
#0 0x7fcaf2b2d14a in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
15
#1 0x55d688447e0d in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:29
16
#2 0x55d688447e0d in npcm_clk_enter_reset ../hw/misc/npcm_clk.c:968
17
#3 0x55d6899b7213 in resettable_phase_enter ../hw/core/resettable.c:136
18
#4 0x55d6899a1ef7 in bus_reset_child_foreach ../hw/core/bus.c:97
19
#5 0x55d6899b717d in resettable_child_foreach ../hw/core/resettable.c:92
20
#6 0x55d6899b717d in resettable_phase_enter ../hw/core/resettable.c:129
21
#7 0x55d6899b4ead in resettable_container_child_foreach ../hw/core/resetcontainer.c:54
22
#8 0x55d6899b717d in resettable_child_foreach ../hw/core/resettable.c:92
23
#9 0x55d6899b717d in resettable_phase_enter ../hw/core/resettable.c:129
24
#10 0x55d6899b7bfa in resettable_assert_reset ../hw/core/resettable.c:55
25
#11 0x55d6899b8666 in resettable_reset ../hw/core/resettable.c:45
26
#12 0x55d688d15cd2 in qemu_system_reset ../system/runstate.c:527
27
#13 0x55d687fc5edd in qdev_machine_creation_done ../hw/core/machine.c:1738
28
#14 0x55d688d209bd in qemu_machine_creation_done ../system/vl.c:2779
29
#15 0x55d688d209bd in qmp_x_exit_preconfig ../system/vl.c:2807
30
#16 0x55d688d281fb in qemu_init ../system/vl.c:3838
31
#17 0x55d687ceab12 in main ../system/main.c:68
32
#18 0x7fcaef006249 (/lib/x86_64-linux-gnu/libc.so.6+0x27249)
33
#19 0x7fcaef006304 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x27304)
34
#20 0x55d687cf0010 in _start (/home/runner/work/qemu-ci/qemu-ci/build/qemu-system-arm+0x371c010)
35
36
0x55d68a3e97f0 is located 0 bytes to the right of global variable 'npcm7xx_cold_reset_values' defined in '../hw/misc/npcm_clk.c:134:23' (0x55d68a3e9780) of size 112
37
38
Impacted tests:
39
Summary of Failures:
40
41
check:
42
2/747 qemu:qtest+qtest-aarch64 / qtest-aarch64/qom-test ERROR 9.28s killed by signal 6 SIGABRT
43
4/747 qemu:qtest+qtest-arm / qtest-arm/qom-test ERROR 7.82s killed by signal 6 SIGABRT
44
32/747 qemu:qtest+qtest-aarch64 / qtest-aarch64/device-introspect-test ERROR 10.91s killed by signal 6 SIGABRT
45
35/747 qemu:qtest+qtest-arm / qtest-arm/device-introspect-test ERROR 11.33s killed by signal 6 SIGABRT
46
114/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_pwm-test ERROR 0.98s killed by signal 6 SIGABRT
47
115/747 qemu:qtest+qtest-aarch64 / qtest-aarch64/test-hmp ERROR 2.95s killed by signal 6 SIGABRT
48
117/747 qemu:qtest+qtest-arm / qtest-arm/test-hmp ERROR 2.54s killed by signal 6 SIGABRT
49
151/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_watchdog_timer-test ERROR 0.96s killed by signal 6 SIGABRT
50
247/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_adc-test ERROR 0.96s killed by signal 6 SIGABRT
51
248/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_gpio-test ERROR 1.05s killed by signal 6 SIGABRT
52
249/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_rng-test ERROR 0.97s killed by signal 6 SIGABRT
53
250/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_sdhci-test ERROR 0.97s killed by signal 6 SIGABRT
54
251/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_smbus-test ERROR 0.89s killed by signal 6 SIGABRT
55
252/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_timer-test ERROR 1.09s killed by signal 6 SIGABRT
56
253/747 qemu:qtest+qtest-arm / qtest-arm/npcm_gmac-test ERROR 1.12s killed by signal 6 SIGABRT
57
255/747 qemu:qtest+qtest-arm / qtest-arm/npcm7xx_emc-test ERROR 1.05s killed by signal 6 SIGABRT
58
59
check-functional:
60
22/203 qemu:func-thorough+func-arm-thorough+thorough / func-arm-arm_quanta_gsj ERROR 0.79s exit status 1
61
38/203 qemu:func-quick+func-aarch64 / func-aarch64-migration ERROR 1.97s exit status 1
62
45/203 qemu:func-quick+func-arm / func-arm-migration ERROR 1.90s exit status 1
63
64
Fixes: cf76c4e174e1 ("hw/misc: Add nr_regs and cold_reset_values to NPCM CLK")
65
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
66
Reviewed-by: Hao Wu <wuhaotsh@google.com>
67
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
68
---
69
hw/misc/npcm_clk.c | 5 +++--
70
1 file changed, 3 insertions(+), 2 deletions(-)
71
72
diff --git a/hw/misc/npcm_clk.c b/hw/misc/npcm_clk.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/misc/npcm_clk.c
75
+++ b/hw/misc/npcm_clk.c
76
@@ -XXX,XX +XXX,XX @@ static void npcm_clk_enter_reset(Object *obj, ResetType type)
77
NPCMCLKState *s = NPCM_CLK(obj);
78
NPCMCLKClass *c = NPCM_CLK_GET_CLASS(s);
79
80
- g_assert(sizeof(s->regs) >= c->nr_regs * sizeof(uint32_t));
81
- memcpy(s->regs, c->cold_reset_values, sizeof(s->regs));
82
+ size_t sizeof_regs = c->nr_regs * sizeof(uint32_t);
83
+ g_assert(sizeof(s->regs) >= sizeof_regs);
84
+ memcpy(s->regs, c->cold_reset_values, sizeof_regs);
85
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
86
npcm7xx_clk_update_all_clocks(s);
87
/*
88
--
89
2.43.0
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
While at it add missing GUSB2RHBCTL register as found in i.MX 8M Plus reference
4
manual.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Message-id: 20250223114708.1780-2-shentey@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/usb/hcd-dwc3.h | 2 +-
12
hw/usb/hcd-dwc3.c | 5 +++++
13
2 files changed, 6 insertions(+), 1 deletion(-)
14
15
diff --git a/include/hw/usb/hcd-dwc3.h b/include/hw/usb/hcd-dwc3.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/usb/hcd-dwc3.h
18
+++ b/include/hw/usb/hcd-dwc3.h
19
@@ -XXX,XX +XXX,XX @@
20
#define USB_DWC3(obj) \
21
OBJECT_CHECK(USBDWC3, (obj), TYPE_USB_DWC3)
22
23
-#define USB_DWC3_R_MAX ((0x530 / 4) + 1)
24
+#define USB_DWC3_R_MAX (0x600 / 4)
25
#define DWC3_SIZE 0x10000
26
27
typedef struct USBDWC3 {
28
diff --git a/hw/usb/hcd-dwc3.c b/hw/usb/hcd-dwc3.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/usb/hcd-dwc3.c
31
+++ b/hw/usb/hcd-dwc3.c
32
@@ -XXX,XX +XXX,XX @@ REG32(GFLADJ, 0x530)
33
FIELD(GFLADJ, GFLADJ_REFCLK_FLADJ, 8, 14)
34
FIELD(GFLADJ, GFLADJ_30MHZ_SDBND_SEL, 7, 1)
35
FIELD(GFLADJ, GFLADJ_30MHZ, 0, 6)
36
+REG32(GUSB2RHBCTL, 0x540)
37
+ FIELD(GUSB2RHBCTL, OVRD_L1TIMEOUT, 0, 4)
38
39
#define DWC3_GLOBAL_OFFSET 0xC100
40
static void reset_csr(USBDWC3 * s)
41
@@ -XXX,XX +XXX,XX @@ static const RegisterAccessInfo usb_dwc3_regs_info[] = {
42
.rsvd = 0x40,
43
.ro = 0x400040,
44
.unimp = 0xffffffff,
45
+ },{ .name = "GUSB2RHBCTL", .addr = A_GUSB2RHBCTL,
46
+ .rsvd = 0xfffffff0,
47
+ .unimp = 0xffffffff,
48
}
49
};
50
51
--
52
2.43.0
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
On the real device, the PCIe root bus is only connected to a PCIe bridge and
4
does not allow for direct attachment of devices. Doing so in QEMU results in no
5
PCI devices being detected by Linux. Instead, PCI devices should plug into the
6
secondary PCIe bus spawned by the internal PCIe bridge.
7
8
Unfortunately, QEMU defaults to plugging devices into the PCIe root bus. To work
9
around this, every PCI device created on the command line needs an extra
10
`bus=dw-pcie` option which is error prone. Fix that by marking the PCIe root bus
11
as full which makes QEMU decend into the child PCIe bus.
12
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Message-id: 20250223114708.1780-3-shentey@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/hw/pci-host/designware.h | 7 +++++++
19
hw/pci-host/designware.c | 18 +++++++++++++++++-
20
2 files changed, 24 insertions(+), 1 deletion(-)
21
22
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/pci-host/designware.h
25
+++ b/include/hw/pci-host/designware.h
26
@@ -XXX,XX +XXX,XX @@
27
#include "hw/pci/pci_bridge.h"
28
#include "qom/object.h"
29
30
+#define TYPE_DESIGNWARE_PCIE_ROOT_BUS "designware-pcie-root-BUS"
31
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERootBus, DESIGNWARE_PCIE_ROOT_BUS)
32
+
33
#define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
34
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
35
36
#define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
37
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
38
39
+struct DesignwarePCIERootBus {
40
+ PCIBus parent;
41
+};
42
+
43
typedef struct DesignwarePCIEViewport {
44
DesignwarePCIERoot *root;
45
46
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/pci-host/designware.c
49
+++ b/hw/pci-host/designware.c
50
@@ -XXX,XX +XXX,XX @@
51
#define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff)
52
#define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C
53
54
+static void designware_pcie_root_bus_class_init(ObjectClass *klass, void *data)
55
+{
56
+ BusClass *k = BUS_CLASS(klass);
57
+
58
+ /*
59
+ * Designware has only a single root complex. Enforce the limit on the
60
+ * parent bus
61
+ */
62
+ k->max_dev = 1;
63
+}
64
+
65
static DesignwarePCIEHost *
66
designware_pcie_root_to_host(DesignwarePCIERoot *root)
67
{
68
@@ -XXX,XX +XXX,XX @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
69
&s->pci.memory,
70
&s->pci.io,
71
0, 4,
72
- TYPE_PCIE_BUS);
73
+ TYPE_DESIGNWARE_PCIE_ROOT_BUS);
74
pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
75
76
memory_region_init(&s->pci.address_space_root,
77
@@ -XXX,XX +XXX,XX @@ static void designware_pcie_host_init(Object *obj)
78
79
static const TypeInfo designware_pcie_types[] = {
80
{
81
+ .name = TYPE_DESIGNWARE_PCIE_ROOT_BUS,
82
+ .parent = TYPE_PCIE_BUS,
83
+ .instance_size = sizeof(DesignwarePCIERootBus),
84
+ .class_init = designware_pcie_root_bus_class_init,
85
+ }, {
86
.name = TYPE_DESIGNWARE_PCIE_HOST,
87
.parent = TYPE_PCI_HOST_BRIDGE,
88
.instance_size = sizeof(DesignwarePCIEHost),
89
--
90
2.43.0
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add support for "TX complete"/TXDC interrupt generate by real HW since
3
The move of the Kconfig bits to hw/gpio is fixing a bug in 6328d8ffa6cb9d
4
it is needed to support guests other than Linux.
4
("misc/pca955*: Move models under hw/gpio"), which moved the code but forgot to
5
move the Kconfig sections.
5
6
6
Based on the patch by Bill Paul as found here:
7
Fixes: 6328d8ffa6cb9d "misc/pca955*: Move models under hw/gpio"
7
https://bugs.launchpad.net/qemu/+bug/1753314
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
9
Message-id: 20250223114708.1780-4-shentey@gmail.com
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>
15
Message-id: 20180315191141.6789-2-andrew.smirnov@gmail.com
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
12
---
19
include/hw/char/imx_serial.h | 3 +++
13
hw/gpio/Kconfig | 8 ++++++++
20
hw/char/imx_serial.c | 20 +++++++++++++++++---
14
hw/misc/Kconfig | 8 --------
21
2 files changed, 20 insertions(+), 3 deletions(-)
15
2 files changed, 8 insertions(+), 8 deletions(-)
22
16
23
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
17
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/char/imx_serial.h
19
--- a/hw/gpio/Kconfig
26
+++ b/include/hw/char/imx_serial.h
20
+++ b/hw/gpio/Kconfig
27
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ config SIFIVE_GPIO
28
#define UCR2_RXEN (1<<1) /* Receiver enable */
22
config STM32L4X5_GPIO
29
#define UCR2_SRST (1<<0) /* Reset complete */
23
bool
30
24
31
+#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
25
+config PCA9552
26
+ bool
27
+ depends on I2C
32
+
28
+
33
#define UTS1_TXEMPTY (1<<6)
29
+config PCA9554
34
#define UTS1_RXEMPTY (1<<5)
30
+ bool
35
#define UTS1_TXFULL (1<<4)
31
+ depends on I2C
36
@@ -XXX,XX +XXX,XX @@ typedef struct IMXSerialState {
32
+
37
uint32_t ubmr;
33
config PCF8574
38
uint32_t ubrc;
34
bool
39
uint32_t ucr3;
35
depends on I2C
40
+ uint32_t ucr4;
36
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
41
42
qemu_irq irq;
43
CharBackend chr;
44
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
45
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/char/imx_serial.c
38
--- a/hw/misc/Kconfig
47
+++ b/hw/char/imx_serial.c
39
+++ b/hw/misc/Kconfig
48
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@ config EDU
49
41
default y if TEST_DEVICES
50
static const VMStateDescription vmstate_imx_serial = {
42
depends on PCI && MSI_NONBROKEN
51
.name = TYPE_IMX_SERIAL,
43
52
- .version_id = 1,
44
-config PCA9552
53
- .minimum_version_id = 1,
45
- bool
54
+ .version_id = 2,
46
- depends on I2C
55
+ .minimum_version_id = 2,
47
-
56
.fields = (VMStateField[]) {
48
-config PCA9554
57
VMSTATE_INT32(readbuff, IMXSerialState),
49
- bool
58
VMSTATE_UINT32(usr1, IMXSerialState),
50
- depends on I2C
59
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_serial = {
51
-
60
VMSTATE_UINT32(ubmr, IMXSerialState),
52
config I2C_ECHO
61
VMSTATE_UINT32(ubrc, IMXSerialState),
53
bool
62
VMSTATE_UINT32(ucr3, IMXSerialState),
54
default y if TEST_DEVICES
63
+ VMSTATE_UINT32(ucr4, IMXSerialState),
64
VMSTATE_END_OF_LIST()
65
},
66
};
67
@@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s)
68
* unfortunately.
69
*/
70
mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
71
+ /*
72
+ * TCEN and TXDC are both bit 3
73
+ */
74
+ mask |= s->ucr4 & UCR4_TCEN;
75
+
76
usr2 = s->usr2 & mask;
77
78
qemu_set_irq(s->irq, usr1 || usr2);
79
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
80
return s->ucr3;
81
82
case 0x23: /* UCR4 */
83
+ return s->ucr4;
84
+
85
case 0x29: /* BRM Incremental */
86
return 0x0; /* TODO */
87
88
@@ -XXX,XX +XXX,XX @@ static void imx_serial_write(void *opaque, hwaddr offset,
89
* qemu_chr_fe_write and background I/O callbacks */
90
qemu_chr_fe_write_all(&s->chr, &ch, 1);
91
s->usr1 &= ~USR1_TRDY;
92
+ s->usr2 &= ~USR2_TXDC;
93
imx_update(s);
94
s->usr1 |= USR1_TRDY;
95
+ s->usr2 |= USR2_TXDC;
96
imx_update(s);
97
}
98
break;
99
@@ -XXX,XX +XXX,XX @@ static void imx_serial_write(void *opaque, hwaddr offset,
100
s->ucr3 = value & 0xffff;
101
break;
102
103
- case 0x2d: /* UTS1 */
104
case 0x23: /* UCR4 */
105
+ s->ucr4 = value & 0xffff;
106
+ imx_update(s);
107
+ break;
108
+
109
+ case 0x2d: /* UTS1 */
110
qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
111
HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
112
/* TODO */
113
--
55
--
114
2.16.2
56
2.43.0
115
116
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
4
serial. All other devices of the A53 memory map are represented as
5
TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
6
for running Linux without it crashing due to invalid memory accesses.
7
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20250223114708.1780-5-shentey@gmail.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: drop 'static const' from serial_table[] definition to avoid
12
compile failure on GCC 7.5]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
MAINTAINERS | 9 +
16
docs/system/arm/imx8mp-evk.rst | 54 +++++
17
docs/system/target-arm.rst | 1 +
18
include/hw/arm/fsl-imx8mp.h | 189 +++++++++++++++++
19
hw/arm/fsl-imx8mp.c | 367 +++++++++++++++++++++++++++++++++
20
hw/arm/imx8mp-evk.c | 55 +++++
21
hw/arm/Kconfig | 12 ++
22
hw/arm/meson.build | 2 +
23
8 files changed, 689 insertions(+)
24
create mode 100644 docs/system/arm/imx8mp-evk.rst
25
create mode 100644 include/hw/arm/fsl-imx8mp.h
26
create mode 100644 hw/arm/fsl-imx8mp.c
27
create mode 100644 hw/arm/imx8mp-evk.c
28
29
diff --git a/MAINTAINERS b/MAINTAINERS
30
index XXXXXXX..XXXXXXX 100644
31
--- a/MAINTAINERS
32
+++ b/MAINTAINERS
33
@@ -XXX,XX +XXX,XX @@ F: hw/pci-host/designware.c
34
F: include/hw/pci-host/designware.h
35
F: docs/system/arm/mcimx7d-sabre.rst
36
37
+MCIMX8MP-EVK / i.MX8MP
38
+M: Bernhard Beschow <shentey@gmail.com>
39
+L: qemu-arm@nongnu.org
40
+S: Maintained
41
+F: hw/arm/imx8mp-evk.c
42
+F: hw/arm/fsl-imx8mp.c
43
+F: include/hw/arm/fsl-imx8mp.h
44
+F: docs/system/arm/imx8mp-evk.rst
45
+
46
MPS2 / MPS3
47
M: Peter Maydell <peter.maydell@linaro.org>
48
L: qemu-arm@nongnu.org
49
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
50
new file mode 100644
51
index XXXXXXX..XXXXXXX
52
--- /dev/null
53
+++ b/docs/system/arm/imx8mp-evk.rst
54
@@ -XXX,XX +XXX,XX @@
55
+NXP i.MX 8M Plus Evaluation Kit (``imx8mp-evk``)
56
+================================================
57
+
58
+The ``imx8mp-evk`` machine models the i.MX 8M Plus Evaluation Kit, based on an
59
+i.MX 8M Plus SoC.
60
+
61
+Supported devices
62
+-----------------
63
+
64
+The ``imx8mp-evk`` machine implements the following devices:
65
+
66
+ * Up to 4 Cortex-A53 cores
67
+ * Generic Interrupt Controller (GICv3)
68
+ * 4 UARTs
69
+
70
+Boot options
71
+------------
72
+
73
+The ``imx8mp-evk`` machine can start a Linux kernel directly using the standard
74
+``-kernel`` functionality.
75
+
76
+Direct Linux Kernel Boot
77
+''''''''''''''''''''''''
78
+
79
+Probably the easiest way to get started with a whole Linux system on the machine
80
+is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
81
+of writing and involves two steps. First run the following commands in the
82
+toplevel directory of the Buildroot source tree:
83
+
84
+.. code-block:: bash
85
+
86
+ $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
87
+ $ make freescale_imx8mpevk_defconfig
88
+ $ make
89
+
90
+Once finished successfully there is an ``output/image`` subfolder. Navigate into
91
+it and patch the device tree with the following commands which will remove the
92
+``cpu-idle-states`` properties from CPU nodes:
93
+
94
+.. code-block:: bash
95
+
96
+ $ dtc imx8mp-evk.dtb | sed '/cpu-idle-states/d' > imx8mp-evk-patched.dts
97
+ $ dtc imx8mp-evk-patched.dts -o imx8mp-evk-patched.dtb
98
+
99
+Now that everything is prepared the machine can be started as follows:
100
+
101
+.. code-block:: bash
102
+
103
+ $ qemu-system-aarch64 -M imx8mp-evk -smp 4 -m 3G \
104
+ -display none -serial null -serial stdio \
105
+ -kernel Image \
106
+ -dtb imx8mp-evk-patched.dtb \
107
+ -initrd rootfs.cpio \
108
+ -append "root=/dev/ram"
109
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
110
index XXXXXXX..XXXXXXX 100644
111
--- a/docs/system/target-arm.rst
112
+++ b/docs/system/target-arm.rst
113
@@ -XXX,XX +XXX,XX @@ Board-specific documentation
114
arm/imx25-pdk
115
arm/mcimx6ul-evk
116
arm/mcimx7d-sabre
117
+ arm/imx8mp-evk
118
arm/orangepi
119
arm/raspi
120
arm/collie
121
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
122
new file mode 100644
123
index XXXXXXX..XXXXXXX
124
--- /dev/null
125
+++ b/include/hw/arm/fsl-imx8mp.h
126
@@ -XXX,XX +XXX,XX @@
127
+/*
128
+ * i.MX 8M Plus SoC Definitions
129
+ *
130
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
131
+ *
132
+ * SPDX-License-Identifier: GPL-2.0-or-later
133
+ */
134
+
135
+#ifndef FSL_IMX8MP_H
136
+#define FSL_IMX8MP_H
137
+
138
+#include "cpu.h"
139
+#include "hw/char/imx_serial.h"
140
+#include "hw/intc/arm_gicv3_common.h"
141
+#include "qom/object.h"
142
+#include "qemu/units.h"
143
+
144
+#define TYPE_FSL_IMX8MP "fsl-imx8mp"
145
+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
146
+
147
+#define FSL_IMX8MP_RAM_START 0x40000000
148
+#define FSL_IMX8MP_RAM_SIZE_MAX (8 * GiB)
149
+
150
+enum FslImx8mpConfiguration {
151
+ FSL_IMX8MP_NUM_CPUS = 4,
152
+ FSL_IMX8MP_NUM_IRQS = 160,
153
+ FSL_IMX8MP_NUM_UARTS = 4,
154
+};
155
+
156
+struct FslImx8mpState {
157
+ DeviceState parent_obj;
158
+
159
+ ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
160
+ GICv3State gic;
161
+ IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
162
+};
163
+
164
+enum FslImx8mpMemoryRegions {
165
+ FSL_IMX8MP_A53_DAP,
166
+ FSL_IMX8MP_AIPS1_CONFIGURATION,
167
+ FSL_IMX8MP_AIPS2_CONFIGURATION,
168
+ FSL_IMX8MP_AIPS3_CONFIGURATION,
169
+ FSL_IMX8MP_AIPS4_CONFIGURATION,
170
+ FSL_IMX8MP_AIPS5_CONFIGURATION,
171
+ FSL_IMX8MP_ANA_OSC,
172
+ FSL_IMX8MP_ANA_PLL,
173
+ FSL_IMX8MP_ANA_TSENSOR,
174
+ FSL_IMX8MP_APBH_DMA,
175
+ FSL_IMX8MP_ASRC,
176
+ FSL_IMX8MP_AUDIO_BLK_CTRL,
177
+ FSL_IMX8MP_AUDIO_DSP,
178
+ FSL_IMX8MP_AUDIO_XCVR_RX,
179
+ FSL_IMX8MP_AUD_IRQ_STEER,
180
+ FSL_IMX8MP_BOOT_ROM,
181
+ FSL_IMX8MP_BOOT_ROM_PROTECTED,
182
+ FSL_IMX8MP_CAAM,
183
+ FSL_IMX8MP_CAAM_MEM,
184
+ FSL_IMX8MP_CCM,
185
+ FSL_IMX8MP_CSU,
186
+ FSL_IMX8MP_DDR_BLK_CTRL,
187
+ FSL_IMX8MP_DDR_CTL,
188
+ FSL_IMX8MP_DDR_PERF_MON,
189
+ FSL_IMX8MP_DDR_PHY,
190
+ FSL_IMX8MP_DDR_PHY_BROADCAST,
191
+ FSL_IMX8MP_ECSPI1,
192
+ FSL_IMX8MP_ECSPI2,
193
+ FSL_IMX8MP_ECSPI3,
194
+ FSL_IMX8MP_EDMA_CHANNELS,
195
+ FSL_IMX8MP_EDMA_MANAGEMENT_PAGE,
196
+ FSL_IMX8MP_ENET1,
197
+ FSL_IMX8MP_ENET2_TSN,
198
+ FSL_IMX8MP_FLEXCAN1,
199
+ FSL_IMX8MP_FLEXCAN2,
200
+ FSL_IMX8MP_GIC_DIST,
201
+ FSL_IMX8MP_GIC_REDIST,
202
+ FSL_IMX8MP_GPC,
203
+ FSL_IMX8MP_GPIO1,
204
+ FSL_IMX8MP_GPIO2,
205
+ FSL_IMX8MP_GPIO3,
206
+ FSL_IMX8MP_GPIO4,
207
+ FSL_IMX8MP_GPIO5,
208
+ FSL_IMX8MP_GPT1,
209
+ FSL_IMX8MP_GPT2,
210
+ FSL_IMX8MP_GPT3,
211
+ FSL_IMX8MP_GPT4,
212
+ FSL_IMX8MP_GPT5,
213
+ FSL_IMX8MP_GPT6,
214
+ FSL_IMX8MP_GPU2D,
215
+ FSL_IMX8MP_GPU3D,
216
+ FSL_IMX8MP_HDMI_TX,
217
+ FSL_IMX8MP_HDMI_TX_AUDLNK_MSTR,
218
+ FSL_IMX8MP_HSIO_BLK_CTL,
219
+ FSL_IMX8MP_I2C1,
220
+ FSL_IMX8MP_I2C2,
221
+ FSL_IMX8MP_I2C3,
222
+ FSL_IMX8MP_I2C4,
223
+ FSL_IMX8MP_I2C5,
224
+ FSL_IMX8MP_I2C6,
225
+ FSL_IMX8MP_INTERCONNECT,
226
+ FSL_IMX8MP_IOMUXC,
227
+ FSL_IMX8MP_IOMUXC_GPR,
228
+ FSL_IMX8MP_IPS_DEWARP,
229
+ FSL_IMX8MP_ISI,
230
+ FSL_IMX8MP_ISP1,
231
+ FSL_IMX8MP_ISP2,
232
+ FSL_IMX8MP_LCDIF1,
233
+ FSL_IMX8MP_LCDIF2,
234
+ FSL_IMX8MP_MEDIA_BLK_CTL,
235
+ FSL_IMX8MP_MIPI_CSI1,
236
+ FSL_IMX8MP_MIPI_CSI2,
237
+ FSL_IMX8MP_MIPI_DSI1,
238
+ FSL_IMX8MP_MU_1_A,
239
+ FSL_IMX8MP_MU_1_B,
240
+ FSL_IMX8MP_MU_2_A,
241
+ FSL_IMX8MP_MU_2_B,
242
+ FSL_IMX8MP_MU_3_A,
243
+ FSL_IMX8MP_MU_3_B,
244
+ FSL_IMX8MP_NPU,
245
+ FSL_IMX8MP_OCOTP_CTRL,
246
+ FSL_IMX8MP_OCRAM,
247
+ FSL_IMX8MP_OCRAM_S,
248
+ FSL_IMX8MP_PCIE1,
249
+ FSL_IMX8MP_PCIE1_MEM,
250
+ FSL_IMX8MP_PCIE_PHY1,
251
+ FSL_IMX8MP_PDM,
252
+ FSL_IMX8MP_PERFMON1,
253
+ FSL_IMX8MP_PERFMON2,
254
+ FSL_IMX8MP_PWM1,
255
+ FSL_IMX8MP_PWM2,
256
+ FSL_IMX8MP_PWM3,
257
+ FSL_IMX8MP_PWM4,
258
+ FSL_IMX8MP_QOSC,
259
+ FSL_IMX8MP_QSPI,
260
+ FSL_IMX8MP_QSPI1_RX_BUFFER,
261
+ FSL_IMX8MP_QSPI1_TX_BUFFER,
262
+ FSL_IMX8MP_QSPI_MEM,
263
+ FSL_IMX8MP_RAM,
264
+ FSL_IMX8MP_RDC,
265
+ FSL_IMX8MP_SAI1,
266
+ FSL_IMX8MP_SAI2,
267
+ FSL_IMX8MP_SAI3,
268
+ FSL_IMX8MP_SAI5,
269
+ FSL_IMX8MP_SAI6,
270
+ FSL_IMX8MP_SAI7,
271
+ FSL_IMX8MP_SDMA1,
272
+ FSL_IMX8MP_SDMA2,
273
+ FSL_IMX8MP_SDMA3,
274
+ FSL_IMX8MP_SEMAPHORE1,
275
+ FSL_IMX8MP_SEMAPHORE2,
276
+ FSL_IMX8MP_SEMAPHORE_HS,
277
+ FSL_IMX8MP_SNVS_HP,
278
+ FSL_IMX8MP_SPBA1,
279
+ FSL_IMX8MP_SPBA2,
280
+ FSL_IMX8MP_SRC,
281
+ FSL_IMX8MP_SYSCNT_CMP,
282
+ FSL_IMX8MP_SYSCNT_CTRL,
283
+ FSL_IMX8MP_SYSCNT_RD,
284
+ FSL_IMX8MP_TCM_DTCM,
285
+ FSL_IMX8MP_TCM_ITCM,
286
+ FSL_IMX8MP_TZASC,
287
+ FSL_IMX8MP_UART1,
288
+ FSL_IMX8MP_UART2,
289
+ FSL_IMX8MP_UART3,
290
+ FSL_IMX8MP_UART4,
291
+ FSL_IMX8MP_USB1,
292
+ FSL_IMX8MP_USB2,
293
+ FSL_IMX8MP_USDHC1,
294
+ FSL_IMX8MP_USDHC2,
295
+ FSL_IMX8MP_USDHC3,
296
+ FSL_IMX8MP_VPU,
297
+ FSL_IMX8MP_VPU_BLK_CTRL,
298
+ FSL_IMX8MP_VPU_G1_DECODER,
299
+ FSL_IMX8MP_VPU_G2_DECODER,
300
+ FSL_IMX8MP_VPU_VC8000E_ENCODER,
301
+ FSL_IMX8MP_WDOG1,
302
+ FSL_IMX8MP_WDOG2,
303
+ FSL_IMX8MP_WDOG3,
304
+};
305
+
306
+enum FslImx8mpIrqs {
307
+ FSL_IMX8MP_UART1_IRQ = 26,
308
+ FSL_IMX8MP_UART2_IRQ = 27,
309
+ FSL_IMX8MP_UART3_IRQ = 28,
310
+ FSL_IMX8MP_UART4_IRQ = 29,
311
+ FSL_IMX8MP_UART5_IRQ = 30,
312
+ FSL_IMX8MP_UART6_IRQ = 16,
313
+};
314
+
315
+#endif /* FSL_IMX8MP_H */
316
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
317
new file mode 100644
318
index XXXXXXX..XXXXXXX
319
--- /dev/null
320
+++ b/hw/arm/fsl-imx8mp.c
321
@@ -XXX,XX +XXX,XX @@
322
+/*
323
+ * i.MX 8M Plus SoC Implementation
324
+ *
325
+ * Based on hw/arm/fsl-imx6.c
326
+ *
327
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
328
+ *
329
+ * SPDX-License-Identifier: GPL-2.0-or-later
330
+ */
331
+
332
+#include "qemu/osdep.h"
333
+#include "exec/address-spaces.h"
334
+#include "hw/arm/bsa.h"
335
+#include "hw/arm/fsl-imx8mp.h"
336
+#include "hw/intc/arm_gicv3.h"
337
+#include "hw/misc/unimp.h"
338
+#include "hw/boards.h"
339
+#include "system/system.h"
340
+#include "target/arm/cpu-qom.h"
341
+#include "qapi/error.h"
342
+#include "qobject/qlist.h"
343
+
344
+static const struct {
345
+ hwaddr addr;
346
+ size_t size;
347
+ const char *name;
348
+} fsl_imx8mp_memmap[] = {
349
+ [FSL_IMX8MP_RAM] = { FSL_IMX8MP_RAM_START, FSL_IMX8MP_RAM_SIZE_MAX, "ram" },
350
+ [FSL_IMX8MP_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
351
+ [FSL_IMX8MP_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
352
+ [FSL_IMX8MP_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
353
+ [FSL_IMX8MP_DDR_BLK_CTRL] = { 0x3d000000, 1 * MiB, "ddr_blk_ctrl" },
354
+ [FSL_IMX8MP_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
355
+ [FSL_IMX8MP_AUDIO_DSP] = { 0x3b000000, 16 * MiB, "audio_dsp" },
356
+ [FSL_IMX8MP_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
357
+ [FSL_IMX8MP_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
358
+ [FSL_IMX8MP_NPU] = { 0x38500000, 2 * MiB, "npu" },
359
+ [FSL_IMX8MP_VPU] = { 0x38340000, 2 * MiB, "vpu" },
360
+ [FSL_IMX8MP_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
361
+ [FSL_IMX8MP_VPU_VC8000E_ENCODER] = { 0x38320000, 2 * MiB, "vpu_vc8000e_encoder" },
362
+ [FSL_IMX8MP_VPU_G2_DECODER] = { 0x38310000, 2 * MiB, "vpu_g2_decoder" },
363
+ [FSL_IMX8MP_VPU_G1_DECODER] = { 0x38300000, 2 * MiB, "vpu_g1_decoder" },
364
+ [FSL_IMX8MP_USB2] = { 0x38200000, 1 * MiB, "usb2" },
365
+ [FSL_IMX8MP_USB1] = { 0x38100000, 1 * MiB, "usb1" },
366
+ [FSL_IMX8MP_GPU2D] = { 0x38008000, 32 * KiB, "gpu2d" },
367
+ [FSL_IMX8MP_GPU3D] = { 0x38000000, 32 * KiB, "gpu3d" },
368
+ [FSL_IMX8MP_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
369
+ [FSL_IMX8MP_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
370
+ [FSL_IMX8MP_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
371
+ [FSL_IMX8MP_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
372
+
373
+ /* AIPS-5 Begin */
374
+ [FSL_IMX8MP_MU_3_B] = { 0x30e90000, 64 * KiB, "mu_3_b" },
375
+ [FSL_IMX8MP_MU_3_A] = { 0x30e80000, 64 * KiB, "mu_3_a" },
376
+ [FSL_IMX8MP_MU_2_B] = { 0x30e70000, 64 * KiB, "mu_2_b" },
377
+ [FSL_IMX8MP_MU_2_A] = { 0x30e60000, 64 * KiB, "mu_2_a" },
378
+ [FSL_IMX8MP_EDMA_CHANNELS] = { 0x30e40000, 128 * KiB, "edma_channels" },
379
+ [FSL_IMX8MP_EDMA_MANAGEMENT_PAGE] = { 0x30e30000, 64 * KiB, "edma_management_page" },
380
+ [FSL_IMX8MP_AUDIO_BLK_CTRL] = { 0x30e20000, 64 * KiB, "audio_blk_ctrl" },
381
+ [FSL_IMX8MP_SDMA2] = { 0x30e10000, 64 * KiB, "sdma2" },
382
+ [FSL_IMX8MP_SDMA3] = { 0x30e00000, 64 * KiB, "sdma3" },
383
+ [FSL_IMX8MP_AIPS5_CONFIGURATION] = { 0x30df0000, 64 * KiB, "aips5_configuration" },
384
+ [FSL_IMX8MP_SPBA2] = { 0x30cf0000, 64 * KiB, "spba2" },
385
+ [FSL_IMX8MP_AUDIO_XCVR_RX] = { 0x30cc0000, 64 * KiB, "audio_xcvr_rx" },
386
+ [FSL_IMX8MP_HDMI_TX_AUDLNK_MSTR] = { 0x30cb0000, 64 * KiB, "hdmi_tx_audlnk_mstr" },
387
+ [FSL_IMX8MP_PDM] = { 0x30ca0000, 64 * KiB, "pdm" },
388
+ [FSL_IMX8MP_ASRC] = { 0x30c90000, 64 * KiB, "asrc" },
389
+ [FSL_IMX8MP_SAI7] = { 0x30c80000, 64 * KiB, "sai7" },
390
+ [FSL_IMX8MP_SAI6] = { 0x30c60000, 64 * KiB, "sai6" },
391
+ [FSL_IMX8MP_SAI5] = { 0x30c50000, 64 * KiB, "sai5" },
392
+ [FSL_IMX8MP_SAI3] = { 0x30c30000, 64 * KiB, "sai3" },
393
+ [FSL_IMX8MP_SAI2] = { 0x30c20000, 64 * KiB, "sai2" },
394
+ [FSL_IMX8MP_SAI1] = { 0x30c10000, 64 * KiB, "sai1" },
395
+ /* AIPS-5 End */
396
+
397
+ /* AIPS-4 Begin */
398
+ [FSL_IMX8MP_HDMI_TX] = { 0x32fc0000, 128 * KiB, "hdmi_tx" },
399
+ [FSL_IMX8MP_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
400
+ [FSL_IMX8MP_HSIO_BLK_CTL] = { 0x32f10000, 64 * KiB, "hsio_blk_ctl" },
401
+ [FSL_IMX8MP_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
402
+ [FSL_IMX8MP_MEDIA_BLK_CTL] = { 0x32ec0000, 64 * KiB, "media_blk_ctl" },
403
+ [FSL_IMX8MP_LCDIF2] = { 0x32e90000, 64 * KiB, "lcdif2" },
404
+ [FSL_IMX8MP_LCDIF1] = { 0x32e80000, 64 * KiB, "lcdif1" },
405
+ [FSL_IMX8MP_MIPI_DSI1] = { 0x32e60000, 64 * KiB, "mipi_dsi1" },
406
+ [FSL_IMX8MP_MIPI_CSI2] = { 0x32e50000, 64 * KiB, "mipi_csi2" },
407
+ [FSL_IMX8MP_MIPI_CSI1] = { 0x32e40000, 64 * KiB, "mipi_csi1" },
408
+ [FSL_IMX8MP_IPS_DEWARP] = { 0x32e30000, 64 * KiB, "ips_dewarp" },
409
+ [FSL_IMX8MP_ISP2] = { 0x32e20000, 64 * KiB, "isp2" },
410
+ [FSL_IMX8MP_ISP1] = { 0x32e10000, 64 * KiB, "isp1" },
411
+ [FSL_IMX8MP_ISI] = { 0x32e00000, 64 * KiB, "isi" },
412
+ [FSL_IMX8MP_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
413
+ /* AIPS-4 End */
414
+
415
+ [FSL_IMX8MP_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect" },
416
+
417
+ /* AIPS-3 Begin */
418
+ [FSL_IMX8MP_ENET2_TSN] = { 0x30bf0000, 64 * KiB, "enet2_tsn" },
419
+ [FSL_IMX8MP_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
420
+ [FSL_IMX8MP_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
421
+ [FSL_IMX8MP_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
422
+ [FSL_IMX8MP_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
423
+ [FSL_IMX8MP_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
424
+ [FSL_IMX8MP_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
425
+ [FSL_IMX8MP_I2C6] = { 0x30ae0000, 64 * KiB, "i2c6" },
426
+ [FSL_IMX8MP_I2C5] = { 0x30ad0000, 64 * KiB, "i2c5" },
427
+ [FSL_IMX8MP_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
428
+ [FSL_IMX8MP_MU_1_B] = { 0x30ab0000, 64 * KiB, "mu_1_b" },
429
+ [FSL_IMX8MP_MU_1_A] = { 0x30aa0000, 64 * KiB, "mu_1_a" },
430
+ [FSL_IMX8MP_AUD_IRQ_STEER] = { 0x30a80000, 64 * KiB, "aud_irq_steer" },
431
+ [FSL_IMX8MP_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
432
+ [FSL_IMX8MP_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
433
+ [FSL_IMX8MP_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
434
+ [FSL_IMX8MP_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
435
+ [FSL_IMX8MP_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
436
+ [FSL_IMX8MP_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
437
+ [FSL_IMX8MP_CAAM] = { 0x30900000, 256 * KiB, "caam" },
438
+ [FSL_IMX8MP_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
439
+ [FSL_IMX8MP_FLEXCAN2] = { 0x308d0000, 64 * KiB, "flexcan2" },
440
+ [FSL_IMX8MP_FLEXCAN1] = { 0x308c0000, 64 * KiB, "flexcan1" },
441
+ [FSL_IMX8MP_UART2] = { 0x30890000, 64 * KiB, "uart2" },
442
+ [FSL_IMX8MP_UART3] = { 0x30880000, 64 * KiB, "uart3" },
443
+ [FSL_IMX8MP_UART1] = { 0x30860000, 64 * KiB, "uart1" },
444
+ [FSL_IMX8MP_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
445
+ [FSL_IMX8MP_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
446
+ [FSL_IMX8MP_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
447
+ /* AIPS-3 End */
448
+
449
+ /* AIPS-2 Begin */
450
+ [FSL_IMX8MP_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
451
+ [FSL_IMX8MP_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
452
+ [FSL_IMX8MP_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
453
+ [FSL_IMX8MP_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
454
+ [FSL_IMX8MP_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
455
+ [FSL_IMX8MP_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
456
+ [FSL_IMX8MP_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
457
+ [FSL_IMX8MP_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
458
+ [FSL_IMX8MP_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
459
+ [FSL_IMX8MP_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
460
+ [FSL_IMX8MP_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
461
+ [FSL_IMX8MP_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
462
+ [FSL_IMX8MP_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
463
+ [FSL_IMX8MP_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
464
+ /* AIPS-2 End */
465
+
466
+ /* AIPS-1 Begin */
467
+ [FSL_IMX8MP_CSU] = { 0x303e0000, 64 * KiB, "csu" },
468
+ [FSL_IMX8MP_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
469
+ [FSL_IMX8MP_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
470
+ [FSL_IMX8MP_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
471
+ [FSL_IMX8MP_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
472
+ [FSL_IMX8MP_SRC] = { 0x30390000, 64 * KiB, "src" },
473
+ [FSL_IMX8MP_CCM] = { 0x30380000, 64 * KiB, "ccm" },
474
+ [FSL_IMX8MP_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
475
+ [FSL_IMX8MP_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
476
+ [FSL_IMX8MP_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
477
+ [FSL_IMX8MP_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
478
+ [FSL_IMX8MP_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
479
+ [FSL_IMX8MP_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
480
+ [FSL_IMX8MP_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
481
+ [FSL_IMX8MP_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
482
+ [FSL_IMX8MP_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
483
+ [FSL_IMX8MP_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
484
+ [FSL_IMX8MP_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
485
+ [FSL_IMX8MP_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
486
+ [FSL_IMX8MP_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
487
+ [FSL_IMX8MP_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
488
+ [FSL_IMX8MP_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
489
+ [FSL_IMX8MP_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
490
+ [FSL_IMX8MP_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
491
+ [FSL_IMX8MP_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
492
+ [FSL_IMX8MP_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
493
+ /* AIPS-1 End */
494
+
495
+ [FSL_IMX8MP_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
496
+ [FSL_IMX8MP_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
497
+ [FSL_IMX8MP_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
498
+ [FSL_IMX8MP_OCRAM] = { 0x00900000, 576 * KiB, "ocram" },
499
+ [FSL_IMX8MP_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
500
+ [FSL_IMX8MP_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
501
+ [FSL_IMX8MP_OCRAM_S] = { 0x00180000, 36 * KiB, "ocram_s" },
502
+ [FSL_IMX8MP_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
503
+ [FSL_IMX8MP_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
504
+ [FSL_IMX8MP_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" },
505
+};
506
+
507
+static void fsl_imx8mp_init(Object *obj)
508
+{
509
+ MachineState *ms = MACHINE(qdev_get_machine());
510
+ FslImx8mpState *s = FSL_IMX8MP(obj);
511
+ int i;
512
+
513
+ for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MP_NUM_CPUS); i++) {
514
+ g_autofree char *name = g_strdup_printf("cpu%d", i);
515
+ object_initialize_child(obj, name, &s->cpu[i],
516
+ ARM_CPU_TYPE_NAME("cortex-a53"));
517
+ }
518
+
519
+ object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
520
+
521
+ for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
522
+ g_autofree char *name = g_strdup_printf("uart%d", i + 1);
523
+ object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
524
+ }
525
+}
526
+
527
+static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
528
+{
529
+ MachineState *ms = MACHINE(qdev_get_machine());
530
+ FslImx8mpState *s = FSL_IMX8MP(dev);
531
+ DeviceState *gicdev = DEVICE(&s->gic);
532
+ int i;
533
+
534
+ if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
535
+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
536
+ TYPE_FSL_IMX8MP, FSL_IMX8MP_NUM_CPUS, ms->smp.cpus);
537
+ return;
538
+ }
539
+
540
+ /* CPUs */
541
+ for (i = 0; i < ms->smp.cpus; i++) {
542
+ /* On uniprocessor, the CBAR is set to 0 */
543
+ if (ms->smp.cpus > 1) {
544
+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
545
+ fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr,
546
+ &error_abort);
547
+ }
548
+
549
+ /*
550
+ * CNTFID0 base frequency in Hz of system counter
551
+ */
552
+ object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
553
+ &error_abort);
554
+
555
+ if (i) {
556
+ /*
557
+ * Secondary CPUs start in powered-down state (and can be
558
+ * powered up via the SRC system reset controller)
559
+ */
560
+ object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
561
+ true, &error_abort);
562
+ }
563
+
564
+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
565
+ return;
566
+ }
567
+ }
568
+
569
+ /* GIC */
570
+ {
571
+ SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
572
+ QList *redist_region_count;
573
+
574
+ qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
575
+ qdev_prop_set_uint32(gicdev, "num-irq",
576
+ FSL_IMX8MP_NUM_IRQS + GIC_INTERNAL);
577
+ redist_region_count = qlist_new();
578
+ qlist_append_int(redist_region_count, ms->smp.cpus);
579
+ qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
580
+ object_property_set_link(OBJECT(&s->gic), "sysmem",
581
+ OBJECT(get_system_memory()), &error_fatal);
582
+ if (!sysbus_realize(gicsbd, errp)) {
583
+ return;
584
+ }
585
+ sysbus_mmio_map(gicsbd, 0, fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr);
586
+ sysbus_mmio_map(gicsbd, 1, fsl_imx8mp_memmap[FSL_IMX8MP_GIC_REDIST].addr);
587
+
588
+ /*
589
+ * Wire the outputs from each CPU's generic timer and the GICv3
590
+ * maintenance interrupt signal to the appropriate GIC PPI inputs, and
591
+ * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
592
+ */
593
+ for (i = 0; i < ms->smp.cpus; i++) {
594
+ DeviceState *cpudev = DEVICE(&s->cpu[i]);
595
+ int intidbase = FSL_IMX8MP_NUM_IRQS + i * GIC_INTERNAL;
596
+ qemu_irq irq;
597
+
598
+ /*
599
+ * Mapping from the output timer irq lines from the CPU to the
600
+ * GIC PPI inputs.
601
+ */
602
+ static const int timer_irqs[] = {
603
+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
604
+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
605
+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
606
+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
607
+ };
608
+
609
+ for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
610
+ irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
611
+ qdev_connect_gpio_out(cpudev, j, irq);
612
+ }
613
+
614
+ irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
615
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
616
+ 0, irq);
617
+
618
+ irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
619
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, irq);
620
+
621
+ sysbus_connect_irq(gicsbd, i,
622
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
623
+ sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
624
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
625
+ }
626
+ }
627
+
628
+ /* UARTs */
629
+ for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
630
+ struct {
631
+ hwaddr addr;
632
+ unsigned int irq;
633
+ } serial_table[FSL_IMX8MP_NUM_UARTS] = {
634
+ { fsl_imx8mp_memmap[FSL_IMX8MP_UART1].addr, FSL_IMX8MP_UART1_IRQ },
635
+ { fsl_imx8mp_memmap[FSL_IMX8MP_UART2].addr, FSL_IMX8MP_UART2_IRQ },
636
+ { fsl_imx8mp_memmap[FSL_IMX8MP_UART3].addr, FSL_IMX8MP_UART3_IRQ },
637
+ { fsl_imx8mp_memmap[FSL_IMX8MP_UART4].addr, FSL_IMX8MP_UART4_IRQ },
638
+ };
639
+
640
+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
641
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
642
+ return;
643
+ }
644
+
645
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
646
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
647
+ qdev_get_gpio_in(gicdev, serial_table[i].irq));
648
+ }
649
+
650
+ /* Unimplemented devices */
651
+ for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
652
+ switch (i) {
653
+ case FSL_IMX8MP_GIC_DIST:
654
+ case FSL_IMX8MP_GIC_REDIST:
655
+ case FSL_IMX8MP_RAM:
656
+ case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
657
+ /* device implemented and treated above */
658
+ break;
659
+
660
+ default:
661
+ create_unimplemented_device(fsl_imx8mp_memmap[i].name,
662
+ fsl_imx8mp_memmap[i].addr,
663
+ fsl_imx8mp_memmap[i].size);
664
+ break;
665
+ }
666
+ }
667
+}
668
+
669
+static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
670
+{
671
+ DeviceClass *dc = DEVICE_CLASS(oc);
672
+
673
+ dc->realize = fsl_imx8mp_realize;
674
+
675
+ dc->desc = "i.MX 8M Plus SoC";
676
+}
677
+
678
+static const TypeInfo fsl_imx8mp_types[] = {
679
+ {
680
+ .name = TYPE_FSL_IMX8MP,
681
+ .parent = TYPE_DEVICE,
682
+ .instance_size = sizeof(FslImx8mpState),
683
+ .instance_init = fsl_imx8mp_init,
684
+ .class_init = fsl_imx8mp_class_init,
685
+ },
686
+};
687
+
688
+DEFINE_TYPES(fsl_imx8mp_types)
689
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
690
new file mode 100644
691
index XXXXXXX..XXXXXXX
692
--- /dev/null
693
+++ b/hw/arm/imx8mp-evk.c
694
@@ -XXX,XX +XXX,XX @@
695
+/*
696
+ * NXP i.MX 8M Plus Evaluation Kit System Emulation
697
+ *
698
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
699
+ *
700
+ * SPDX-License-Identifier: GPL-2.0-or-later
701
+ */
702
+
703
+#include "qemu/osdep.h"
704
+#include "exec/address-spaces.h"
705
+#include "hw/arm/boot.h"
706
+#include "hw/arm/fsl-imx8mp.h"
707
+#include "hw/boards.h"
708
+#include "system/qtest.h"
709
+#include "qemu/error-report.h"
710
+#include "qapi/error.h"
711
+
712
+static void imx8mp_evk_init(MachineState *machine)
713
+{
714
+ static struct arm_boot_info boot_info;
715
+ FslImx8mpState *s;
716
+
717
+ if (machine->ram_size > FSL_IMX8MP_RAM_SIZE_MAX) {
718
+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
719
+ machine->ram_size, FSL_IMX8MP_RAM_SIZE_MAX);
720
+ exit(1);
721
+ }
722
+
723
+ boot_info = (struct arm_boot_info) {
724
+ .loader_start = FSL_IMX8MP_RAM_START,
725
+ .board_id = -1,
726
+ .ram_size = machine->ram_size,
727
+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
728
+ };
729
+
730
+ s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP));
731
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
732
+ qdev_realize(DEVICE(s), NULL, &error_fatal);
733
+
734
+ memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
735
+ machine->ram);
736
+
737
+ if (!qtest_enabled()) {
738
+ arm_load_kernel(&s->cpu[0], machine, &boot_info);
739
+ }
740
+}
741
+
742
+static void imx8mp_evk_machine_init(MachineClass *mc)
743
+{
744
+ mc->desc = "NXP i.MX 8M Plus EVK Board";
745
+ mc->init = imx8mp_evk_init;
746
+ mc->max_cpus = FSL_IMX8MP_NUM_CPUS;
747
+ mc->default_ram_id = "imx8mp-evk.ram";
748
+}
749
+DEFINE_MACHINE("imx8mp-evk", imx8mp_evk_machine_init)
750
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
751
index XXXXXXX..XXXXXXX 100644
752
--- a/hw/arm/Kconfig
753
+++ b/hw/arm/Kconfig
754
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
755
select UNIMP
756
select USB_CHIPIDEA
757
758
+config FSL_IMX8MP
759
+ bool
760
+ select ARM_GIC
761
+ select IMX
762
+ select UNIMP
763
+
764
+config FSL_IMX8MP_EVK
765
+ bool
766
+ default y
767
+ depends on TCG && AARCH64
768
+ select FSL_IMX8MP
769
+
770
config ARM_SMMUV3
771
bool
772
773
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
774
index XXXXXXX..XXXXXXX 100644
775
--- a/hw/arm/meson.build
776
+++ b/hw/arm/meson.build
777
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))
778
arm_ss.add(when: 'CONFIG_MUSCA', if_true: files('musca.c'))
779
arm_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c'))
780
arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c'))
781
+arm_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true: files('fsl-imx8mp.c'))
782
+arm_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true: files('imx8mp-evk.c'))
783
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
784
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
785
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
786
--
787
2.43.0
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The sabrelite machine model used by qemu-system-arm is based on the
3
Fixes quite a few stack traces during the Linux boot process. Also provides the
4
Freescale/NXP i.MX6Q processor. This SoC has an on-board ethernet
4
clocks for devices added later, e.g. enet1.
5
controller which is supported in QEMU using the imx_fec.c module
6
(actually called imx.enet for this model.)
7
5
8
The include/hw/arm/fsm-imx6.h file defines the interrupt vectors for the
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
imx.enet device like this:
7
Message-id: 20250223114708.1780-6-shentey@gmail.com
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>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
43
---
10
---
44
include/hw/arm/fsl-imx6.h | 4 ++--
11
MAINTAINERS | 2 +
45
hw/net/imx_fec.c | 28 +++++++++++++++++++++++++++-
12
docs/system/arm/imx8mp-evk.rst | 1 +
46
2 files changed, 29 insertions(+), 3 deletions(-)
13
include/hw/arm/fsl-imx8mp.h | 4 +
14
include/hw/misc/imx8mp_analog.h | 81 +++++++++++++++
15
include/hw/misc/imx8mp_ccm.h | 30 ++++++
16
hw/arm/fsl-imx8mp.c | 20 ++++
17
hw/misc/imx8mp_analog.c | 160 +++++++++++++++++++++++++++++
18
hw/misc/imx8mp_ccm.c | 175 ++++++++++++++++++++++++++++++++
19
hw/arm/Kconfig | 2 +
20
hw/misc/Kconfig | 6 ++
21
hw/misc/meson.build | 2 +
22
11 files changed, 483 insertions(+)
23
create mode 100644 include/hw/misc/imx8mp_analog.h
24
create mode 100644 include/hw/misc/imx8mp_ccm.h
25
create mode 100644 hw/misc/imx8mp_analog.c
26
create mode 100644 hw/misc/imx8mp_ccm.c
47
27
48
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
28
diff --git a/MAINTAINERS b/MAINTAINERS
49
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/arm/fsl-imx6.h
30
--- a/MAINTAINERS
51
+++ b/include/hw/arm/fsl-imx6.h
31
+++ b/MAINTAINERS
52
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX6State {
32
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
53
#define FSL_IMX6_HDMI_MASTER_IRQ 115
33
S: Maintained
54
#define FSL_IMX6_HDMI_CEC_IRQ 116
34
F: hw/arm/imx8mp-evk.c
55
#define FSL_IMX6_MLB150_LOW_IRQ 117
35
F: hw/arm/fsl-imx8mp.c
56
-#define FSL_IMX6_ENET_MAC_1588_IRQ 118
36
+F: hw/misc/imx8mp_*.c
57
-#define FSL_IMX6_ENET_MAC_IRQ 119
37
F: include/hw/arm/fsl-imx8mp.h
58
+#define FSL_IMX6_ENET_MAC_IRQ 118
38
+F: include/hw/misc/imx8mp_*.h
59
+#define FSL_IMX6_ENET_MAC_1588_IRQ 119
39
F: docs/system/arm/imx8mp-evk.rst
60
#define FSL_IMX6_PCIE1_IRQ 120
40
61
#define FSL_IMX6_PCIE2_IRQ 121
41
MPS2 / MPS3
62
#define FSL_IMX6_PCIE3_IRQ 122
42
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
63
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
64
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/net/imx_fec.c
44
--- a/docs/system/arm/imx8mp-evk.rst
66
+++ b/hw/net/imx_fec.c
45
+++ b/docs/system/arm/imx8mp-evk.rst
67
@@ -XXX,XX +XXX,XX @@ static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr)
46
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
68
47
* Up to 4 Cortex-A53 cores
69
static void imx_eth_update(IMXFECState *s)
48
* Generic Interrupt Controller (GICv3)
70
{
49
* 4 UARTs
71
- if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_TS_TIMER) {
50
+ * Clock Tree
51
52
Boot options
53
------------
54
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/arm/fsl-imx8mp.h
57
+++ b/include/hw/arm/fsl-imx8mp.h
58
@@ -XXX,XX +XXX,XX @@
59
#include "cpu.h"
60
#include "hw/char/imx_serial.h"
61
#include "hw/intc/arm_gicv3_common.h"
62
+#include "hw/misc/imx8mp_analog.h"
63
+#include "hw/misc/imx8mp_ccm.h"
64
#include "qom/object.h"
65
#include "qemu/units.h"
66
67
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
68
69
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
70
GICv3State gic;
71
+ IMX8MPCCMState ccm;
72
+ IMX8MPAnalogState analog;
73
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
74
};
75
76
diff --git a/include/hw/misc/imx8mp_analog.h b/include/hw/misc/imx8mp_analog.h
77
new file mode 100644
78
index XXXXXXX..XXXXXXX
79
--- /dev/null
80
+++ b/include/hw/misc/imx8mp_analog.h
81
@@ -XXX,XX +XXX,XX @@
82
+/*
83
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
84
+ *
85
+ * i.MX8MP ANALOG IP block emulation code
86
+ *
87
+ * SPDX-License-Identifier: GPL-2.0-or-later
88
+ */
89
+
90
+#ifndef IMX8MP_ANALOG_H
91
+#define IMX8MP_ANALOG_H
92
+
93
+#include "qom/object.h"
94
+#include "hw/sysbus.h"
95
+
96
+enum IMX8MPAnalogRegisters {
97
+ ANALOG_AUDIO_PLL1_GEN_CTRL = 0x000 / 4,
98
+ ANALOG_AUDIO_PLL1_FDIV_CTL0 = 0x004 / 4,
99
+ ANALOG_AUDIO_PLL1_FDIV_CTL1 = 0x008 / 4,
100
+ ANALOG_AUDIO_PLL1_SSCG_CTRL = 0x00c / 4,
101
+ ANALOG_AUDIO_PLL1_MNIT_CTRL = 0x010 / 4,
102
+ ANALOG_AUDIO_PLL2_GEN_CTRL = 0x014 / 4,
103
+ ANALOG_AUDIO_PLL2_FDIV_CTL0 = 0x018 / 4,
104
+ ANALOG_AUDIO_PLL2_FDIV_CTL1 = 0x01c / 4,
105
+ ANALOG_AUDIO_PLL2_SSCG_CTRL = 0x020 / 4,
106
+ ANALOG_AUDIO_PLL2_MNIT_CTRL = 0x024 / 4,
107
+ ANALOG_VIDEO_PLL1_GEN_CTRL = 0x028 / 4,
108
+ ANALOG_VIDEO_PLL1_FDIV_CTL0 = 0x02c / 4,
109
+ ANALOG_VIDEO_PLL1_FDIV_CTL1 = 0x030 / 4,
110
+ ANALOG_VIDEO_PLL1_SSCG_CTRL = 0x034 / 4,
111
+ ANALOG_VIDEO_PLL1_MNIT_CTRL = 0x038 / 4,
112
+ ANALOG_DRAM_PLL_GEN_CTRL = 0x050 / 4,
113
+ ANALOG_DRAM_PLL_FDIV_CTL0 = 0x054 / 4,
114
+ ANALOG_DRAM_PLL_FDIV_CTL1 = 0x058 / 4,
115
+ ANALOG_DRAM_PLL_SSCG_CTRL = 0x05c / 4,
116
+ ANALOG_DRAM_PLL_MNIT_CTRL = 0x060 / 4,
117
+ ANALOG_GPU_PLL_GEN_CTRL = 0x064 / 4,
118
+ ANALOG_GPU_PLL_FDIV_CTL0 = 0x068 / 4,
119
+ ANALOG_GPU_PLL_LOCKD_CTRL = 0x06c / 4,
120
+ ANALOG_GPU_PLL_MNIT_CTRL = 0x070 / 4,
121
+ ANALOG_VPU_PLL_GEN_CTRL = 0x074 / 4,
122
+ ANALOG_VPU_PLL_FDIV_CTL0 = 0x078 / 4,
123
+ ANALOG_VPU_PLL_LOCKD_CTRL = 0x07c / 4,
124
+ ANALOG_VPU_PLL_MNIT_CTRL = 0x080 / 4,
125
+ ANALOG_ARM_PLL_GEN_CTRL = 0x084 / 4,
126
+ ANALOG_ARM_PLL_FDIV_CTL0 = 0x088 / 4,
127
+ ANALOG_ARM_PLL_LOCKD_CTRL = 0x08c / 4,
128
+ ANALOG_ARM_PLL_MNIT_CTRL = 0x090 / 4,
129
+ ANALOG_SYS_PLL1_GEN_CTRL = 0x094 / 4,
130
+ ANALOG_SYS_PLL1_FDIV_CTL0 = 0x098 / 4,
131
+ ANALOG_SYS_PLL1_LOCKD_CTRL = 0x09c / 4,
132
+ ANALOG_SYS_PLL1_MNIT_CTRL = 0x100 / 4,
133
+ ANALOG_SYS_PLL2_GEN_CTRL = 0x104 / 4,
134
+ ANALOG_SYS_PLL2_FDIV_CTL0 = 0x108 / 4,
135
+ ANALOG_SYS_PLL2_LOCKD_CTRL = 0x10c / 4,
136
+ ANALOG_SYS_PLL2_MNIT_CTRL = 0x110 / 4,
137
+ ANALOG_SYS_PLL3_GEN_CTRL = 0x114 / 4,
138
+ ANALOG_SYS_PLL3_FDIV_CTL0 = 0x118 / 4,
139
+ ANALOG_SYS_PLL3_LOCKD_CTRL = 0x11c / 4,
140
+ ANALOG_SYS_PLL3_MNIT_CTRL = 0x120 / 4,
141
+ ANALOG_OSC_MISC_CFG = 0x124 / 4,
142
+ ANALOG_ANAMIX_PLL_MNIT_CTL = 0x128 / 4,
143
+
144
+ ANALOG_DIGPROG = 0x800 / 4,
145
+ ANALOG_MAX,
146
+};
147
+
148
+#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
149
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
150
+
151
+struct IMX8MPAnalogState {
152
+ SysBusDevice parent_obj;
153
+
154
+ struct {
155
+ MemoryRegion container;
156
+ MemoryRegion analog;
157
+ } mmio;
158
+
159
+ uint32_t analog[ANALOG_MAX];
160
+};
161
+
162
+#endif /* IMX8MP_ANALOG_H */
163
diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
164
new file mode 100644
165
index XXXXXXX..XXXXXXX
166
--- /dev/null
167
+++ b/include/hw/misc/imx8mp_ccm.h
168
@@ -XXX,XX +XXX,XX @@
169
+/*
170
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
171
+ *
172
+ * i.MX 8M Plus CCM IP block emulation code
173
+ *
174
+ * SPDX-License-Identifier: GPL-2.0-or-later
175
+ */
176
+
177
+#ifndef IMX8MP_CCM_H
178
+#define IMX8MP_CCM_H
179
+
180
+#include "hw/misc/imx_ccm.h"
181
+#include "qom/object.h"
182
+
183
+enum IMX8MPCCMRegisters {
184
+ CCM_MAX = 0xc6fc / sizeof(uint32_t) + 1,
185
+};
186
+
187
+#define TYPE_IMX8MP_CCM "imx8mp.ccm"
188
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPCCMState, IMX8MP_CCM)
189
+
190
+struct IMX8MPCCMState {
191
+ IMXCCMState parent_obj;
192
+
193
+ MemoryRegion iomem;
194
+
195
+ uint32_t ccm[CCM_MAX];
196
+};
197
+
198
+#endif /* IMX8MP_CCM_H */
199
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/arm/fsl-imx8mp.c
202
+++ b/hw/arm/fsl-imx8mp.c
203
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
204
205
object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
206
207
+ object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
208
+
209
+ object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
210
+
211
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
212
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
213
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
214
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
215
}
216
}
217
218
+ /* CCM */
219
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
220
+ return;
221
+ }
222
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
223
+ fsl_imx8mp_memmap[FSL_IMX8MP_CCM].addr);
224
+
225
+ /* Analog */
226
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
227
+ return;
228
+ }
229
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
230
+ fsl_imx8mp_memmap[FSL_IMX8MP_ANA_PLL].addr);
231
+
232
/* UARTs */
233
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
234
struct {
235
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
236
/* Unimplemented devices */
237
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
238
switch (i) {
239
+ case FSL_IMX8MP_ANA_PLL:
240
+ case FSL_IMX8MP_CCM:
241
case FSL_IMX8MP_GIC_DIST:
242
case FSL_IMX8MP_GIC_REDIST:
243
case FSL_IMX8MP_RAM:
244
diff --git a/hw/misc/imx8mp_analog.c b/hw/misc/imx8mp_analog.c
245
new file mode 100644
246
index XXXXXXX..XXXXXXX
247
--- /dev/null
248
+++ b/hw/misc/imx8mp_analog.c
249
@@ -XXX,XX +XXX,XX @@
250
+/*
251
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
252
+ *
253
+ * i.MX 8M Plus ANALOG IP block emulation code
254
+ *
255
+ * Based on hw/misc/imx7_ccm.c
256
+ *
257
+ * SPDX-License-Identifier: GPL-2.0-or-later
258
+ */
259
+
260
+#include "qemu/osdep.h"
261
+#include "qemu/log.h"
262
+
263
+#include "hw/misc/imx8mp_analog.h"
264
+#include "migration/vmstate.h"
265
+
266
+#define ANALOG_PLL_LOCK BIT(31)
267
+
268
+static void imx8mp_analog_reset(DeviceState *dev)
269
+{
270
+ IMX8MPAnalogState *s = IMX8MP_ANALOG(dev);
271
+
272
+ memset(s->analog, 0, sizeof(s->analog));
273
+
274
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] = 0x00002010;
275
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL0] = 0x00145032;
276
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL1] = 0x00000000;
277
+ s->analog[ANALOG_AUDIO_PLL1_SSCG_CTRL] = 0x00000000;
278
+ s->analog[ANALOG_AUDIO_PLL1_MNIT_CTRL] = 0x00100103;
279
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] = 0x00002010;
280
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL0] = 0x00145032;
281
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL1] = 0x00000000;
282
+ s->analog[ANALOG_AUDIO_PLL2_SSCG_CTRL] = 0x00000000;
283
+ s->analog[ANALOG_AUDIO_PLL2_MNIT_CTRL] = 0x00100103;
284
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] = 0x00002010;
285
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL0] = 0x00145032;
286
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL1] = 0x00000000;
287
+ s->analog[ANALOG_VIDEO_PLL1_SSCG_CTRL] = 0x00000000;
288
+ s->analog[ANALOG_VIDEO_PLL1_MNIT_CTRL] = 0x00100103;
289
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] = 0x00002010;
290
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL0] = 0x0012c032;
291
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL1] = 0x00000000;
292
+ s->analog[ANALOG_DRAM_PLL_SSCG_CTRL] = 0x00000000;
293
+ s->analog[ANALOG_DRAM_PLL_MNIT_CTRL] = 0x00100103;
294
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] = 0x00000810;
295
+ s->analog[ANALOG_GPU_PLL_FDIV_CTL0] = 0x000c8031;
296
+ s->analog[ANALOG_GPU_PLL_LOCKD_CTRL] = 0x0010003f;
297
+ s->analog[ANALOG_GPU_PLL_MNIT_CTRL] = 0x00280081;
298
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] = 0x00000810;
299
+ s->analog[ANALOG_VPU_PLL_FDIV_CTL0] = 0x0012c032;
300
+ s->analog[ANALOG_VPU_PLL_LOCKD_CTRL] = 0x0010003f;
301
+ s->analog[ANALOG_VPU_PLL_MNIT_CTRL] = 0x00280081;
302
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] = 0x00000810;
303
+ s->analog[ANALOG_ARM_PLL_FDIV_CTL0] = 0x000fa031;
304
+ s->analog[ANALOG_ARM_PLL_LOCKD_CTRL] = 0x0010003f;
305
+ s->analog[ANALOG_ARM_PLL_MNIT_CTRL] = 0x00280081;
306
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] = 0x0aaaa810;
307
+ s->analog[ANALOG_SYS_PLL1_FDIV_CTL0] = 0x00190032;
308
+ s->analog[ANALOG_SYS_PLL1_LOCKD_CTRL] = 0x0010003f;
309
+ s->analog[ANALOG_SYS_PLL1_MNIT_CTRL] = 0x00280081;
310
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] = 0x0aaaa810;
311
+ s->analog[ANALOG_SYS_PLL2_FDIV_CTL0] = 0x000fa031;
312
+ s->analog[ANALOG_SYS_PLL2_LOCKD_CTRL] = 0x0010003f;
313
+ s->analog[ANALOG_SYS_PLL2_MNIT_CTRL] = 0x00280081;
314
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] = 0x00000810;
315
+ s->analog[ANALOG_SYS_PLL3_FDIV_CTL0] = 0x000fa031;
316
+ s->analog[ANALOG_SYS_PLL3_LOCKD_CTRL] = 0x0010003f;
317
+ s->analog[ANALOG_SYS_PLL3_MNIT_CTRL] = 0x00280081;
318
+ s->analog[ANALOG_OSC_MISC_CFG] = 0x00000000;
319
+ s->analog[ANALOG_ANAMIX_PLL_MNIT_CTL] = 0x00000000;
320
+ s->analog[ANALOG_DIGPROG] = 0x00824010;
321
+
322
+ /* all PLLs need to be locked */
323
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
324
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
325
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
326
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
327
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
328
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
329
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
330
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
331
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
332
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] |= ANALOG_PLL_LOCK;
333
+}
334
+
335
+static uint64_t imx8mp_analog_read(void *opaque, hwaddr offset, unsigned size)
336
+{
337
+ IMX8MPAnalogState *s = opaque;
338
+
339
+ return s->analog[offset >> 2];
340
+}
341
+
342
+static void imx8mp_analog_write(void *opaque, hwaddr offset,
343
+ uint64_t value, unsigned size)
344
+{
345
+ IMX8MPAnalogState *s = opaque;
346
+
347
+ if (offset >> 2 == ANALOG_DIGPROG) {
348
+ qemu_log_mask(LOG_GUEST_ERROR,
349
+ "Guest write to read-only ANALOG_DIGPROG register\n");
350
+ } else {
351
+ s->analog[offset >> 2] = value;
352
+ }
353
+}
354
+
355
+static const struct MemoryRegionOps imx8mp_analog_ops = {
356
+ .read = imx8mp_analog_read,
357
+ .write = imx8mp_analog_write,
358
+ .endianness = DEVICE_NATIVE_ENDIAN,
359
+ .impl = {
360
+ .min_access_size = 4,
361
+ .max_access_size = 4,
362
+ .unaligned = false,
363
+ },
364
+};
365
+
366
+static void imx8mp_analog_init(Object *obj)
367
+{
368
+ IMX8MPAnalogState *s = IMX8MP_ANALOG(obj);
369
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
370
+
371
+ memory_region_init(&s->mmio.container, obj, TYPE_IMX8MP_ANALOG, 0x10000);
372
+
373
+ memory_region_init_io(&s->mmio.analog, obj, &imx8mp_analog_ops, s,
374
+ TYPE_IMX8MP_ANALOG, sizeof(s->analog));
375
+ memory_region_add_subregion(&s->mmio.container, 0, &s->mmio.analog);
376
+
377
+ sysbus_init_mmio(sd, &s->mmio.container);
378
+}
379
+
380
+static const VMStateDescription imx8mp_analog_vmstate = {
381
+ .name = TYPE_IMX8MP_ANALOG,
382
+ .version_id = 1,
383
+ .minimum_version_id = 1,
384
+ .fields = (const VMStateField[]) {
385
+ VMSTATE_UINT32_ARRAY(analog, IMX8MPAnalogState, ANALOG_MAX),
386
+ VMSTATE_END_OF_LIST()
387
+ },
388
+};
389
+
390
+static void imx8mp_analog_class_init(ObjectClass *klass, void *data)
391
+{
392
+ DeviceClass *dc = DEVICE_CLASS(klass);
393
+
394
+ device_class_set_legacy_reset(dc, imx8mp_analog_reset);
395
+ dc->vmsd = &imx8mp_analog_vmstate;
396
+ dc->desc = "i.MX 8M Plus Analog Module";
397
+}
398
+
399
+static const TypeInfo imx8mp_analog_types[] = {
400
+ {
401
+ .name = TYPE_IMX8MP_ANALOG,
402
+ .parent = TYPE_SYS_BUS_DEVICE,
403
+ .instance_size = sizeof(IMX8MPAnalogState),
404
+ .instance_init = imx8mp_analog_init,
405
+ .class_init = imx8mp_analog_class_init,
406
+ }
407
+};
408
+
409
+DEFINE_TYPES(imx8mp_analog_types);
410
diff --git a/hw/misc/imx8mp_ccm.c b/hw/misc/imx8mp_ccm.c
411
new file mode 100644
412
index XXXXXXX..XXXXXXX
413
--- /dev/null
414
+++ b/hw/misc/imx8mp_ccm.c
415
@@ -XXX,XX +XXX,XX @@
416
+/*
417
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
418
+ *
419
+ * i.MX 8M Plus CCM IP block emulation code
420
+ *
421
+ * Based on hw/misc/imx7_ccm.c
422
+ *
423
+ * SPDX-License-Identifier: GPL-2.0-or-later
424
+ */
425
+
426
+#include "qemu/osdep.h"
427
+#include "qemu/log.h"
428
+
429
+#include "hw/misc/imx8mp_ccm.h"
430
+#include "migration/vmstate.h"
431
+
432
+#include "trace.h"
433
+
434
+#define CKIH_FREQ 16000000 /* 16MHz crystal input */
435
+
436
+static void imx8mp_ccm_reset(DeviceState *dev)
437
+{
438
+ IMX8MPCCMState *s = IMX8MP_CCM(dev);
439
+
440
+ memset(s->ccm, 0, sizeof(s->ccm));
441
+}
442
+
443
+#define CCM_INDEX(offset) (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
444
+#define CCM_BITOP(offset) ((offset) & (hwaddr)0xF)
445
+
446
+enum {
447
+ CCM_BITOP_NONE = 0x00,
448
+ CCM_BITOP_SET = 0x04,
449
+ CCM_BITOP_CLR = 0x08,
450
+ CCM_BITOP_TOG = 0x0C,
451
+};
452
+
453
+static uint64_t imx8mp_set_clr_tog_read(void *opaque, hwaddr offset,
454
+ unsigned size)
455
+{
456
+ const uint32_t *mmio = opaque;
457
+
458
+ return mmio[CCM_INDEX(offset)];
459
+}
460
+
461
+static void imx8mp_set_clr_tog_write(void *opaque, hwaddr offset,
462
+ uint64_t value, unsigned size)
463
+{
464
+ const uint8_t bitop = CCM_BITOP(offset);
465
+ const uint32_t index = CCM_INDEX(offset);
466
+ uint32_t *mmio = opaque;
467
+
468
+ switch (bitop) {
469
+ case CCM_BITOP_NONE:
470
+ mmio[index] = value;
471
+ break;
472
+ case CCM_BITOP_SET:
473
+ mmio[index] |= value;
474
+ break;
475
+ case CCM_BITOP_CLR:
476
+ mmio[index] &= ~value;
477
+ break;
478
+ case CCM_BITOP_TOG:
479
+ mmio[index] ^= value;
480
+ break;
481
+ };
482
+}
483
+
484
+static const struct MemoryRegionOps imx8mp_set_clr_tog_ops = {
485
+ .read = imx8mp_set_clr_tog_read,
486
+ .write = imx8mp_set_clr_tog_write,
487
+ .endianness = DEVICE_NATIVE_ENDIAN,
488
+ .impl = {
489
+ /*
490
+ * Our device would not work correctly if the guest was doing
491
+ * unaligned access. This might not be a limitation on the real
492
+ * device but in practice there is no reason for a guest to access
493
+ * this device unaligned.
494
+ */
495
+ .min_access_size = 4,
496
+ .max_access_size = 4,
497
+ .unaligned = false,
498
+ },
499
+};
500
+
501
+static void imx8mp_ccm_init(Object *obj)
502
+{
503
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
504
+ IMX8MPCCMState *s = IMX8MP_CCM(obj);
505
+
506
+ memory_region_init_io(&s->iomem,
507
+ obj,
508
+ &imx8mp_set_clr_tog_ops,
509
+ s->ccm,
510
+ TYPE_IMX8MP_CCM ".ccm",
511
+ sizeof(s->ccm));
512
+
513
+ sysbus_init_mmio(sd, &s->iomem);
514
+}
515
+
516
+static const VMStateDescription imx8mp_ccm_vmstate = {
517
+ .name = TYPE_IMX8MP_CCM,
518
+ .version_id = 1,
519
+ .minimum_version_id = 1,
520
+ .fields = (const VMStateField[]) {
521
+ VMSTATE_UINT32_ARRAY(ccm, IMX8MPCCMState, CCM_MAX),
522
+ VMSTATE_END_OF_LIST()
523
+ },
524
+};
525
+
526
+static uint32_t imx8mp_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
527
+{
72
+ /*
528
+ /*
73
+ * Previous versions of qemu had the ENET_INT_MAC and ENET_INT_TS_TIMER
529
+ * This function is "consumed" by GPT emulation code. Some clocks
74
+ * interrupts swapped. This worked with older versions of Linux (4.14
530
+ * have fixed frequencies and we can provide requested frequency
75
+ * and older) since Linux associated both interrupt lines with Ethernet
531
+ * easily. However for CCM provided clocks (like IPG) each GPT
76
+ * MAC interrupts. Specifically,
532
+ * timer can have its own clock root.
77
+ * - Linux 4.15 and later have separate interrupt handlers for the MAC and
533
+ * This means we need additional information when calling this
78
+ * timer interrupts. Those versions of Linux fail with versions of QEMU
534
+ * function to know the requester's identity.
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
+ */
535
+ */
97
+ if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] &
536
+ uint32_t freq = 0;
98
+ (ENET_INT_MAC | ENET_INT_TS_TIMER)) {
537
+
99
qemu_set_irq(s->irq[1], 1);
538
+ switch (clock) {
100
} else {
539
+ case CLK_NONE:
101
qemu_set_irq(s->irq[1], 0);
540
+ break;
541
+ case CLK_32k:
542
+ freq = CKIL_FREQ;
543
+ break;
544
+ case CLK_HIGH:
545
+ freq = CKIH_FREQ;
546
+ break;
547
+ case CLK_IPG:
548
+ case CLK_IPG_HIGH:
549
+ /*
550
+ * For now we don't have a way to figure out the device this
551
+ * function is called for. Until then the IPG derived clocks
552
+ * are left unimplemented.
553
+ */
554
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Clock %d Not implemented\n",
555
+ TYPE_IMX8MP_CCM, __func__, clock);
556
+ break;
557
+ default:
558
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
559
+ TYPE_IMX8MP_CCM, __func__, clock);
560
+ break;
561
+ }
562
+
563
+ trace_ccm_clock_freq(clock, freq);
564
+
565
+ return freq;
566
+}
567
+
568
+static void imx8mp_ccm_class_init(ObjectClass *klass, void *data)
569
+{
570
+ DeviceClass *dc = DEVICE_CLASS(klass);
571
+ IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
572
+
573
+ device_class_set_legacy_reset(dc, imx8mp_ccm_reset);
574
+ dc->vmsd = &imx8mp_ccm_vmstate;
575
+ dc->desc = "i.MX 8M Plus Clock Control Module";
576
+
577
+ ccm->get_clock_frequency = imx8mp_ccm_get_clock_frequency;
578
+}
579
+
580
+static const TypeInfo imx8mp_ccm_types[] = {
581
+ {
582
+ .name = TYPE_IMX8MP_CCM,
583
+ .parent = TYPE_IMX_CCM,
584
+ .instance_size = sizeof(IMX8MPCCMState),
585
+ .instance_init = imx8mp_ccm_init,
586
+ .class_init = imx8mp_ccm_class_init,
587
+ },
588
+};
589
+
590
+DEFINE_TYPES(imx8mp_ccm_types);
591
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
592
index XXXXXXX..XXXXXXX 100644
593
--- a/hw/arm/Kconfig
594
+++ b/hw/arm/Kconfig
595
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
596
config FSL_IMX8MP
597
bool
598
select ARM_GIC
599
+ select FSL_IMX8MP_ANALOG
600
+ select FSL_IMX8MP_CCM
601
select IMX
602
select UNIMP
603
604
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
605
index XXXXXXX..XXXXXXX 100644
606
--- a/hw/misc/Kconfig
607
+++ b/hw/misc/Kconfig
608
@@ -XXX,XX +XXX,XX @@ config IMX
609
select SSI
610
select USB_EHCI_SYSBUS
611
612
+config FSL_IMX8MP_ANALOG
613
+ bool
614
+
615
+config FSL_IMX8MP_CCM
616
+ bool
617
+
618
config STM32_RCC
619
bool
620
621
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
622
index XXXXXXX..XXXXXXX 100644
623
--- a/hw/misc/meson.build
624
+++ b/hw/misc/meson.build
625
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
626
system_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
627
system_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
628
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', 'exynos4210_clk.c', 'exynos4210_rng.c'))
629
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_analog.c'))
630
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true: files('imx8mp_ccm.c'))
631
system_ss.add(when: 'CONFIG_IMX', if_true: files(
632
'imx25_ccm.c',
633
'imx31_ccm.c',
102
--
634
--
103
2.16.2
635
2.43.0
104
105
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
SNVS contains an RTC which allows Linux to deal correctly with time. This is
4
particularly useful when handling persistent storage which will be done in the
5
next patch.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20250223114708.1780-7-shentey@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/system/arm/imx8mp-evk.rst | 1 +
13
include/hw/arm/fsl-imx8mp.h | 2 ++
14
hw/arm/fsl-imx8mp.c | 10 ++++++++++
15
3 files changed, 13 insertions(+)
16
17
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/system/arm/imx8mp-evk.rst
20
+++ b/docs/system/arm/imx8mp-evk.rst
21
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
22
* Up to 4 Cortex-A53 cores
23
* Generic Interrupt Controller (GICv3)
24
* 4 UARTs
25
+ * Secure Non-Volatile Storage (SNVS) including an RTC
26
* Clock Tree
27
28
Boot options
29
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/arm/fsl-imx8mp.h
32
+++ b/include/hw/arm/fsl-imx8mp.h
33
@@ -XXX,XX +XXX,XX @@
34
#include "cpu.h"
35
#include "hw/char/imx_serial.h"
36
#include "hw/intc/arm_gicv3_common.h"
37
+#include "hw/misc/imx7_snvs.h"
38
#include "hw/misc/imx8mp_analog.h"
39
#include "hw/misc/imx8mp_ccm.h"
40
#include "qom/object.h"
41
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
42
GICv3State gic;
43
IMX8MPCCMState ccm;
44
IMX8MPAnalogState analog;
45
+ IMX7SNVSState snvs;
46
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
47
};
48
49
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/fsl-imx8mp.c
52
+++ b/hw/arm/fsl-imx8mp.c
53
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
54
55
object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
56
57
+ object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
58
+
59
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
60
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
61
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
62
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
63
qdev_get_gpio_in(gicdev, serial_table[i].irq));
64
}
65
66
+ /* SNVS */
67
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
68
+ return;
69
+ }
70
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
71
+ fsl_imx8mp_memmap[FSL_IMX8MP_SNVS_HP].addr);
72
+
73
/* Unimplemented devices */
74
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
75
switch (i) {
76
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
77
case FSL_IMX8MP_GIC_DIST:
78
case FSL_IMX8MP_GIC_REDIST:
79
case FSL_IMX8MP_RAM:
80
+ case FSL_IMX8MP_SNVS_HP:
81
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
82
/* device implemented and treated above */
83
break;
84
--
85
2.43.0
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
The USDHC emulation allows for running real-world images such as those generated
4
by Buildroot. Convert the board documentation accordingly instead of running a
5
Linux kernel with ephemeral storage.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20250223114708.1780-8-shentey@gmail.com
10
[PMM: drop 'static const' from usdhc_table[] for GCC 7.5]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
docs/system/arm/imx8mp-evk.rst | 18 ++++++++++++------
14
include/hw/arm/fsl-imx8mp.h | 7 +++++++
15
hw/arm/fsl-imx8mp.c | 28 ++++++++++++++++++++++++++++
16
hw/arm/imx8mp-evk.c | 18 ++++++++++++++++++
17
hw/arm/Kconfig | 1 +
18
5 files changed, 66 insertions(+), 6 deletions(-)
19
20
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
21
index XXXXXXX..XXXXXXX 100644
22
--- a/docs/system/arm/imx8mp-evk.rst
23
+++ b/docs/system/arm/imx8mp-evk.rst
24
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
25
* Up to 4 Cortex-A53 cores
26
* Generic Interrupt Controller (GICv3)
27
* 4 UARTs
28
+ * 3 USDHC Storage Controllers
29
* Secure Non-Volatile Storage (SNVS) including an RTC
30
* Clock Tree
31
32
@@ -XXX,XX +XXX,XX @@ Direct Linux Kernel Boot
33
34
Probably the easiest way to get started with a whole Linux system on the machine
35
is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
36
-of writing and involves two steps. First run the following commands in the
37
+of writing and involves three steps. First run the following commands in the
38
toplevel directory of the Buildroot source tree:
39
40
.. code-block:: bash
41
42
- $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
43
$ make freescale_imx8mpevk_defconfig
44
$ make
45
46
Once finished successfully there is an ``output/image`` subfolder. Navigate into
47
-it and patch the device tree with the following commands which will remove the
48
-``cpu-idle-states`` properties from CPU nodes:
49
+it and resize the SD card image to a power of two:
50
+
51
+.. code-block:: bash
52
+
53
+ $ qemu-img resize sdcard.img 256M
54
+
55
+Finally, the device tree needs to be patched with the following commands which
56
+will remove the ``cpu-idle-states`` properties from CPU nodes:
57
58
.. code-block:: bash
59
60
@@ -XXX,XX +XXX,XX @@ Now that everything is prepared the machine can be started as follows:
61
-display none -serial null -serial stdio \
62
-kernel Image \
63
-dtb imx8mp-evk-patched.dtb \
64
- -initrd rootfs.cpio \
65
- -append "root=/dev/ram"
66
+ -append "root=/dev/mmcblk2p2" \
67
+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
68
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/hw/arm/fsl-imx8mp.h
71
+++ b/include/hw/arm/fsl-imx8mp.h
72
@@ -XXX,XX +XXX,XX @@
73
#include "hw/misc/imx7_snvs.h"
74
#include "hw/misc/imx8mp_analog.h"
75
#include "hw/misc/imx8mp_ccm.h"
76
+#include "hw/sd/sdhci.h"
77
#include "qom/object.h"
78
#include "qemu/units.h"
79
80
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpConfiguration {
81
FSL_IMX8MP_NUM_CPUS = 4,
82
FSL_IMX8MP_NUM_IRQS = 160,
83
FSL_IMX8MP_NUM_UARTS = 4,
84
+ FSL_IMX8MP_NUM_USDHCS = 3,
85
};
86
87
struct FslImx8mpState {
88
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
89
IMX8MPAnalogState analog;
90
IMX7SNVSState snvs;
91
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
92
+ SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
93
};
94
95
enum FslImx8mpMemoryRegions {
96
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpMemoryRegions {
97
};
98
99
enum FslImx8mpIrqs {
100
+ FSL_IMX8MP_USDHC1_IRQ = 22,
101
+ FSL_IMX8MP_USDHC2_IRQ = 23,
102
+ FSL_IMX8MP_USDHC3_IRQ = 24,
103
+
104
FSL_IMX8MP_UART1_IRQ = 26,
105
FSL_IMX8MP_UART2_IRQ = 27,
106
FSL_IMX8MP_UART3_IRQ = 28,
107
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/hw/arm/fsl-imx8mp.c
110
+++ b/hw/arm/fsl-imx8mp.c
111
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
112
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
113
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
114
}
115
+
116
+ for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
117
+ g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
118
+ object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
119
+ }
120
}
121
122
static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
123
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
124
qdev_get_gpio_in(gicdev, serial_table[i].irq));
125
}
126
127
+ /* USDHCs */
128
+ for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
129
+ struct {
130
+ hwaddr addr;
131
+ unsigned int irq;
132
+ } usdhc_table[FSL_IMX8MP_NUM_USDHCS] = {
133
+ { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC1].addr, FSL_IMX8MP_USDHC1_IRQ },
134
+ { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC2].addr, FSL_IMX8MP_USDHC2_IRQ },
135
+ { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC3].addr, FSL_IMX8MP_USDHC3_IRQ },
136
+ };
137
+
138
+ object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
139
+ SDHCI_VENDOR_IMX, &error_abort);
140
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
141
+ return;
142
+ }
143
+
144
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].addr);
145
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
146
+ qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
147
+ }
148
+
149
/* SNVS */
150
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
151
return;
152
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
153
case FSL_IMX8MP_RAM:
154
case FSL_IMX8MP_SNVS_HP:
155
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
156
+ case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
157
/* device implemented and treated above */
158
break;
159
160
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/hw/arm/imx8mp-evk.c
163
+++ b/hw/arm/imx8mp-evk.c
164
@@ -XXX,XX +XXX,XX @@
165
#include "hw/arm/boot.h"
166
#include "hw/arm/fsl-imx8mp.h"
167
#include "hw/boards.h"
168
+#include "hw/qdev-properties.h"
169
#include "system/qtest.h"
170
#include "qemu/error-report.h"
171
#include "qapi/error.h"
172
@@ -XXX,XX +XXX,XX @@ static void imx8mp_evk_init(MachineState *machine)
173
memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
174
machine->ram);
175
176
+ for (int i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
177
+ BusState *bus;
178
+ DeviceState *carddev;
179
+ BlockBackend *blk;
180
+ DriveInfo *di = drive_get(IF_SD, i, 0);
181
+
182
+ if (!di) {
183
+ continue;
184
+ }
185
+
186
+ blk = blk_by_legacy_dinfo(di);
187
+ bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
188
+ carddev = qdev_new(TYPE_SD_CARD);
189
+ qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
190
+ qdev_realize_and_unref(carddev, bus, &error_fatal);
191
+ }
192
+
193
if (!qtest_enabled()) {
194
arm_load_kernel(&s->cpu[0], machine, &boot_info);
195
}
196
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
197
index XXXXXXX..XXXXXXX 100644
198
--- a/hw/arm/Kconfig
199
+++ b/hw/arm/Kconfig
200
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
201
select FSL_IMX8MP_ANALOG
202
select FSL_IMX8MP_CCM
203
select IMX
204
+ select SDHCI
205
select UNIMP
206
207
config FSL_IMX8MP_EVK
208
--
209
2.43.0
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Code of imx_update() is slightly confusing since the "flags" variable
3
Linux checks for the PLLs in the PHY to be locked, so implement a model
4
doesn't really corespond to anything in real hardware and server as a
4
emulating that.
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
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
via USR1 and USR2 against corresponding masking bits and use the to
7
Message-id: 20250223114708.1780-9-shentey@gmail.com
10
detemine if IRQ line should be asserted or not.
11
12
NOTE: Check for UTS1_TXEMPTY being set has been dropped for two
13
reasons:
14
15
1. Emulation code implements a single character FIFO, so this flag
16
will always be set since characters are trasmitted as a part of
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
25
Cc: qemu-arm@nongnu.org
26
Cc: Bill Paul <wpaul@windriver.com>
27
Cc: Peter Maydell <peter.maydell@linaro.org>
28
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>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
---
10
---
33
hw/char/imx_serial.c | 24 ++++++++++++++++--------
11
MAINTAINERS | 2 +
34
1 file changed, 16 insertions(+), 8 deletions(-)
12
docs/system/arm/imx8mp-evk.rst | 1 +
13
include/hw/arm/fsl-imx8mp.h | 10 +++
14
include/hw/pci-host/fsl_imx8m_phy.h | 28 +++++++++
15
hw/arm/fsl-imx8mp.c | 30 +++++++++
16
hw/pci-host/fsl_imx8m_phy.c | 98 +++++++++++++++++++++++++++++
17
hw/arm/Kconfig | 3 +
18
hw/pci-host/Kconfig | 3 +
19
hw/pci-host/meson.build | 1 +
20
9 files changed, 176 insertions(+)
21
create mode 100644 include/hw/pci-host/fsl_imx8m_phy.h
22
create mode 100644 hw/pci-host/fsl_imx8m_phy.c
35
23
36
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
24
diff --git a/MAINTAINERS b/MAINTAINERS
37
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/char/imx_serial.c
26
--- a/MAINTAINERS
39
+++ b/hw/char/imx_serial.c
27
+++ b/MAINTAINERS
40
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_serial = {
28
@@ -XXX,XX +XXX,XX @@ S: Maintained
41
29
F: hw/arm/imx8mp-evk.c
42
static void imx_update(IMXSerialState *s)
30
F: hw/arm/fsl-imx8mp.c
43
{
31
F: hw/misc/imx8mp_*.c
44
- uint32_t flags;
32
+F: hw/pci-host/fsl_imx8m_phy.c
45
+ uint32_t usr1;
33
F: include/hw/arm/fsl-imx8mp.h
46
+ uint32_t usr2;
34
F: include/hw/misc/imx8mp_*.h
47
+ uint32_t mask;
35
+F: include/hw/pci-host/fsl_imx8m_phy.h
48
36
F: docs/system/arm/imx8mp-evk.rst
49
- flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
37
50
- if (s->ucr1 & UCR1_TXMPTYEN) {
38
MPS2 / MPS3
51
- flags |= (s->uts1 & UTS1_TXEMPTY);
39
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
52
- } else {
40
index XXXXXXX..XXXXXXX 100644
53
- flags &= ~USR1_TRDY;
41
--- a/docs/system/arm/imx8mp-evk.rst
54
- }
42
+++ b/docs/system/arm/imx8mp-evk.rst
55
+ /*
43
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
56
+ * Lucky for us TRDY and RRDY has the same offset in both USR1 and
44
* Generic Interrupt Controller (GICv3)
57
+ * UCR1, so we can get away with something as simple as the
45
* 4 UARTs
58
+ * following:
46
* 3 USDHC Storage Controllers
59
+ */
47
+ * 1 Designware PCI Express Controller
60
+ usr1 = s->usr1 & s->ucr1 & (USR1_TRDY | USR1_RRDY);
48
* Secure Non-Volatile Storage (SNVS) including an RTC
61
+ /*
49
* Clock Tree
62
+ * Bits that we want in USR2 are not as conveniently laid out,
50
63
+ * unfortunately.
51
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
64
+ */
52
index XXXXXXX..XXXXXXX 100644
65
+ mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
53
--- a/include/hw/arm/fsl-imx8mp.h
66
+ usr2 = s->usr2 & mask;
54
+++ b/include/hw/arm/fsl-imx8mp.h
67
55
@@ -XXX,XX +XXX,XX @@
68
- qemu_set_irq(s->irq, !!flags);
56
#include "hw/misc/imx7_snvs.h"
69
+ qemu_set_irq(s->irq, usr1 || usr2);
57
#include "hw/misc/imx8mp_analog.h"
58
#include "hw/misc/imx8mp_ccm.h"
59
+#include "hw/pci-host/designware.h"
60
+#include "hw/pci-host/fsl_imx8m_phy.h"
61
#include "hw/sd/sdhci.h"
62
#include "qom/object.h"
63
#include "qemu/units.h"
64
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
65
IMX7SNVSState snvs;
66
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
67
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
68
+ DesignwarePCIEHost pcie;
69
+ FslImx8mPciePhyState pcie_phy;
70
};
71
72
enum FslImx8mpMemoryRegions {
73
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
74
FSL_IMX8MP_UART4_IRQ = 29,
75
FSL_IMX8MP_UART5_IRQ = 30,
76
FSL_IMX8MP_UART6_IRQ = 16,
77
+
78
+ FSL_IMX8MP_PCI_INTA_IRQ = 126,
79
+ FSL_IMX8MP_PCI_INTB_IRQ = 125,
80
+ FSL_IMX8MP_PCI_INTC_IRQ = 124,
81
+ FSL_IMX8MP_PCI_INTD_IRQ = 123,
82
+ FSL_IMX8MP_PCI_MSI_IRQ = 140,
83
};
84
85
#endif /* FSL_IMX8MP_H */
86
diff --git a/include/hw/pci-host/fsl_imx8m_phy.h b/include/hw/pci-host/fsl_imx8m_phy.h
87
new file mode 100644
88
index XXXXXXX..XXXXXXX
89
--- /dev/null
90
+++ b/include/hw/pci-host/fsl_imx8m_phy.h
91
@@ -XXX,XX +XXX,XX @@
92
+/*
93
+ * i.MX8 PCIe PHY emulation
94
+ *
95
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
96
+ *
97
+ * SPDX-License-Identifier: GPL-2.0-or-later
98
+ */
99
+
100
+#ifndef HW_PCIHOST_FSLIMX8MPCIEPHY_H
101
+#define HW_PCIHOST_FSLIMX8MPCIEPHY_H
102
+
103
+#include "hw/sysbus.h"
104
+#include "qom/object.h"
105
+#include "exec/memory.h"
106
+
107
+#define TYPE_FSL_IMX8M_PCIE_PHY "fsl-imx8m-pcie-phy"
108
+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mPciePhyState, FSL_IMX8M_PCIE_PHY)
109
+
110
+#define FSL_IMX8M_PCIE_PHY_DATA_SIZE 0x800
111
+
112
+struct FslImx8mPciePhyState {
113
+ SysBusDevice parent_obj;
114
+
115
+ MemoryRegion iomem;
116
+ uint8_t data[FSL_IMX8M_PCIE_PHY_DATA_SIZE];
117
+};
118
+
119
+#endif
120
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/arm/fsl-imx8mp.c
123
+++ b/hw/arm/fsl-imx8mp.c
124
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
125
g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
126
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
127
}
128
+
129
+ object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
130
+ object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
131
+ TYPE_FSL_IMX8M_PCIE_PHY);
70
}
132
}
71
133
72
static void imx_serial_reset(IMXSerialState *s)
134
static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
135
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
136
sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
137
fsl_imx8mp_memmap[FSL_IMX8MP_SNVS_HP].addr);
138
139
+ /* PCIe */
140
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie), errp)) {
141
+ return;
142
+ }
143
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0,
144
+ fsl_imx8mp_memmap[FSL_IMX8MP_PCIE1].addr);
145
+
146
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0,
147
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTA_IRQ));
148
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1,
149
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTB_IRQ));
150
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2,
151
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTC_IRQ));
152
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3,
153
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_INTD_IRQ));
154
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4,
155
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_PCI_MSI_IRQ));
156
+
157
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy), errp)) {
158
+ return;
159
+ }
160
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
161
+ fsl_imx8mp_memmap[FSL_IMX8MP_PCIE_PHY1].addr);
162
+
163
/* Unimplemented devices */
164
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
165
switch (i) {
166
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
167
case FSL_IMX8MP_CCM:
168
case FSL_IMX8MP_GIC_DIST:
169
case FSL_IMX8MP_GIC_REDIST:
170
+ case FSL_IMX8MP_PCIE1:
171
+ case FSL_IMX8MP_PCIE_PHY1:
172
case FSL_IMX8MP_RAM:
173
case FSL_IMX8MP_SNVS_HP:
174
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
175
diff --git a/hw/pci-host/fsl_imx8m_phy.c b/hw/pci-host/fsl_imx8m_phy.c
176
new file mode 100644
177
index XXXXXXX..XXXXXXX
178
--- /dev/null
179
+++ b/hw/pci-host/fsl_imx8m_phy.c
180
@@ -XXX,XX +XXX,XX @@
181
+/*
182
+ * i.MX8 PCIe PHY emulation
183
+ *
184
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
185
+ *
186
+ * SPDX-License-Identifier: GPL-2.0-or-later
187
+ */
188
+
189
+#include "qemu/osdep.h"
190
+#include "hw/pci-host/fsl_imx8m_phy.h"
191
+#include "hw/resettable.h"
192
+#include "migration/vmstate.h"
193
+
194
+#define CMN_REG075 0x1d4
195
+#define ANA_PLL_LOCK_DONE BIT(1)
196
+#define ANA_PLL_AFC_DONE BIT(0)
197
+
198
+static uint64_t fsl_imx8m_pcie_phy_read(void *opaque, hwaddr offset,
199
+ unsigned size)
200
+{
201
+ FslImx8mPciePhyState *s = opaque;
202
+
203
+ if (offset == CMN_REG075) {
204
+ return s->data[offset] | ANA_PLL_LOCK_DONE | ANA_PLL_AFC_DONE;
205
+ }
206
+
207
+ return s->data[offset];
208
+}
209
+
210
+static void fsl_imx8m_pcie_phy_write(void *opaque, hwaddr offset,
211
+ uint64_t value, unsigned size)
212
+{
213
+ FslImx8mPciePhyState *s = opaque;
214
+
215
+ s->data[offset] = value;
216
+}
217
+
218
+static const MemoryRegionOps fsl_imx8m_pcie_phy_ops = {
219
+ .read = fsl_imx8m_pcie_phy_read,
220
+ .write = fsl_imx8m_pcie_phy_write,
221
+ .impl = {
222
+ .min_access_size = 1,
223
+ .max_access_size = 1,
224
+ },
225
+ .valid = {
226
+ .min_access_size = 1,
227
+ .max_access_size = 8,
228
+ },
229
+ .endianness = DEVICE_LITTLE_ENDIAN,
230
+};
231
+
232
+static void fsl_imx8m_pcie_phy_realize(DeviceState *dev, Error **errp)
233
+{
234
+ FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(dev);
235
+
236
+ memory_region_init_io(&s->iomem, OBJECT(s), &fsl_imx8m_pcie_phy_ops, s,
237
+ TYPE_FSL_IMX8M_PCIE_PHY, ARRAY_SIZE(s->data));
238
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
239
+}
240
+
241
+static void fsl_imx8m_pcie_phy_reset_hold(Object *obj, ResetType type)
242
+{
243
+ FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(obj);
244
+
245
+ memset(s->data, 0, sizeof(s->data));
246
+}
247
+
248
+static const VMStateDescription fsl_imx8m_pcie_phy_vmstate = {
249
+ .name = "fsl-imx8m-pcie-phy",
250
+ .version_id = 1,
251
+ .minimum_version_id = 1,
252
+ .fields = (const VMStateField[]) {
253
+ VMSTATE_UINT8_ARRAY(data, FslImx8mPciePhyState,
254
+ FSL_IMX8M_PCIE_PHY_DATA_SIZE),
255
+ VMSTATE_END_OF_LIST()
256
+ }
257
+};
258
+
259
+static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, void *data)
260
+{
261
+ DeviceClass *dc = DEVICE_CLASS(klass);
262
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
263
+
264
+ dc->realize = fsl_imx8m_pcie_phy_realize;
265
+ dc->vmsd = &fsl_imx8m_pcie_phy_vmstate;
266
+ rc->phases.hold = fsl_imx8m_pcie_phy_reset_hold;
267
+}
268
+
269
+static const TypeInfo fsl_imx8m_pcie_phy_types[] = {
270
+ {
271
+ .name = TYPE_FSL_IMX8M_PCIE_PHY,
272
+ .parent = TYPE_SYS_BUS_DEVICE,
273
+ .instance_size = sizeof(FslImx8mPciePhyState),
274
+ .class_init = fsl_imx8m_pcie_phy_class_init,
275
+ }
276
+};
277
+
278
+DEFINE_TYPES(fsl_imx8m_pcie_phy_types)
279
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
280
index XXXXXXX..XXXXXXX 100644
281
--- a/hw/arm/Kconfig
282
+++ b/hw/arm/Kconfig
283
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
284
285
config FSL_IMX8MP
286
bool
287
+ imply PCI_DEVICES
288
select ARM_GIC
289
select FSL_IMX8MP_ANALOG
290
select FSL_IMX8MP_CCM
291
select IMX
292
+ select PCI_EXPRESS_DESIGNWARE
293
+ select PCI_EXPRESS_FSL_IMX8M_PHY
294
select SDHCI
295
select UNIMP
296
297
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
298
index XXXXXXX..XXXXXXX 100644
299
--- a/hw/pci-host/Kconfig
300
+++ b/hw/pci-host/Kconfig
301
@@ -XXX,XX +XXX,XX @@ config ASTRO
302
bool
303
select PCI
304
305
+config PCI_EXPRESS_FSL_IMX8M_PHY
306
+ bool
307
+
308
config GT64120
309
bool
310
select PCI
311
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
312
index XXXXXXX..XXXXXXX 100644
313
--- a/hw/pci-host/meson.build
314
+++ b/hw/pci-host/meson.build
315
@@ -XXX,XX +XXX,XX @@ pci_ss.add(when: 'CONFIG_ARTICIA', if_true: files('articia.c'))
316
pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c'))
317
318
# ARM devices
319
+pci_ss.add(when: 'CONFIG_PCI_EXPRESS_FSL_IMX8M_PHY', if_true: files('fsl_imx8m_phy.c'))
320
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
321
322
# HPPA devices
73
--
323
--
74
2.16.2
324
2.43.0
75
76
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Message-id: 20250223114708.1780-10-shentey@gmail.com
6
[PMM: drop static const from gpio_table for GCC 7.5]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
docs/system/arm/imx8mp-evk.rst | 1 +
10
include/hw/arm/fsl-imx8mp.h | 14 +++++++++
11
hw/arm/fsl-imx8mp.c | 55 ++++++++++++++++++++++++++++++++++
12
3 files changed, 70 insertions(+)
13
14
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
15
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/imx8mp-evk.rst
17
+++ b/docs/system/arm/imx8mp-evk.rst
18
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
19
* 4 UARTs
20
* 3 USDHC Storage Controllers
21
* 1 Designware PCI Express Controller
22
+ * 5 GPIO Controllers
23
* Secure Non-Volatile Storage (SNVS) including an RTC
24
* Clock Tree
25
26
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/fsl-imx8mp.h
29
+++ b/include/hw/arm/fsl-imx8mp.h
30
@@ -XXX,XX +XXX,XX @@
31
32
#include "cpu.h"
33
#include "hw/char/imx_serial.h"
34
+#include "hw/gpio/imx_gpio.h"
35
#include "hw/intc/arm_gicv3_common.h"
36
#include "hw/misc/imx7_snvs.h"
37
#include "hw/misc/imx8mp_analog.h"
38
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
39
40
enum FslImx8mpConfiguration {
41
FSL_IMX8MP_NUM_CPUS = 4,
42
+ FSL_IMX8MP_NUM_GPIOS = 5,
43
FSL_IMX8MP_NUM_IRQS = 160,
44
FSL_IMX8MP_NUM_UARTS = 4,
45
FSL_IMX8MP_NUM_USDHCS = 3,
46
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
47
48
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
49
GICv3State gic;
50
+ IMXGPIOState gpio[FSL_IMX8MP_NUM_GPIOS];
51
IMX8MPCCMState ccm;
52
IMX8MPAnalogState analog;
53
IMX7SNVSState snvs;
54
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
55
FSL_IMX8MP_UART5_IRQ = 30,
56
FSL_IMX8MP_UART6_IRQ = 16,
57
58
+ FSL_IMX8MP_GPIO1_LOW_IRQ = 64,
59
+ FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
60
+ FSL_IMX8MP_GPIO2_LOW_IRQ = 66,
61
+ FSL_IMX8MP_GPIO2_HIGH_IRQ = 67,
62
+ FSL_IMX8MP_GPIO3_LOW_IRQ = 68,
63
+ FSL_IMX8MP_GPIO3_HIGH_IRQ = 69,
64
+ FSL_IMX8MP_GPIO4_LOW_IRQ = 70,
65
+ FSL_IMX8MP_GPIO4_HIGH_IRQ = 71,
66
+ FSL_IMX8MP_GPIO5_LOW_IRQ = 72,
67
+ FSL_IMX8MP_GPIO5_HIGH_IRQ = 73,
68
+
69
FSL_IMX8MP_PCI_INTA_IRQ = 126,
70
FSL_IMX8MP_PCI_INTB_IRQ = 125,
71
FSL_IMX8MP_PCI_INTC_IRQ = 124,
72
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/arm/fsl-imx8mp.c
75
+++ b/hw/arm/fsl-imx8mp.c
76
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
77
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
78
}
79
80
+ for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
81
+ g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
82
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
83
+ }
84
+
85
for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
86
g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
87
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
88
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
89
qdev_get_gpio_in(gicdev, serial_table[i].irq));
90
}
91
92
+ /* GPIOs */
93
+ for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
94
+ struct {
95
+ hwaddr addr;
96
+ unsigned int irq_low;
97
+ unsigned int irq_high;
98
+ } gpio_table[FSL_IMX8MP_NUM_GPIOS] = {
99
+ {
100
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO1].addr,
101
+ FSL_IMX8MP_GPIO1_LOW_IRQ,
102
+ FSL_IMX8MP_GPIO1_HIGH_IRQ
103
+ },
104
+ {
105
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO2].addr,
106
+ FSL_IMX8MP_GPIO2_LOW_IRQ,
107
+ FSL_IMX8MP_GPIO2_HIGH_IRQ
108
+ },
109
+ {
110
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO3].addr,
111
+ FSL_IMX8MP_GPIO3_LOW_IRQ,
112
+ FSL_IMX8MP_GPIO3_HIGH_IRQ
113
+ },
114
+ {
115
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO4].addr,
116
+ FSL_IMX8MP_GPIO4_LOW_IRQ,
117
+ FSL_IMX8MP_GPIO4_HIGH_IRQ
118
+ },
119
+ {
120
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO5].addr,
121
+ FSL_IMX8MP_GPIO5_LOW_IRQ,
122
+ FSL_IMX8MP_GPIO5_HIGH_IRQ
123
+ },
124
+ };
125
+
126
+ object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", true,
127
+ &error_abort);
128
+ object_property_set_bool(OBJECT(&s->gpio[i]), "has-upper-pin-irq",
129
+ true, &error_abort);
130
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
131
+ return;
132
+ }
133
+
134
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
135
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
136
+ qdev_get_gpio_in(gicdev, gpio_table[i].irq_low));
137
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
138
+ qdev_get_gpio_in(gicdev, gpio_table[i].irq_high));
139
+ }
140
+
141
/* USDHCs */
142
for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
143
struct {
144
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
145
case FSL_IMX8MP_CCM:
146
case FSL_IMX8MP_GIC_DIST:
147
case FSL_IMX8MP_GIC_REDIST:
148
+ case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
149
case FSL_IMX8MP_PCIE1:
150
case FSL_IMX8MP_PCIE_PHY1:
151
case FSL_IMX8MP_RAM:
152
--
153
2.43.0
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Message-id: 20250223114708.1780-11-shentey@gmail.com
6
[PMM: drop static const from i2c_table for GCC 7.5]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
docs/system/arm/imx8mp-evk.rst | 1 +
10
include/hw/arm/fsl-imx8mp.h | 11 +++++++++++
11
hw/arm/fsl-imx8mp.c | 29 +++++++++++++++++++++++++++++
12
hw/arm/Kconfig | 2 ++
13
4 files changed, 43 insertions(+)
14
15
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/arm/imx8mp-evk.rst
18
+++ b/docs/system/arm/imx8mp-evk.rst
19
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
20
* 3 USDHC Storage Controllers
21
* 1 Designware PCI Express Controller
22
* 5 GPIO Controllers
23
+ * 6 I2C Controllers
24
* Secure Non-Volatile Storage (SNVS) including an RTC
25
* Clock Tree
26
27
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/arm/fsl-imx8mp.h
30
+++ b/include/hw/arm/fsl-imx8mp.h
31
@@ -XXX,XX +XXX,XX @@
32
#include "cpu.h"
33
#include "hw/char/imx_serial.h"
34
#include "hw/gpio/imx_gpio.h"
35
+#include "hw/i2c/imx_i2c.h"
36
#include "hw/intc/arm_gicv3_common.h"
37
#include "hw/misc/imx7_snvs.h"
38
#include "hw/misc/imx8mp_analog.h"
39
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
40
enum FslImx8mpConfiguration {
41
FSL_IMX8MP_NUM_CPUS = 4,
42
FSL_IMX8MP_NUM_GPIOS = 5,
43
+ FSL_IMX8MP_NUM_I2CS = 6,
44
FSL_IMX8MP_NUM_IRQS = 160,
45
FSL_IMX8MP_NUM_UARTS = 4,
46
FSL_IMX8MP_NUM_USDHCS = 3,
47
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
48
IMX8MPCCMState ccm;
49
IMX8MPAnalogState analog;
50
IMX7SNVSState snvs;
51
+ IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
52
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
53
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
54
DesignwarePCIEHost pcie;
55
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
56
FSL_IMX8MP_UART5_IRQ = 30,
57
FSL_IMX8MP_UART6_IRQ = 16,
58
59
+ FSL_IMX8MP_I2C1_IRQ = 35,
60
+ FSL_IMX8MP_I2C2_IRQ = 36,
61
+ FSL_IMX8MP_I2C3_IRQ = 37,
62
+ FSL_IMX8MP_I2C4_IRQ = 38,
63
+
64
FSL_IMX8MP_GPIO1_LOW_IRQ = 64,
65
FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
66
FSL_IMX8MP_GPIO2_LOW_IRQ = 66,
67
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
68
FSL_IMX8MP_GPIO5_LOW_IRQ = 72,
69
FSL_IMX8MP_GPIO5_HIGH_IRQ = 73,
70
71
+ FSL_IMX8MP_I2C5_IRQ = 76,
72
+ FSL_IMX8MP_I2C6_IRQ = 77,
73
+
74
FSL_IMX8MP_PCI_INTA_IRQ = 126,
75
FSL_IMX8MP_PCI_INTB_IRQ = 125,
76
FSL_IMX8MP_PCI_INTC_IRQ = 124,
77
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/fsl-imx8mp.c
80
+++ b/hw/arm/fsl-imx8mp.c
81
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
82
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
83
}
84
85
+ for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
86
+ g_autofree char *name = g_strdup_printf("i2c%d", i + 1);
87
+ object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
88
+ }
89
+
90
for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
91
g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
92
object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
93
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
94
qdev_get_gpio_in(gicdev, serial_table[i].irq));
95
}
96
97
+ /* I2Cs */
98
+ for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
99
+ struct {
100
+ hwaddr addr;
101
+ unsigned int irq;
102
+ } i2c_table[FSL_IMX8MP_NUM_I2CS] = {
103
+ { fsl_imx8mp_memmap[FSL_IMX8MP_I2C1].addr, FSL_IMX8MP_I2C1_IRQ },
104
+ { fsl_imx8mp_memmap[FSL_IMX8MP_I2C2].addr, FSL_IMX8MP_I2C2_IRQ },
105
+ { fsl_imx8mp_memmap[FSL_IMX8MP_I2C3].addr, FSL_IMX8MP_I2C3_IRQ },
106
+ { fsl_imx8mp_memmap[FSL_IMX8MP_I2C4].addr, FSL_IMX8MP_I2C4_IRQ },
107
+ { fsl_imx8mp_memmap[FSL_IMX8MP_I2C5].addr, FSL_IMX8MP_I2C5_IRQ },
108
+ { fsl_imx8mp_memmap[FSL_IMX8MP_I2C6].addr, FSL_IMX8MP_I2C6_IRQ },
109
+ };
110
+
111
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) {
112
+ return;
113
+ }
114
+
115
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
116
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
117
+ qdev_get_gpio_in(gicdev, i2c_table[i].irq));
118
+ }
119
+
120
/* GPIOs */
121
for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
122
struct {
123
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
124
case FSL_IMX8MP_GIC_DIST:
125
case FSL_IMX8MP_GIC_REDIST:
126
case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
127
+ case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
128
case FSL_IMX8MP_PCIE1:
129
case FSL_IMX8MP_PCIE_PHY1:
130
case FSL_IMX8MP_RAM:
131
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/arm/Kconfig
134
+++ b/hw/arm/Kconfig
135
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
136
137
config FSL_IMX8MP
138
bool
139
+ imply I2C_DEVICES
140
imply PCI_DEVICES
141
select ARM_GIC
142
select FSL_IMX8MP_ANALOG
143
select FSL_IMX8MP_CCM
144
select IMX
145
+ select IMX_I2C
146
select PCI_EXPRESS_DESIGNWARE
147
select PCI_EXPRESS_FSL_IMX8M_PHY
148
select SDHCI
149
--
150
2.43.0
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Message-id: 20250223114708.1780-12-shentey@gmail.com
6
[PMM: drop static const from spi_table for GCC 7.5]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
docs/system/arm/imx8mp-evk.rst | 1 +
10
include/hw/arm/fsl-imx8mp.h | 8 ++++++++
11
hw/arm/fsl-imx8mp.c | 26 ++++++++++++++++++++++++++
12
3 files changed, 35 insertions(+)
13
14
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
15
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/imx8mp-evk.rst
17
+++ b/docs/system/arm/imx8mp-evk.rst
18
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
19
* 1 Designware PCI Express Controller
20
* 5 GPIO Controllers
21
* 6 I2C Controllers
22
+ * 3 SPI Controllers
23
* Secure Non-Volatile Storage (SNVS) including an RTC
24
* Clock Tree
25
26
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/fsl-imx8mp.h
29
+++ b/include/hw/arm/fsl-imx8mp.h
30
@@ -XXX,XX +XXX,XX @@
31
#include "hw/pci-host/designware.h"
32
#include "hw/pci-host/fsl_imx8m_phy.h"
33
#include "hw/sd/sdhci.h"
34
+#include "hw/ssi/imx_spi.h"
35
#include "qom/object.h"
36
#include "qemu/units.h"
37
38
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
39
40
enum FslImx8mpConfiguration {
41
FSL_IMX8MP_NUM_CPUS = 4,
42
+ FSL_IMX8MP_NUM_ECSPIS = 3,
43
FSL_IMX8MP_NUM_GPIOS = 5,
44
FSL_IMX8MP_NUM_I2CS = 6,
45
FSL_IMX8MP_NUM_IRQS = 160,
46
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
47
IMX8MPCCMState ccm;
48
IMX8MPAnalogState analog;
49
IMX7SNVSState snvs;
50
+ IMXSPIState spi[FSL_IMX8MP_NUM_ECSPIS];
51
IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
52
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
53
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
54
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
55
FSL_IMX8MP_UART5_IRQ = 30,
56
FSL_IMX8MP_UART6_IRQ = 16,
57
58
+ FSL_IMX8MP_ECSPI1_IRQ = 31,
59
+ FSL_IMX8MP_ECSPI2_IRQ = 32,
60
+ FSL_IMX8MP_ECSPI3_IRQ = 33,
61
+ FSL_IMX8MP_ECSPI4_IRQ = 34,
62
+
63
FSL_IMX8MP_I2C1_IRQ = 35,
64
FSL_IMX8MP_I2C2_IRQ = 36,
65
FSL_IMX8MP_I2C3_IRQ = 37,
66
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/fsl-imx8mp.c
69
+++ b/hw/arm/fsl-imx8mp.c
70
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
71
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
72
}
73
74
+ for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
75
+ g_autofree char *name = g_strdup_printf("spi%d", i + 1);
76
+ object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
77
+ }
78
+
79
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
80
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
81
TYPE_FSL_IMX8M_PCIE_PHY);
82
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
83
qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
84
}
85
86
+ /* ECSPIs */
87
+ for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
88
+ struct {
89
+ hwaddr addr;
90
+ unsigned int irq;
91
+ } spi_table[FSL_IMX8MP_NUM_ECSPIS] = {
92
+ { fsl_imx8mp_memmap[FSL_IMX8MP_ECSPI1].addr, FSL_IMX8MP_ECSPI1_IRQ },
93
+ { fsl_imx8mp_memmap[FSL_IMX8MP_ECSPI2].addr, FSL_IMX8MP_ECSPI2_IRQ },
94
+ { fsl_imx8mp_memmap[FSL_IMX8MP_ECSPI3].addr, FSL_IMX8MP_ECSPI3_IRQ },
95
+ };
96
+
97
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
98
+ return;
99
+ }
100
+
101
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr);
102
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
103
+ qdev_get_gpio_in(gicdev, spi_table[i].irq));
104
+ }
105
+
106
/* SNVS */
107
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
108
return;
109
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
110
case FSL_IMX8MP_GIC_DIST:
111
case FSL_IMX8MP_GIC_REDIST:
112
case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
113
+ case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
114
case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
115
case FSL_IMX8MP_PCIE1:
116
case FSL_IMX8MP_PCIE_PHY1:
117
--
118
2.43.0
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Message-id: 20250223114708.1780-13-shentey@gmail.com
6
[PMM: drop static const from wdog_table for GCC 7.5]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
docs/system/arm/imx8mp-evk.rst | 1 +
10
include/hw/arm/fsl-imx8mp.h | 7 +++++++
11
hw/arm/fsl-imx8mp.c | 28 ++++++++++++++++++++++++++++
12
hw/arm/Kconfig | 1 +
13
4 files changed, 37 insertions(+)
14
15
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/system/arm/imx8mp-evk.rst
18
+++ b/docs/system/arm/imx8mp-evk.rst
19
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
20
* 5 GPIO Controllers
21
* 6 I2C Controllers
22
* 3 SPI Controllers
23
+ * 3 Watchdogs
24
* Secure Non-Volatile Storage (SNVS) including an RTC
25
* Clock Tree
26
27
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/arm/fsl-imx8mp.h
30
+++ b/include/hw/arm/fsl-imx8mp.h
31
@@ -XXX,XX +XXX,XX @@
32
#include "hw/pci-host/fsl_imx8m_phy.h"
33
#include "hw/sd/sdhci.h"
34
#include "hw/ssi/imx_spi.h"
35
+#include "hw/watchdog/wdt_imx2.h"
36
#include "qom/object.h"
37
#include "qemu/units.h"
38
39
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpConfiguration {
40
FSL_IMX8MP_NUM_IRQS = 160,
41
FSL_IMX8MP_NUM_UARTS = 4,
42
FSL_IMX8MP_NUM_USDHCS = 3,
43
+ FSL_IMX8MP_NUM_WDTS = 3,
44
};
45
46
struct FslImx8mpState {
47
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
48
IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
49
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
50
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
51
+ IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
52
DesignwarePCIEHost pcie;
53
FslImx8mPciePhyState pcie_phy;
54
};
55
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
56
FSL_IMX8MP_I2C5_IRQ = 76,
57
FSL_IMX8MP_I2C6_IRQ = 77,
58
59
+ FSL_IMX8MP_WDOG1_IRQ = 78,
60
+ FSL_IMX8MP_WDOG2_IRQ = 79,
61
+ FSL_IMX8MP_WDOG3_IRQ = 10,
62
+
63
FSL_IMX8MP_PCI_INTA_IRQ = 126,
64
FSL_IMX8MP_PCI_INTB_IRQ = 125,
65
FSL_IMX8MP_PCI_INTC_IRQ = 124,
66
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/fsl-imx8mp.c
69
+++ b/hw/arm/fsl-imx8mp.c
70
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
71
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
72
}
73
74
+ for (i = 0; i < FSL_IMX8MP_NUM_WDTS; i++) {
75
+ g_autofree char *name = g_strdup_printf("wdt%d", i);
76
+ object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
77
+ }
78
+
79
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
80
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
81
TYPE_FSL_IMX8M_PCIE_PHY);
82
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
83
sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
84
fsl_imx8mp_memmap[FSL_IMX8MP_SNVS_HP].addr);
85
86
+ /* Watchdogs */
87
+ for (i = 0; i < FSL_IMX8MP_NUM_WDTS; i++) {
88
+ struct {
89
+ hwaddr addr;
90
+ unsigned int irq;
91
+ } wdog_table[FSL_IMX8MP_NUM_WDTS] = {
92
+ { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG1].addr, FSL_IMX8MP_WDOG1_IRQ },
93
+ { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG2].addr, FSL_IMX8MP_WDOG2_IRQ },
94
+ { fsl_imx8mp_memmap[FSL_IMX8MP_WDOG3].addr, FSL_IMX8MP_WDOG3_IRQ },
95
+ };
96
+
97
+ object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support",
98
+ true, &error_abort);
99
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
100
+ return;
101
+ }
102
+
103
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, wdog_table[i].addr);
104
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
105
+ qdev_get_gpio_in(gicdev, wdog_table[i].irq));
106
+ }
107
+
108
/* PCIe */
109
if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie), errp)) {
110
return;
111
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
112
case FSL_IMX8MP_SNVS_HP:
113
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
114
case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
115
+ case FSL_IMX8MP_WDOG1 ... FSL_IMX8MP_WDOG3:
116
/* device implemented and treated above */
117
break;
118
119
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
120
index XXXXXXX..XXXXXXX 100644
121
--- a/hw/arm/Kconfig
122
+++ b/hw/arm/Kconfig
123
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
124
select PCI_EXPRESS_FSL_IMX8M_PHY
125
select SDHCI
126
select UNIMP
127
+ select WDT_IMX2
128
129
config FSL_IMX8MP_EVK
130
bool
131
--
132
2.43.0
diff view generated by jsdifflib
1
From: Wei Huang <wei@redhat.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
For guest kernel that supports KASLR, the load address can change every
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
time when guest VM runs. To find the physical base address correctly,
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
current QEMU dump searches VMCOREINFO for the string "NUMBER(phys_base)=".
5
Message-id: 20250223114708.1780-14-shentey@gmail.com
6
However this string pattern is only available on x86_64. AArch64 uses a
6
[PMM: drop static const from gpt_attrs for GCC 7.5]
7
different field, called "NUMBER(PHYS_OFFSET)=". This patch makes sure
8
QEMU dump uses the correct string on AArch64.
9
10
Signed-off-by: Wei Huang <wei@redhat.com>
11
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
Message-id: 1520615003-20869-1-git-send-email-wei@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
8
---
15
dump.c | 14 +++++++++++---
9
docs/system/arm/imx8mp-evk.rst | 1 +
16
1 file changed, 11 insertions(+), 3 deletions(-)
10
include/hw/arm/fsl-imx8mp.h | 11 +++++++
11
include/hw/timer/imx_gpt.h | 1 +
12
hw/arm/fsl-imx8mp.c | 53 ++++++++++++++++++++++++++++++++++
13
hw/timer/imx_gpt.c | 25 ++++++++++++++++
14
hw/arm/Kconfig | 1 +
15
6 files changed, 92 insertions(+)
17
16
18
diff --git a/dump.c b/dump.c
17
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/dump.c
19
--- a/docs/system/arm/imx8mp-evk.rst
21
+++ b/dump.c
20
+++ b/docs/system/arm/imx8mp-evk.rst
22
@@ -XXX,XX +XXX,XX @@ static void vmcoreinfo_update_phys_base(DumpState *s)
21
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
23
22
* 6 I2C Controllers
24
lines = g_strsplit((char *)vmci, "\n", -1);
23
* 3 SPI Controllers
25
for (i = 0; lines[i]; i++) {
24
* 3 Watchdogs
26
- if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) {
25
+ * 6 General Purpose Timers
27
- if (qemu_strtou64(lines[i] + 18, NULL, 16,
26
* Secure Non-Volatile Storage (SNVS) including an RTC
28
+ const char *prefix = NULL;
27
* Clock Tree
29
+
28
30
+ if (s->dump_info.d_machine == EM_X86_64) {
29
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
31
+ prefix = "NUMBER(phys_base)=";
30
index XXXXXXX..XXXXXXX 100644
32
+ } else if (s->dump_info.d_machine == EM_AARCH64) {
31
--- a/include/hw/arm/fsl-imx8mp.h
33
+ prefix = "NUMBER(PHYS_OFFSET)=";
32
+++ b/include/hw/arm/fsl-imx8mp.h
33
@@ -XXX,XX +XXX,XX @@
34
#include "hw/misc/imx7_snvs.h"
35
#include "hw/misc/imx8mp_analog.h"
36
#include "hw/misc/imx8mp_ccm.h"
37
+#include "hw/or-irq.h"
38
#include "hw/pci-host/designware.h"
39
#include "hw/pci-host/fsl_imx8m_phy.h"
40
#include "hw/sd/sdhci.h"
41
#include "hw/ssi/imx_spi.h"
42
+#include "hw/timer/imx_gpt.h"
43
#include "hw/watchdog/wdt_imx2.h"
44
#include "qom/object.h"
45
#include "qemu/units.h"
46
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpConfiguration {
47
FSL_IMX8MP_NUM_CPUS = 4,
48
FSL_IMX8MP_NUM_ECSPIS = 3,
49
FSL_IMX8MP_NUM_GPIOS = 5,
50
+ FSL_IMX8MP_NUM_GPTS = 6,
51
FSL_IMX8MP_NUM_I2CS = 6,
52
FSL_IMX8MP_NUM_IRQS = 160,
53
FSL_IMX8MP_NUM_UARTS = 4,
54
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
55
56
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
57
GICv3State gic;
58
+ IMXGPTState gpt[FSL_IMX8MP_NUM_GPTS];
59
IMXGPIOState gpio[FSL_IMX8MP_NUM_GPIOS];
60
IMX8MPCCMState ccm;
61
IMX8MPAnalogState analog;
62
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
63
IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
64
DesignwarePCIEHost pcie;
65
FslImx8mPciePhyState pcie_phy;
66
+ OrIRQState gpt5_gpt6_irq;
67
};
68
69
enum FslImx8mpMemoryRegions {
70
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
71
FSL_IMX8MP_I2C3_IRQ = 37,
72
FSL_IMX8MP_I2C4_IRQ = 38,
73
74
+ FSL_IMX8MP_GPT1_IRQ = 55,
75
+ FSL_IMX8MP_GPT2_IRQ = 54,
76
+ FSL_IMX8MP_GPT3_IRQ = 53,
77
+ FSL_IMX8MP_GPT4_IRQ = 52,
78
+ FSL_IMX8MP_GPT5_GPT6_IRQ = 51,
79
+
80
FSL_IMX8MP_GPIO1_LOW_IRQ = 64,
81
FSL_IMX8MP_GPIO1_HIGH_IRQ = 65,
82
FSL_IMX8MP_GPIO2_LOW_IRQ = 66,
83
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
84
index XXXXXXX..XXXXXXX 100644
85
--- a/include/hw/timer/imx_gpt.h
86
+++ b/include/hw/timer/imx_gpt.h
87
@@ -XXX,XX +XXX,XX @@
88
#define TYPE_IMX6_GPT "imx6.gpt"
89
#define TYPE_IMX6UL_GPT "imx6ul.gpt"
90
#define TYPE_IMX7_GPT "imx7.gpt"
91
+#define TYPE_IMX8MP_GPT "imx8mp.gpt"
92
93
#define TYPE_IMX_GPT TYPE_IMX25_GPT
94
95
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/hw/arm/fsl-imx8mp.c
98
+++ b/hw/arm/fsl-imx8mp.c
99
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
100
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
101
}
102
103
+ for (i = 0; i < FSL_IMX8MP_NUM_GPTS; i++) {
104
+ g_autofree char *name = g_strdup_printf("gpt%d", i + 1);
105
+ object_initialize_child(obj, name, &s->gpt[i], TYPE_IMX8MP_GPT);
106
+ }
107
+ object_initialize_child(obj, "gpt5-gpt6-irq", &s->gpt5_gpt6_irq,
108
+ TYPE_OR_IRQ);
109
+
110
for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
111
g_autofree char *name = g_strdup_printf("i2c%d", i + 1);
112
object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
113
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
114
qdev_get_gpio_in(gicdev, serial_table[i].irq));
115
}
116
117
+ /* GPTs */
118
+ object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2,
119
+ &error_abort);
120
+ if (!qdev_realize(DEVICE(&s->gpt5_gpt6_irq), NULL, errp)) {
121
+ return;
122
+ }
123
+
124
+ qdev_connect_gpio_out(DEVICE(&s->gpt5_gpt6_irq), 0,
125
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_GPT5_GPT6_IRQ));
126
+
127
+ for (i = 0; i < FSL_IMX8MP_NUM_GPTS; i++) {
128
+ hwaddr gpt_addrs[FSL_IMX8MP_NUM_GPTS] = {
129
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT1].addr,
130
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT2].addr,
131
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT3].addr,
132
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT4].addr,
133
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT5].addr,
134
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPT6].addr,
135
+ };
136
+
137
+ s->gpt[i].ccm = IMX_CCM(&s->ccm);
138
+
139
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) {
140
+ return;
34
+ }
141
+ }
35
+
142
+
36
+ if (prefix && g_str_has_prefix(lines[i], prefix)) {
143
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_addrs[i]);
37
+ if (qemu_strtou64(lines[i] + strlen(prefix), NULL, 16,
144
+
38
&phys_base) < 0) {
145
+ if (i < FSL_IMX8MP_NUM_GPTS - 2) {
39
- warn_report("Failed to read NUMBER(phys_base)=");
146
+ static const unsigned int gpt_irqs[FSL_IMX8MP_NUM_GPTS - 2] = {
40
+ warn_report("Failed to read %s", prefix);
147
+ FSL_IMX8MP_GPT1_IRQ,
41
} else {
148
+ FSL_IMX8MP_GPT2_IRQ,
42
s->dump_info.phys_base = phys_base;
149
+ FSL_IMX8MP_GPT3_IRQ,
43
}
150
+ FSL_IMX8MP_GPT4_IRQ,
151
+ };
152
+
153
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
154
+ qdev_get_gpio_in(gicdev, gpt_irqs[i]));
155
+ } else {
156
+ int irq = i - FSL_IMX8MP_NUM_GPTS + 2;
157
+
158
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
159
+ qdev_get_gpio_in(DEVICE(&s->gpt5_gpt6_irq), irq));
160
+ }
161
+ }
162
+
163
/* I2Cs */
164
for (i = 0; i < FSL_IMX8MP_NUM_I2CS; i++) {
165
struct {
166
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/timer/imx_gpt.c
169
+++ b/hw/timer/imx_gpt.c
170
@@ -XXX,XX +XXX,XX @@ static const IMXClk imx7_gpt_clocks[] = {
171
CLK_NONE, /* 111 not defined */
172
};
173
174
+static const IMXClk imx8mp_gpt_clocks[] = {
175
+ CLK_NONE, /* 000 No clock source */
176
+ CLK_IPG, /* 001 ipg_clk, 532MHz */
177
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
178
+ CLK_EXT, /* 011 External clock */
179
+ CLK_32k, /* 100 ipg_clk_32k */
180
+ CLK_HIGH, /* 101 ipg_clk_16M */
181
+ CLK_NONE, /* 110 not defined */
182
+ CLK_NONE, /* 111 not defined */
183
+};
184
+
185
/* Must be called from within ptimer_transaction_begin/commit block */
186
static void imx_gpt_set_freq(IMXGPTState *s)
187
{
188
@@ -XXX,XX +XXX,XX @@ static void imx7_gpt_init(Object *obj)
189
s->clocks = imx7_gpt_clocks;
190
}
191
192
+static void imx8mp_gpt_init(Object *obj)
193
+{
194
+ IMXGPTState *s = IMX_GPT(obj);
195
+
196
+ s->clocks = imx8mp_gpt_clocks;
197
+}
198
+
199
static const TypeInfo imx25_gpt_info = {
200
.name = TYPE_IMX25_GPT,
201
.parent = TYPE_SYS_BUS_DEVICE,
202
@@ -XXX,XX +XXX,XX @@ static const TypeInfo imx7_gpt_info = {
203
.instance_init = imx7_gpt_init,
204
};
205
206
+static const TypeInfo imx8mp_gpt_info = {
207
+ .name = TYPE_IMX8MP_GPT,
208
+ .parent = TYPE_IMX25_GPT,
209
+ .instance_init = imx8mp_gpt_init,
210
+};
211
+
212
static void imx_gpt_register_types(void)
213
{
214
type_register_static(&imx25_gpt_info);
215
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_register_types(void)
216
type_register_static(&imx6_gpt_info);
217
type_register_static(&imx6ul_gpt_info);
218
type_register_static(&imx7_gpt_info);
219
+ type_register_static(&imx8mp_gpt_info);
220
}
221
222
type_init(imx_gpt_register_types)
223
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
224
index XXXXXXX..XXXXXXX 100644
225
--- a/hw/arm/Kconfig
226
+++ b/hw/arm/Kconfig
227
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
228
select FSL_IMX8MP_CCM
229
select IMX
230
select IMX_I2C
231
+ select OR_IRQ
232
select PCI_EXPRESS_DESIGNWARE
233
select PCI_EXPRESS_FSL_IMX8M_PHY
234
select SDHCI
44
--
235
--
45
2.16.2
236
2.43.0
46
47
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
The i.MX 8M Plus SoC actually has two ethernet controllers, the usual ENET one
4
and a Designware one. There is no device model for the latter, so only add the
5
ENET one.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20250223114708.1780-15-shentey@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/system/arm/imx8mp-evk.rst | 1 +
13
include/hw/arm/fsl-imx8mp.h | 8 ++++++++
14
hw/arm/fsl-imx8mp.c | 24 ++++++++++++++++++++++++
15
hw/arm/imx8mp-evk.c | 1 +
16
hw/arm/Kconfig | 1 +
17
5 files changed, 35 insertions(+)
18
19
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
20
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/arm/imx8mp-evk.rst
22
+++ b/docs/system/arm/imx8mp-evk.rst
23
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
24
* 4 UARTs
25
* 3 USDHC Storage Controllers
26
* 1 Designware PCI Express Controller
27
+ * 1 Ethernet Controller
28
* 5 GPIO Controllers
29
* 6 I2C Controllers
30
* 3 SPI Controllers
31
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/arm/fsl-imx8mp.h
34
+++ b/include/hw/arm/fsl-imx8mp.h
35
@@ -XXX,XX +XXX,XX @@
36
#include "hw/misc/imx7_snvs.h"
37
#include "hw/misc/imx8mp_analog.h"
38
#include "hw/misc/imx8mp_ccm.h"
39
+#include "hw/net/imx_fec.h"
40
#include "hw/or-irq.h"
41
#include "hw/pci-host/designware.h"
42
#include "hw/pci-host/fsl_imx8m_phy.h"
43
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
44
IMXSPIState spi[FSL_IMX8MP_NUM_ECSPIS];
45
IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
46
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
47
+ IMXFECState enet;
48
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
49
IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
50
DesignwarePCIEHost pcie;
51
FslImx8mPciePhyState pcie_phy;
52
OrIRQState gpt5_gpt6_irq;
53
+
54
+ uint32_t phy_num;
55
+ bool phy_connected;
56
};
57
58
enum FslImx8mpMemoryRegions {
59
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
60
FSL_IMX8MP_WDOG2_IRQ = 79,
61
FSL_IMX8MP_WDOG3_IRQ = 10,
62
63
+ FSL_IMX8MP_ENET1_MAC_IRQ = 118,
64
+ FSL_IMX6_ENET1_MAC_1588_IRQ = 121,
65
+
66
FSL_IMX8MP_PCI_INTA_IRQ = 126,
67
FSL_IMX8MP_PCI_INTB_IRQ = 125,
68
FSL_IMX8MP_PCI_INTC_IRQ = 124,
69
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/hw/arm/fsl-imx8mp.c
72
+++ b/hw/arm/fsl-imx8mp.c
73
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
74
object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
75
}
76
77
+ object_initialize_child(obj, "eth0", &s->enet, TYPE_IMX_ENET);
78
+
79
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
80
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
81
TYPE_FSL_IMX8M_PCIE_PHY);
82
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
83
qdev_get_gpio_in(gicdev, spi_table[i].irq));
84
}
85
86
+ /* ENET1 */
87
+ object_property_set_uint(OBJECT(&s->enet), "phy-num", s->phy_num,
88
+ &error_abort);
89
+ object_property_set_uint(OBJECT(&s->enet), "tx-ring-num", 3, &error_abort);
90
+ qemu_configure_nic_device(DEVICE(&s->enet), true, NULL);
91
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->enet), errp)) {
92
+ return;
93
+ }
94
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0,
95
+ fsl_imx8mp_memmap[FSL_IMX8MP_ENET1].addr);
96
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0,
97
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_ENET1_MAC_IRQ));
98
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1,
99
+ qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IRQ));
100
+
101
/* SNVS */
102
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
103
return;
104
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
105
case FSL_IMX8MP_GIC_REDIST:
106
case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
107
case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
108
+ case FSL_IMX8MP_ENET1:
109
case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
110
case FSL_IMX8MP_PCIE1:
111
case FSL_IMX8MP_PCIE_PHY1:
112
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
113
}
114
}
115
116
+static const Property fsl_imx8mp_properties[] = {
117
+ DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mpState, phy_num, 0),
118
+ DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mpState, phy_connected, true),
119
+};
120
+
121
static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
122
{
123
DeviceClass *dc = DEVICE_CLASS(oc);
124
125
+ device_class_set_props(dc, fsl_imx8mp_properties);
126
dc->realize = fsl_imx8mp_realize;
127
128
dc->desc = "i.MX 8M Plus SoC";
129
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/imx8mp-evk.c
132
+++ b/hw/arm/imx8mp-evk.c
133
@@ -XXX,XX +XXX,XX @@ static void imx8mp_evk_init(MachineState *machine)
134
135
s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP));
136
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
137
+ object_property_set_uint(OBJECT(s), "fec1-phy-num", 1, &error_fatal);
138
qdev_realize(DEVICE(s), NULL, &error_fatal);
139
140
memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
141
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hw/arm/Kconfig
144
+++ b/hw/arm/Kconfig
145
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
146
select FSL_IMX8MP_ANALOG
147
select FSL_IMX8MP_CCM
148
select IMX
149
+ select IMX_FEC
150
select IMX_I2C
151
select OR_IRQ
152
select PCI_EXPRESS_DESIGNWARE
153
--
154
2.43.0
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Split the USB MMIO regions to better keep track of the implemented vs.
4
unimplemented regions.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Message-id: 20250223114708.1780-16-shentey@gmail.com
9
[PMM: drop "static const" from usb_table for GCC 7.5]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/system/arm/imx8mp-evk.rst | 1 +
13
include/hw/arm/fsl-imx8mp.h | 12 +++++++++++
14
hw/arm/fsl-imx8mp.c | 37 ++++++++++++++++++++++++++++++++--
15
hw/arm/Kconfig | 1 +
16
4 files changed, 49 insertions(+), 2 deletions(-)
17
18
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
19
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/imx8mp-evk.rst
21
+++ b/docs/system/arm/imx8mp-evk.rst
22
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
23
* 3 USDHC Storage Controllers
24
* 1 Designware PCI Express Controller
25
* 1 Ethernet Controller
26
+ * 2 Designware USB 3 Controllers
27
* 5 GPIO Controllers
28
* 6 I2C Controllers
29
* 3 SPI Controllers
30
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/arm/fsl-imx8mp.h
33
+++ b/include/hw/arm/fsl-imx8mp.h
34
@@ -XXX,XX +XXX,XX @@
35
#include "hw/sd/sdhci.h"
36
#include "hw/ssi/imx_spi.h"
37
#include "hw/timer/imx_gpt.h"
38
+#include "hw/usb/hcd-dwc3.h"
39
#include "hw/watchdog/wdt_imx2.h"
40
#include "qom/object.h"
41
#include "qemu/units.h"
42
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpConfiguration {
43
FSL_IMX8MP_NUM_I2CS = 6,
44
FSL_IMX8MP_NUM_IRQS = 160,
45
FSL_IMX8MP_NUM_UARTS = 4,
46
+ FSL_IMX8MP_NUM_USBS = 2,
47
FSL_IMX8MP_NUM_USDHCS = 3,
48
FSL_IMX8MP_NUM_WDTS = 3,
49
};
50
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
51
IMXFECState enet;
52
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
53
IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
54
+ USBDWC3 usb[FSL_IMX8MP_NUM_USBS];
55
DesignwarePCIEHost pcie;
56
FslImx8mPciePhyState pcie_phy;
57
OrIRQState gpt5_gpt6_irq;
58
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpMemoryRegions {
59
FSL_IMX8MP_UART4,
60
FSL_IMX8MP_USB1,
61
FSL_IMX8MP_USB2,
62
+ FSL_IMX8MP_USB1_DEV,
63
+ FSL_IMX8MP_USB2_DEV,
64
+ FSL_IMX8MP_USB1_OTG,
65
+ FSL_IMX8MP_USB2_OTG,
66
+ FSL_IMX8MP_USB1_GLUE,
67
+ FSL_IMX8MP_USB2_GLUE,
68
FSL_IMX8MP_USDHC1,
69
FSL_IMX8MP_USDHC2,
70
FSL_IMX8MP_USDHC3,
71
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
72
FSL_IMX8MP_I2C3_IRQ = 37,
73
FSL_IMX8MP_I2C4_IRQ = 38,
74
75
+ FSL_IMX8MP_USB1_IRQ = 40,
76
+ FSL_IMX8MP_USB2_IRQ = 41,
77
+
78
FSL_IMX8MP_GPT1_IRQ = 55,
79
FSL_IMX8MP_GPT2_IRQ = 54,
80
FSL_IMX8MP_GPT3_IRQ = 53,
81
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/arm/fsl-imx8mp.c
84
+++ b/hw/arm/fsl-imx8mp.c
85
@@ -XXX,XX +XXX,XX @@ static const struct {
86
[FSL_IMX8MP_VPU_VC8000E_ENCODER] = { 0x38320000, 2 * MiB, "vpu_vc8000e_encoder" },
87
[FSL_IMX8MP_VPU_G2_DECODER] = { 0x38310000, 2 * MiB, "vpu_g2_decoder" },
88
[FSL_IMX8MP_VPU_G1_DECODER] = { 0x38300000, 2 * MiB, "vpu_g1_decoder" },
89
- [FSL_IMX8MP_USB2] = { 0x38200000, 1 * MiB, "usb2" },
90
- [FSL_IMX8MP_USB1] = { 0x38100000, 1 * MiB, "usb1" },
91
+ [FSL_IMX8MP_USB2_GLUE] = { 0x382f0000, 0x100, "usb2_glue" },
92
+ [FSL_IMX8MP_USB2_OTG] = { 0x3820cc00, 0x100, "usb2_otg" },
93
+ [FSL_IMX8MP_USB2_DEV] = { 0x3820c700, 0x500, "usb2_dev" },
94
+ [FSL_IMX8MP_USB2] = { 0x38200000, 0xc700, "usb2" },
95
+ [FSL_IMX8MP_USB1_GLUE] = { 0x381f0000, 0x100, "usb1_glue" },
96
+ [FSL_IMX8MP_USB1_OTG] = { 0x3810cc00, 0x100, "usb1_otg" },
97
+ [FSL_IMX8MP_USB1_DEV] = { 0x3810c700, 0x500, "usb1_dev" },
98
+ [FSL_IMX8MP_USB1] = { 0x38100000, 0xc700, "usb1" },
99
[FSL_IMX8MP_GPU2D] = { 0x38008000, 32 * KiB, "gpu2d" },
100
[FSL_IMX8MP_GPU3D] = { 0x38000000, 32 * KiB, "gpu3d" },
101
[FSL_IMX8MP_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
102
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
103
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
104
}
105
106
+ for (i = 0; i < FSL_IMX8MP_NUM_USBS; i++) {
107
+ g_autofree char *name = g_strdup_printf("usb%d", i);
108
+ object_initialize_child(obj, name, &s->usb[i], TYPE_USB_DWC3);
109
+ }
110
+
111
for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
112
g_autofree char *name = g_strdup_printf("spi%d", i + 1);
113
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
114
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
115
qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
116
}
117
118
+ /* USBs */
119
+ for (i = 0; i < FSL_IMX8MP_NUM_USBS; i++) {
120
+ struct {
121
+ hwaddr addr;
122
+ unsigned int irq;
123
+ } usb_table[FSL_IMX8MP_NUM_USBS] = {
124
+ { fsl_imx8mp_memmap[FSL_IMX8MP_USB1].addr, FSL_IMX8MP_USB1_IRQ },
125
+ { fsl_imx8mp_memmap[FSL_IMX8MP_USB2].addr, FSL_IMX8MP_USB2_IRQ },
126
+ };
127
+
128
+ qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p2", 1);
129
+ qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p3", 1);
130
+ qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "slots", 2);
131
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), errp)) {
132
+ return;
133
+ }
134
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
135
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0,
136
+ qdev_get_gpio_in(gicdev, usb_table[i].irq));
137
+ }
138
+
139
/* ECSPIs */
140
for (i = 0; i < FSL_IMX8MP_NUM_ECSPIS; i++) {
141
struct {
142
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
143
case FSL_IMX8MP_RAM:
144
case FSL_IMX8MP_SNVS_HP:
145
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
146
+ case FSL_IMX8MP_USB1 ... FSL_IMX8MP_USB2:
147
case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
148
case FSL_IMX8MP_WDOG1 ... FSL_IMX8MP_WDOG3:
149
/* device implemented and treated above */
150
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
151
index XXXXXXX..XXXXXXX 100644
152
--- a/hw/arm/Kconfig
153
+++ b/hw/arm/Kconfig
154
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
155
select PCI_EXPRESS_FSL_IMX8M_PHY
156
select SDHCI
157
select UNIMP
158
+ select USB_DWC3
159
select WDT_IMX2
160
161
config FSL_IMX8MP_EVK
162
--
163
2.43.0
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Message-id: 20250223114708.1780-18-shentey@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
include/hw/arm/fsl-imx8mp.h | 1 +
9
hw/arm/fsl-imx8mp.c | 11 +++++++++++
10
2 files changed, 12 insertions(+)
11
12
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/fsl-imx8mp.h
15
+++ b/include/hw/arm/fsl-imx8mp.h
16
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
17
DesignwarePCIEHost pcie;
18
FslImx8mPciePhyState pcie_phy;
19
OrIRQState gpt5_gpt6_irq;
20
+ MemoryRegion ocram;
21
22
uint32_t phy_num;
23
bool phy_connected;
24
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/fsl-imx8mp.c
27
+++ b/hw/arm/fsl-imx8mp.c
28
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
29
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
30
fsl_imx8mp_memmap[FSL_IMX8MP_PCIE_PHY1].addr);
31
32
+ /* On-Chip RAM */
33
+ if (!memory_region_init_ram(&s->ocram, NULL, "imx8mp.ocram",
34
+ fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].size,
35
+ errp)) {
36
+ return;
37
+ }
38
+ memory_region_add_subregion(get_system_memory(),
39
+ fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].addr,
40
+ &s->ocram);
41
+
42
/* Unimplemented devices */
43
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
44
switch (i) {
45
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
46
case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
47
case FSL_IMX8MP_ENET1:
48
case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
49
+ case FSL_IMX8MP_OCRAM:
50
case FSL_IMX8MP_PCIE1:
51
case FSL_IMX8MP_PCIE_PHY1:
52
case FSL_IMX8MP_RAM:
53
--
54
2.43.0
diff view generated by jsdifflib