1
Arm queue -- mostly the first slice of my Musca patches.
1
Hi; here's another Arm pullreq: the big thing in here is
2
Bernhard's imx8mp-evk board model; there's also various cleanup
3
type patches from me, as well as some bugfixes.
2
4
3
thanks
5
thanks
4
-- PMM
6
-- PMM
5
7
6
The following changes since commit fc3dbb90f2eb069801bfb4cfe9cbc83cf9c5f4a9:
8
The following changes since commit b69801dd6b1eb4d107f7c2f643adf0a4e3ec9124:
7
9
8
Merge remote-tracking branch 'remotes/jnsnow/tags/bitmaps-pull-request' into staging (2019-02-21 13:09:33 +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)
9
11
10
are available in the Git repository at:
12
are available in the Git repository at:
11
13
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190221
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250225
13
15
14
for you to fetch changes up to 3733f80308d2a7f23f5e39b039e0547aba6c07f1:
16
for you to fetch changes up to 1aaf3478684ff1cd02d1b36c32a00bfac9a5dbd5:
15
17
16
hw/arm/armsse: Make 0x5... alias region work for per-CPU devices (2019-02-21 18:17:48 +0000)
18
hw/arm/fsl-imx8mp: Add on-chip RAM (2025-02-25 17:24:00 +0000)
17
19
18
----------------------------------------------------------------
20
----------------------------------------------------------------
19
target-arm queue:
21
target-arm queue:
20
* Model the Arm "Musca" development boards: "musca-a" and "musca-b1"
22
* hw/arm/smmuv3: Fill u.f_cd_fetch.addr for SMMU_EVT_F_CD_FETCH
21
* Implement the ARMv8.3-JSConv extension
23
* hw/arm/virt: Support larger highmem MMIO regions
22
* v8M MPU should use background region as default, not always
24
* machine: Centralize -machine dumpdtb option handling and report
23
* Stop unintentional sign extension in pmu_init
25
attempt to dump nonexistent DTB as an error
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")
24
32
25
----------------------------------------------------------------
33
----------------------------------------------------------------
26
Aaron Lindsay OS (1):
34
Bernhard Beschow (16):
27
target/arm: Stop unintentional sign extension in pmu_init
35
hw/usb/hcd-dwc3: Align global registers size with Linux
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
28
51
29
Peter Maydell (16):
52
Joelle van Dyne (2):
30
hw/arm/armsse: Fix memory leak in error-exit path
53
target/arm/hvf: Disable SME feature
31
target/arm: v8M MPU should use background region as default, not always
54
target/arm/hvf: sign extend the data for a load operation when SSE=1
32
hw/misc/tz-ppc: Support having unused ports in the middle of the range
33
hw/timer/pl031: Allow use as an embedded-struct device
34
hw/timer/pl031: Convert to using trace events
35
hw/char/pl011: Allow use as an embedded-struct device
36
hw/char/pl011: Support all interrupt lines
37
hw/char/pl011: Use '0x' prefix when logging hex numbers
38
hw/arm/armsse: Document SRAM_ADDR_WIDTH property in header comment
39
hw/arm/armsse: Allow boards to specify init-svtor
40
hw/arm/musca.c: Implement models of the Musca-A and -B1 boards
41
hw/arm/musca: Add PPCs
42
hw/arm/musca: Add MPCs
43
hw/arm/musca: Wire up PL031 RTC
44
hw/arm/musca: Wire up PL011 UARTs
45
hw/arm/armsse: Make 0x5... alias region work for per-CPU devices
46
55
47
Richard Henderson (4):
56
Matthew R. Ochs (1):
48
target/arm: Restructure disas_fp_int_conv
57
hw/arm/virt: Support larger highmem MMIO regions
49
target/arm: Split out vfp_helper.c
50
target/arm: Rearrange Floating-point data-processing (2 regs)
51
target/arm: Implement ARMv8.3-JSConv
52
58
53
hw/arm/Makefile.objs | 1 +
59
Nicolin Chen (1):
54
target/arm/Makefile.objs | 2 +-
60
hw/arm/smmuv3: Fill u.f_cd_fetch.addr for SMMU_EVT_F_CD_FETCH
55
include/hw/arm/armsse.h | 7 +-
56
include/hw/char/pl011.h | 34 ++
57
include/hw/misc/tz-ppc.h | 8 +-
58
include/hw/timer/pl031.h | 44 ++
59
target/arm/cpu.h | 10 +
60
target/arm/helper.h | 3 +
61
hw/arm/armsse.c | 44 +-
62
hw/arm/musca.c | 669 ++++++++++++++++++++++
63
hw/char/pl011.c | 81 +--
64
hw/misc/tz-ppc.c | 32 ++
65
hw/timer/pl031.c | 80 ++-
66
target/arm/cpu.c | 1 +
67
target/arm/cpu64.c | 2 +
68
target/arm/helper.c | 1072 +----------------------------------
69
target/arm/translate-a64.c | 120 ++--
70
target/arm/translate.c | 237 ++++----
71
target/arm/vfp_helper.c | 1176 +++++++++++++++++++++++++++++++++++++++
72
MAINTAINERS | 7 +
73
default-configs/arm-softmmu.mak | 1 +
74
hw/timer/trace-events | 6 +
75
22 files changed, 2307 insertions(+), 1330 deletions(-)
76
create mode 100644 include/hw/timer/pl031.h
77
create mode 100644 hw/arm/musca.c
78
create mode 100644 target/arm/vfp_helper.c
79
61
62
Peter Maydell (22):
63
monitor/hmp-cmds.c: Clean up hmp_dumpdtb printf
64
hw/openrisc: Support monitor dumpdtb command
65
hw/mips/boston: Check for error return from boston_fdt_filter()
66
hw/mips/boston: Support dumpdtb monitor commands
67
hw: Centralize handling of -machine dumpdtb option
68
hw/core/machine.c: Make -machine dumpdtb=file.dtb with no DTB an error
69
fpu: Make targets specify floatx80 default Inf at runtime
70
target/m68k: Avoid using floatx80_infinity global const
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
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
1
From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
1
From: Nicolin Chen <nicolinc@nvidia.com>
2
2
3
This was introduced by
3
When we fill in the SMMUEventInfo for SMMU_EVT_F_CD_FETCH we write
4
commit bf8d09694ccc07487cd73d7562081fdaec3370c8
4
the address into the f_ste_fetch member of the union, but then when
5
target/arm: Don't clear supported PMU events when initializing PMCEID1
5
we come to read it back in smmuv3_record_event() we will (correctly)
6
and identified by Coverity (CID 1398645).
6
be using the f_cd_fetch member.
7
7
8
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
8
This is more like a cosmetics fix since the f_cd_fetch and f_ste_fetch are
9
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
basically the same field since they are in the exact same union with exact
10
Message-id: 20190219144621.450-1-aaron@os.amperecomputing.com
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
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
16
---
14
target/arm/helper.c | 2 +-
17
hw/arm/smmuv3.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
18
1 file changed, 1 insertion(+), 1 deletion(-)
16
19
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
22
--- a/hw/arm/smmuv3.c
20
+++ b/target/arm/helper.c
23
+++ b/hw/arm/smmuv3.c
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu)
24
@@ -XXX,XX +XXX,XX @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTransCfg *cfg,
22
25
qemu_log_mask(LOG_GUEST_ERROR,
23
if (cnt->supported(&cpu->env)) {
26
"Cannot fetch pte at address=0x%"PRIx64"\n", addr);
24
supported_event_map[cnt->number] = i;
27
event->type = SMMU_EVT_F_CD_FETCH;
25
- uint64_t event_mask = 1 << (cnt->number & 0x1f);
28
- event->u.f_ste_fetch.addr = addr;
26
+ uint64_t event_mask = 1ULL << (cnt->number & 0x1f);
29
+ event->u.f_cd_fetch.addr = addr;
27
if (cnt->number & 0x20) {
30
return -EINVAL;
28
cpu->pmceid1 |= event_mask;
31
}
29
} else {
32
for (i = 0; i < ARRAY_SIZE(buf->word); i++) {
30
--
33
--
31
2.20.1
34
2.43.0
32
33
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
Many of the devices on the Musca board live behind TrustZone
1
In hmp_dumpdtb(), we print a message when the command succeeds. This
2
Peripheral Protection Controllers (PPCs); add models of the
2
message is missing the trailing \n, so the HMP command prompt is
3
PPCs, using a similar scheme to the MPS2 board models.
3
printed immediately after it. We also weren't capitalizing 'DTB', or
4
This commit wires up the PPCs with "unimplemented device"
4
quoting the filename in the message. Fix these nits.
5
stubs behind them in the correct places in the address map.
6
5
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20250206151214.2947842-2-peter.maydell@linaro.org
9
---
10
---
10
hw/arm/musca.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++
11
monitor/hmp-cmds.c | 2 +-
11
1 file changed, 289 insertions(+)
12
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
13
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
14
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/musca.c
16
--- a/monitor/hmp-cmds.c
16
+++ b/hw/arm/musca.c
17
+++ b/monitor/hmp-cmds.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
18
#include "hw/arm/armsse.h"
19
return;
19
#include "hw/boards.h"
20
#include "hw/core/split-irq.h"
21
+#include "hw/misc/tz-ppc.h"
22
+#include "hw/misc/unimp.h"
23
24
#define MUSCA_NUMIRQ_MAX 96
25
+#define MUSCA_PPC_MAX 3
26
27
typedef enum MuscaType {
28
MUSCA_A,
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
30
31
ARMSSE sse;
32
SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
33
+ SplitIRQ sec_resp_splitter;
34
+ TZPPC ppc[MUSCA_PPC_MAX];
35
+ MemoryRegion container;
36
+ UnimplementedDeviceState eflash[2];
37
+ UnimplementedDeviceState qspi;
38
+ UnimplementedDeviceState mpc[5];
39
+ UnimplementedDeviceState mhu[2];
40
+ UnimplementedDeviceState pwm[3];
41
+ UnimplementedDeviceState i2s;
42
+ UnimplementedDeviceState uart[2];
43
+ UnimplementedDeviceState i2c[2];
44
+ UnimplementedDeviceState spi;
45
+ UnimplementedDeviceState scc;
46
+ UnimplementedDeviceState timer;
47
+ UnimplementedDeviceState rtc;
48
+ UnimplementedDeviceState pvt;
49
+ UnimplementedDeviceState sdio;
50
+ UnimplementedDeviceState gpio;
51
} MuscaMachineState;
52
53
#define TYPE_MUSCA_MACHINE "musca"
54
@@ -XXX,XX +XXX,XX @@ typedef struct {
55
*/
56
#define SYSCLK_FRQ 40000000
57
58
+/*
59
+ * Most of the devices in the Musca board sit behind Peripheral Protection
60
+ * Controllers. These data structures define the layout of which devices
61
+ * sit behind which PPCs.
62
+ * The devfn for each port is a function which creates, configures
63
+ * and initializes the device, returning the MemoryRegion which
64
+ * needs to be plugged into the downstream end of the PPC port.
65
+ */
66
+typedef MemoryRegion *MakeDevFn(MuscaMachineState *mms, void *opaque,
67
+ const char *name, hwaddr size);
68
+
69
+typedef struct PPCPortInfo {
70
+ const char *name;
71
+ MakeDevFn *devfn;
72
+ void *opaque;
73
+ hwaddr addr;
74
+ hwaddr size;
75
+} PPCPortInfo;
76
+
77
+typedef struct PPCInfo {
78
+ const char *name;
79
+ PPCPortInfo ports[TZ_NUM_PORTS];
80
+} PPCInfo;
81
+
82
+static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
83
+ void *opaque, const char *name, hwaddr size)
84
+{
85
+ /*
86
+ * Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
87
+ * and return a pointer to its MemoryRegion.
88
+ */
89
+ UnimplementedDeviceState *uds = opaque;
90
+
91
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
92
+ sizeof(UnimplementedDeviceState),
93
+ TYPE_UNIMPLEMENTED_DEVICE);
94
+ qdev_prop_set_string(DEVICE(uds), "name", name);
95
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
96
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
97
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
98
+}
99
+
100
+static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
101
+ const char *name, hwaddr size)
102
+{
103
+ /*
104
+ * Create the container MemoryRegion for all the devices that live
105
+ * behind the Musca-A PPC's single port. These devices don't have a PPC
106
+ * port each, but we use the PPCPortInfo struct as a convenient way
107
+ * to describe them. Note that addresses here are relative to the base
108
+ * address of the PPC port region: 0x40100000, and devices appear both
109
+ * at the 0x4... NS region and the 0x5... S region.
110
+ */
111
+ int i;
112
+ MemoryRegion *container = &mms->container;
113
+
114
+ const PPCPortInfo devices[] = {
115
+ { "uart0", make_unimp_dev, &mms->uart[0], 0x1000, 0x1000 },
116
+ { "uart1", make_unimp_dev, &mms->uart[1], 0x2000, 0x1000 },
117
+ { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
118
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
119
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
120
+ { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
121
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
122
+ { "rtc", make_unimp_dev, &mms->rtc, 0x8000, 0x1000 },
123
+ { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
124
+ { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
125
+ { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
126
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
127
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
128
+ { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
129
+ { "mpc0", make_unimp_dev, &mms->mpc[0], 0x12000, 0x1000 },
130
+ { "mpc1", make_unimp_dev, &mms->mpc[1], 0x13000, 0x1000 },
131
+ };
132
+
133
+ memory_region_init(container, OBJECT(mms), "musca-device-container", size);
134
+
135
+ for (i = 0; i < ARRAY_SIZE(devices); i++) {
136
+ const PPCPortInfo *pinfo = &devices[i];
137
+ MemoryRegion *mr;
138
+
139
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
140
+ memory_region_add_subregion(container, pinfo->addr, mr);
141
+ }
142
+
143
+ return &mms->container;
144
+}
145
+
146
static void musca_init(MachineState *machine)
147
{
148
MuscaMachineState *mms = MUSCA_MACHINE(machine);
149
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
150
MachineClass *mc = MACHINE_GET_CLASS(machine);
151
MemoryRegion *system_memory = get_system_memory();
152
DeviceState *ssedev;
153
+ DeviceState *dev_splitter;
154
+ const PPCInfo *ppcs;
155
+ int num_ppcs;
156
int i;
157
158
assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
159
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
160
"EXP_CPU1_IRQ", i));
161
}
20
}
162
21
163
+ /*
22
- monitor_printf(mon, "dtb dumped to %s", filename);
164
+ * The sec_resp_cfg output from the SSE-200 must be split into multiple
23
+ monitor_printf(mon, "DTB dumped to '%s'\n", filename);
165
+ * lines, one for each of the PPCs we create here.
166
+ */
167
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
168
+ TYPE_SPLIT_IRQ);
169
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
170
+ OBJECT(&mms->sec_resp_splitter), &error_fatal);
171
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter),
172
+ ARRAY_SIZE(mms->ppc), "num-lines", &error_fatal);
173
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
174
+ "realized", &error_fatal);
175
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
176
+ qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0,
177
+ qdev_get_gpio_in(dev_splitter, 0));
178
+
179
+ /*
180
+ * Most of the devices in the board are behind Peripheral Protection
181
+ * Controllers. The required order for initializing things is:
182
+ * + initialize the PPC
183
+ * + initialize, configure and realize downstream devices
184
+ * + connect downstream device MemoryRegions to the PPC
185
+ * + realize the PPC
186
+ * + map the PPC's MemoryRegions to the places in the address map
187
+ * where the downstream devices should appear
188
+ * + wire up the PPC's control lines to the SSE object
189
+ *
190
+ * The PPC mapping differs for the -A and -B1 variants; the -A version
191
+ * is much simpler, using only a single port of a single PPC and putting
192
+ * all the devices behind that.
193
+ */
194
+ const PPCInfo a_ppcs[] = { {
195
+ .name = "ahb_ppcexp0",
196
+ .ports = {
197
+ { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 },
198
+ },
199
+ },
200
+ };
201
+
202
+ /*
203
+ * Devices listed with an 0x4.. address appear in both the NS 0x4.. region
204
+ * and the 0x5.. S region. Devices listed with an 0x5.. address appear
205
+ * only in the S region.
206
+ */
207
+ const PPCInfo b1_ppcs[] = { {
208
+ .name = "apb_ppcexp0",
209
+ .ports = {
210
+ { "eflash0", make_unimp_dev, &mms->eflash[0],
211
+ 0x52400000, 0x1000 },
212
+ { "eflash1", make_unimp_dev, &mms->eflash[1],
213
+ 0x52500000, 0x1000 },
214
+ { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
215
+ { "mpc0", make_unimp_dev, &mms->mpc[0], 0x52000000, 0x1000 },
216
+ { "mpc1", make_unimp_dev, &mms->mpc[1], 0x52100000, 0x1000 },
217
+ { "mpc2", make_unimp_dev, &mms->mpc[2], 0x52200000, 0x1000 },
218
+ { "mpc3", make_unimp_dev, &mms->mpc[3], 0x52300000, 0x1000 },
219
+ { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
220
+ { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
221
+ { }, /* port 9: unused */
222
+ { }, /* port 10: unused */
223
+ { }, /* port 11: unused */
224
+ { }, /* port 12: unused */
225
+ { }, /* port 13: unused */
226
+ { "mpc4", make_unimp_dev, &mms->mpc[4], 0x52e00000, 0x1000 },
227
+ },
228
+ }, {
229
+ .name = "apb_ppcexp1",
230
+ .ports = {
231
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 },
232
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
233
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
234
+ { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
235
+ { "uart0", make_unimp_dev, &mms->uart[0], 0x40105000, 0x1000 },
236
+ { "uart1", make_unimp_dev, &mms->uart[1], 0x40106000, 0x1000 },
237
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
238
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
239
+ { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
240
+ { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
241
+ { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
242
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4010d000, 0x1000 },
243
+ { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
244
+ { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
245
+ },
246
+ }, {
247
+ .name = "ahb_ppcexp0",
248
+ .ports = {
249
+ { }, /* port 0: unused */
250
+ { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 },
251
+ },
252
+ },
253
+ };
254
+
255
+ switch (mmc->type) {
256
+ case MUSCA_A:
257
+ ppcs = a_ppcs;
258
+ num_ppcs = ARRAY_SIZE(a_ppcs);
259
+ break;
260
+ case MUSCA_B1:
261
+ ppcs = b1_ppcs;
262
+ num_ppcs = ARRAY_SIZE(b1_ppcs);
263
+ break;
264
+ default:
265
+ g_assert_not_reached();
266
+ }
267
+ assert(num_ppcs <= MUSCA_PPC_MAX);
268
+
269
+ for (i = 0; i < num_ppcs; i++) {
270
+ const PPCInfo *ppcinfo = &ppcs[i];
271
+ TZPPC *ppc = &mms->ppc[i];
272
+ DeviceState *ppcdev;
273
+ int port;
274
+ char *gpioname;
275
+
276
+ sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc,
277
+ sizeof(TZPPC), TYPE_TZ_PPC);
278
+ ppcdev = DEVICE(ppc);
279
+
280
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
281
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
282
+ MemoryRegion *mr;
283
+ char *portname;
284
+
285
+ if (!pinfo->devfn) {
286
+ continue;
287
+ }
288
+
289
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
290
+ portname = g_strdup_printf("port[%d]", port);
291
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
292
+ portname, &error_fatal);
293
+ g_free(portname);
294
+ }
295
+
296
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
297
+
298
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
299
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
300
+
301
+ if (!pinfo->devfn) {
302
+ continue;
303
+ }
304
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
305
+
306
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
307
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
308
+ qdev_get_gpio_in_named(ppcdev,
309
+ "cfg_nonsec",
310
+ port));
311
+ g_free(gpioname);
312
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
313
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
314
+ qdev_get_gpio_in_named(ppcdev,
315
+ "cfg_ap", port));
316
+ g_free(gpioname);
317
+ }
318
+
319
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
320
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
321
+ qdev_get_gpio_in_named(ppcdev,
322
+ "irq_enable", 0));
323
+ g_free(gpioname);
324
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
325
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
326
+ qdev_get_gpio_in_named(ppcdev,
327
+ "irq_clear", 0));
328
+ g_free(gpioname);
329
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
330
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
331
+ qdev_get_gpio_in_named(ssedev,
332
+ gpioname, 0));
333
+ g_free(gpioname);
334
+
335
+ qdev_connect_gpio_out(dev_splitter, i,
336
+ qdev_get_gpio_in_named(ppcdev,
337
+ "cfg_sec_resp", 0));
338
+ }
339
+
340
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
341
}
24
}
342
25
#endif
343
--
26
--
344
2.20.1
27
2.43.0
345
28
346
29
diff view generated by jsdifflib
1
The pl011 logs when the guest makes a bad access. It prints
1
The openrisc machines don't set MachineState::fdt to point to their
2
the address offset in hex but confusingly omits the '0x'
2
DTB blob. This means that although the command line '-machine
3
prefix; add it.
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".
6
7
Set MachineState::fdt in openrisc_load_fdt(), when we write it to
8
guest memory.
4
9
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@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
8
---
14
---
9
hw/char/pl011.c | 4 ++--
15
include/hw/openrisc/boot.h | 3 ++-
10
1 file changed, 2 insertions(+), 2 deletions(-)
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(-)
11
20
12
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
21
diff --git a/include/hw/openrisc/boot.h b/include/hw/openrisc/boot.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/char/pl011.c
23
--- a/include/hw/openrisc/boot.h
15
+++ b/hw/char/pl011.c
24
+++ b/include/hw/openrisc/boot.h
16
@@ -XXX,XX +XXX,XX @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
25
@@ -XXX,XX +XXX,XX @@
17
break;
26
#define OPENRISC_BOOT_H
18
default:
27
19
qemu_log_mask(LOG_GUEST_ERROR,
28
#include "exec/cpu-defs.h"
20
- "pl011_read: Bad offset %x\n", (int)offset);
29
+#include "hw/boards.h"
21
+ "pl011_read: Bad offset 0x%x\n", (int)offset);
30
22
r = 0;
31
hwaddr openrisc_load_kernel(ram_addr_t ram_size,
23
break;
32
const char *kernel_filename,
24
}
33
@@ -XXX,XX +XXX,XX @@ hwaddr openrisc_load_kernel(ram_addr_t ram_size,
25
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
34
hwaddr openrisc_load_initrd(void *fdt, const char *filename,
26
break;
35
hwaddr load_start, uint64_t mem_size);
27
default:
36
28
qemu_log_mask(LOG_GUEST_ERROR,
37
-uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
29
- "pl011_write: Bad offset %x\n", (int)offset);
38
+uint32_t openrisc_load_fdt(MachineState *ms, void *fdt, hwaddr load_start,
30
+ "pl011_write: Bad offset 0x%x\n", (int)offset);
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);
31
}
78
}
32
}
79
}
33
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
}
34
--
93
--
35
2.20.1
94
2.43.0
36
95
37
96
diff view generated by jsdifflib
1
The Musca boards have DAPLink firmware that sets the initial
1
The function boston_fdt_filter() can return NULL on errors (in which
2
secure VTOR value (the location of the vector table) differently
2
case it will print an error message). When we call this from the
3
depending on the boot mode (from flash, from RAM, etc). Export
3
non-FIT-image codepath, we aren't checking the return value, so we
4
the init-svtor as a QOM property of the ARMSSE object so that
4
will plough on with a NULL pointer, and segfault in fdt_totalsize().
5
the board can change it.
5
Check for errors here.
6
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20250206151214.2947842-4-peter.maydell@linaro.org
10
---
10
---
11
include/hw/arm/armsse.h | 3 +++
11
hw/mips/boston.c | 4 ++++
12
hw/arm/armsse.c | 8 ++++----
12
1 file changed, 4 insertions(+)
13
2 files changed, 7 insertions(+), 4 deletions(-)
14
13
15
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
14
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/armsse.h
16
--- a/hw/mips/boston.c
18
+++ b/include/hw/arm/armsse.h
17
+++ b/hw/mips/boston.c
19
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
20
* if necessary.)
19
21
* + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
20
dtb_load_data = boston_fdt_filter(s, dtb_file_data,
22
* address of each SRAM bank (and thus the total amount of internal SRAM)
21
NULL, &dtb_vaddr);
23
+ * + QOM property "init-svtor" sets the initial value of the CPU SVTOR register
22
+ if (!dtb_load_data) {
24
+ * (where it expects to load the PC and SP from the vector table on reset)
23
+ /* boston_fdt_filter() already printed the error for us */
25
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
24
+ exit(1);
26
* which are wired to its NVIC lines 32 .. n+32
25
+ }
27
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
26
28
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
27
/* Calculate real fdt size after filter */
29
uint32_t exp_numirq;
28
dt_size = fdt_totalsize(dtb_load_data);
30
uint32_t mainclk_frq;
31
uint32_t sram_addr_width;
32
+ uint32_t init_svtor;
33
} ARMSSE;
34
35
typedef struct ARMSSEInfo ARMSSEInfo;
36
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/armsse.c
39
+++ b/hw/arm/armsse.c
40
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
41
* the INITSVTOR* registers before powering up the CPUs in any case,
42
* so the hardware's default value doesn't matter. QEMU doesn't emulate
43
* the control processor, so instead we behave in the way that the
44
- * firmware does. All boards currently known about have firmware that
45
- * sets the INITSVTOR0 and INITSVTOR1 registers to 0x10000000, like the
46
- * IoTKit default. We can make this more configurable if necessary.
47
+ * firmware does. The initial value is configurable by the board code
48
+ * to match whatever its firmware does.
49
*/
50
- qdev_prop_set_uint32(cpudev, "init-svtor", 0x10000000);
51
+ qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
52
/*
53
* Start all CPUs except CPU0 powered down. In real hardware it is
54
* a configurable property of the SSE-200 which CPUs start powered up
55
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
56
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
57
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
58
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
59
+ DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
60
DEFINE_PROP_END_OF_LIST()
61
};
62
63
--
29
--
64
2.20.1
30
2.43.0
65
31
66
32
diff view generated by jsdifflib
1
Convert the debug printing in the PL031 device to use trace events,
1
The boston machine doesn't set MachineState::fdt to the DTB blob that
2
and augment it to cover the interesting parts of device operation.
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).
3
18
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20250206151214.2947842-5-peter.maydell@linaro.org
7
---
22
---
8
hw/timer/pl031.c | 55 +++++++++++++++++++++++--------------------
23
include/hw/loader-fit.h | 21 ++++++++++++++++++---
9
hw/timer/trace-events | 6 +++++
24
hw/core/loader-fit.c | 38 +++++++++++++++++++++-----------------
10
2 files changed, 36 insertions(+), 25 deletions(-)
25
hw/mips/boston.c | 11 +++++++----
11
26
3 files changed, 46 insertions(+), 24 deletions(-)
12
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
27
28
diff --git a/include/hw/loader-fit.h b/include/hw/loader-fit.h
13
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/timer/pl031.c
30
--- a/include/hw/loader-fit.h
15
+++ b/hw/timer/pl031.c
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
16
@@ -XXX,XX +XXX,XX @@
67
@@ -XXX,XX +XXX,XX @@
17
#include "sysemu/sysemu.h"
68
18
#include "qemu/cutils.h"
69
#define FIT_LOADER_MAX_PATH (128)
19
#include "qemu/log.h"
70
20
-
71
-static const void *fit_load_image_alloc(const void *itb, const char *name,
21
-//#define DEBUG_PL031
72
- int *poff, size_t *psz, Error **errp)
22
-
73
+static void *fit_load_image_alloc(const void *itb, const char *name,
23
-#ifdef DEBUG_PL031
74
+ int *poff, size_t *psz, Error **errp)
24
-#define DPRINTF(fmt, ...) \
75
{
25
-do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
76
const void *data;
26
-#else
77
const char *comp;
27
-#define DPRINTF(fmt, ...) do {} while(0)
78
@@ -XXX,XX +XXX,XX @@ static const void *fit_load_image_alloc(const void *itb, const char *name,
28
-#endif
79
return NULL;
29
+#include "trace.h"
80
}
30
81
31
#define RTC_DR 0x00 /* Data read register */
82
- data = g_realloc(uncomp_data, uncomp_len);
32
#define RTC_MR 0x04 /* Match register */
83
+ uncomp_data = g_realloc(uncomp_data, uncomp_len);
33
@@ -XXX,XX +XXX,XX @@ static const unsigned char pl031_id[] = {
84
if (psz) {
34
85
*psz = uncomp_len;
35
static void pl031_update(PL031State *s)
86
}
36
{
87
- return data;
37
- qemu_set_irq(s->irq, s->is & s->im);
88
+ return uncomp_data;
38
+ uint32_t flags = s->is & s->im;
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;
39
+
123
+
40
+ trace_pl031_irq_state(flags);
124
+ filtered_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
41
+ qemu_set_irq(s->irq, flags);
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;
42
}
146
}
43
147
44
static void pl031_interrupt(void * opaque)
148
@@ -XXX,XX +XXX,XX @@ out:
45
@@ -XXX,XX +XXX,XX @@ static void pl031_interrupt(void * opaque)
149
return ret;
46
PL031State *s = (PL031State *)opaque;
47
48
s->is = 1;
49
- DPRINTF("Alarm raised\n");
50
+ trace_pl031_alarm_raised();
51
pl031_update(s);
52
}
150
}
53
151
54
@@ -XXX,XX +XXX,XX @@ static void pl031_set_alarm(PL031State *s)
152
-int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
55
/* The timer wraps around. This subtraction also wraps in the same way,
153
+int load_fit(const struct fit_loader *ldr, const char *filename,
56
and gives correct results when alarm < now_ticks. */
154
+ void **pfdt, void *opaque)
57
ticks = s->mr - pl031_get_count(s);
155
{
58
- DPRINTF("Alarm set in %ud ticks\n", ticks);
156
Error *err = NULL;
59
+ trace_pl031_set_alarm(ticks);
157
const struct fit_loader_match *match;
60
if (ticks == 0) {
158
@@ -XXX,XX +XXX,XX @@ int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
61
timer_del(s->timer);
159
goto out;
62
pl031_interrupt(s);
160
}
63
@@ -XXX,XX +XXX,XX @@ static uint64_t pl031_read(void *opaque, hwaddr offset,
161
64
unsigned size)
162
- ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end,
65
{
163
+ ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end, pfdt,
66
PL031State *s = (PL031State *)opaque;
164
&err);
67
-
165
if (ret) {
68
- if (offset >= 0xfe0 && offset < 0x1000)
166
error_report_err(err);
69
- return pl031_id[(offset - 0xfe0) >> 2];
167
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
70
+ uint64_t r;
168
index XXXXXXX..XXXXXXX 100644
71
169
--- a/hw/mips/boston.c
72
switch (offset) {
170
+++ b/hw/mips/boston.c
73
case RTC_DR:
171
@@ -XXX,XX +XXX,XX @@ static void gen_firmware(void *p, hwaddr kernel_entry, hwaddr fdt_addr)
74
- return pl031_get_count(s);
172
kernel_entry);
75
+ r = pl031_get_count(s);
76
+ break;
77
case RTC_MR:
78
- return s->mr;
79
+ r = s->mr;
80
+ break;
81
case RTC_IMSC:
82
- return s->im;
83
+ r = s->im;
84
+ break;
85
case RTC_RIS:
86
- return s->is;
87
+ r = s->is;
88
+ break;
89
case RTC_LR:
90
- return s->lr;
91
+ r = s->lr;
92
+ break;
93
case RTC_CR:
94
/* RTC is permanently enabled. */
95
- return 1;
96
+ r = 1;
97
+ break;
98
case RTC_MIS:
99
- return s->is & s->im;
100
+ r = s->is & s->im;
101
+ break;
102
+ case 0xfe0 ... 0xfff:
103
+ r = pl031_id[(offset - 0xfe0) >> 2];
104
+ break;
105
case RTC_ICR:
106
qemu_log_mask(LOG_GUEST_ERROR,
107
"pl031: read of write-only register at offset 0x%x\n",
108
(int)offset);
109
+ r = 0;
110
break;
111
default:
112
qemu_log_mask(LOG_GUEST_ERROR,
113
"pl031_read: Bad offset 0x%x\n", (int)offset);
114
+ r = 0;
115
break;
116
}
117
118
- return 0;
119
+ trace_pl031_read(offset, r);
120
+ return r;
121
}
173
}
122
174
123
static void pl031_write(void * opaque, hwaddr offset,
175
-static const void *boston_fdt_filter(void *opaque, const void *fdt_orig,
124
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
176
- const void *match_data, hwaddr *load_addr)
125
{
177
+static void *boston_fdt_filter(void *opaque, const void *fdt_orig,
126
PL031State *s = (PL031State *)opaque;
178
+ const void *match_data, hwaddr *load_addr)
127
179
{
128
+ trace_pl031_write(offset, value);
180
BostonState *s = BOSTON(opaque);
129
181
MachineState *machine = s->mach;
130
switch (offset) {
182
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
131
case RTC_LR:
183
if (kernel_size > 0) {
132
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
184
int dt_size;
133
break;
185
g_autofree const void *dtb_file_data = NULL;
134
case RTC_IMSC:
186
- g_autofree const void *dtb_load_data = NULL;
135
s->im = value & 1;
187
+ void *dtb_load_data = NULL;
136
- DPRINTF("Interrupt mask %d\n", s->im);
188
hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB);
137
pl031_update(s);
189
hwaddr dtb_vaddr = cpu_mips_phys_to_kseg0(NULL, dtb_paddr);
138
break;
190
139
case RTC_ICR:
191
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
140
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
192
exit(1);
141
cleared when bit 0 of the written value is set. However the
193
}
142
arm926e documentation (DDI0287B) states that the interrupt is
194
143
cleared when any value is written. */
195
+ machine->fdt = dtb_load_data;
144
- DPRINTF("Interrupt cleared");
196
+
145
s->is = 0;
197
/* Calculate real fdt size after filter */
146
pl031_update(s);
198
dt_size = fdt_totalsize(dtb_load_data);
147
break;
199
rom_add_blob_fixed("dtb", dtb_load_data, dt_size, dtb_paddr);
148
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
200
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
149
index XXXXXXX..XXXXXXX 100644
201
rom_ptr(dtb_paddr, dt_size));
150
--- a/hw/timer/trace-events
202
} else {
151
+++ b/hw/timer/trace-events
203
/* Try to load file as FIT */
152
@@ -XXX,XX +XXX,XX @@ xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec
204
- fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
153
nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
205
+ fit_err = load_fit(&boston_fit_loader, machine->kernel_filename,
154
nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
206
+ &machine->fdt, s);
155
207
if (fit_err) {
156
+# hw/timer/pl031.c
208
error_report("unable to load kernel image");
157
+pl031_irq_state(int level) "irq state %d"
209
exit(1);
158
+pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
159
+pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
160
+pl031_alarm_raised(void) "alarm raised"
161
+pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
162
--
210
--
163
2.20.1
211
2.43.0
164
212
165
213
diff view generated by jsdifflib
1
Wire up the two PL011 UARTs in the Musca board.
1
Currently we handle the 'dumpdtb' machine sub-option ad-hoc in every
2
board model that has an FDT. It's up to the board code to make sure
3
it calls qemu_fdt_dumpdtb() in the right place.
4
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.
2
23
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
26
---
6
hw/arm/musca.c | 34 +++++++++++++++++++++++++++++-----
27
include/system/device_tree.h | 2 --
7
1 file changed, 29 insertions(+), 5 deletions(-)
28
hw/arm/boot.c | 2 --
8
29
hw/core/machine.c | 25 +++++++++++++++++++++++++
9
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
30
hw/loongarch/virt-fdt-build.c | 1 -
10
index XXXXXXX..XXXXXXX 100644
31
hw/mips/boston.c | 1 -
11
--- a/hw/arm/musca.c
32
hw/openrisc/boot.c | 1 -
12
+++ b/hw/arm/musca.c
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
54
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/boot.c
57
+++ b/hw/arm/boot.c
58
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
59
binfo->modify_dtb(binfo, fdt);
60
}
61
62
- qemu_fdt_dumpdtb(fdt, size);
63
-
64
/* Put the DTB into the memory map as a ROM image: this will ensure
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
13
@@ -XXX,XX +XXX,XX @@
71
@@ -XXX,XX +XXX,XX @@
14
#include "qemu/error-report.h"
72
#include "qemu/error-report.h"
15
#include "qapi/error.h"
73
#include "qapi/error.h"
16
#include "exec/address-spaces.h"
74
#include "qapi/qapi-visit-machine.h"
17
+#include "sysemu/sysemu.h"
75
+#include "qapi/qapi-commands-machine.h"
18
#include "hw/arm/arm.h"
76
#include "qemu/madvise.h"
19
#include "hw/arm/armsse.h"
77
#include "qom/object_interfaces.h"
20
#include "hw/boards.h"
78
#include "system/cpus.h"
21
+#include "hw/char/pl011.h"
79
@@ -XXX,XX +XXX,XX @@ void qemu_remove_machine_init_done_notifier(Notifier *notify)
22
#include "hw/core/split-irq.h"
80
notifier_remove(notify);
23
#include "hw/misc/tz-mpc.h"
24
#include "hw/misc/tz-ppc.h"
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
26
UnimplementedDeviceState mhu[2];
27
UnimplementedDeviceState pwm[3];
28
UnimplementedDeviceState i2s;
29
- UnimplementedDeviceState uart[2];
30
+ PL011State uart[2];
31
UnimplementedDeviceState i2c[2];
32
UnimplementedDeviceState spi;
33
UnimplementedDeviceState scc;
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
35
return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
36
}
81
}
37
82
38
+static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque,
83
+static void handle_machine_dumpdtb(MachineState *ms)
39
+ const char *name, hwaddr size)
40
+{
84
+{
41
+ PL011State *uart = opaque;
85
+ if (!ms->dumpdtb) {
42
+ int i = uart - &mms->uart[0];
86
+ return;
43
+ int irqbase = 7 + i * 6;
87
+ }
44
+ SysBusDevice *s;
88
+ if (!ms->fdt) {
45
+
89
+ /* Silently ignore dumpdtb option if there is nothing to dump */
46
+ sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
90
+ return;
47
+ TYPE_PL011);
91
+ }
48
+ qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
92
+#ifdef CONFIG_FDT
49
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
93
+ qmp_dumpdtb(ms->dumpdtb, &error_fatal);
50
+ s = SYS_BUS_DEVICE(uart);
94
+ exit(0);
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */
95
+#else
52
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */
96
+ error_report("This machine doesn't have an FDT");
53
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */
97
+ exit(1);
54
+ sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */
98
+#endif
55
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */
56
+ sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */
57
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
58
+}
99
+}
59
+
100
+
60
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
101
void qdev_machine_creation_done(void)
61
const char *name, hwaddr size)
62
{
102
{
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
103
cpu_synchronize_all_post_init();
64
MemoryRegion *container = &mms->container;
104
@@ -XXX,XX +XXX,XX @@ void qdev_machine_creation_done(void)
65
105
phase_advance(PHASE_MACHINE_READY);
66
const PPCPortInfo devices[] = {
106
qdev_assert_realized_properly();
67
- { "uart0", make_unimp_dev, &mms->uart[0], 0x1000, 0x1000 },
107
68
- { "uart1", make_unimp_dev, &mms->uart[1], 0x2000, 0x1000 },
108
+ /*
69
+ { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 },
109
+ * If the user used -machine dumpdtb=file.dtb to request that we
70
+ { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 },
110
+ * dump the DTB to a file, do it now, and exit.
71
{ "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
111
+ */
72
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
112
+ handle_machine_dumpdtb(current_machine);
73
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
113
+
74
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
114
/* TODO: once all bus devices are qdevified, this should be done
75
{ "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
115
* when bus is created by qdev.c */
76
{ "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
116
/*
77
{ "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
117
diff --git a/hw/loongarch/virt-fdt-build.c b/hw/loongarch/virt-fdt-build.c
78
- { "uart0", make_unimp_dev, &mms->uart[0], 0x40105000, 0x1000 },
118
index XXXXXXX..XXXXXXX 100644
79
- { "uart1", make_unimp_dev, &mms->uart[1], 0x40106000, 0x1000 },
119
--- a/hw/loongarch/virt-fdt-build.c
80
+ { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 },
120
+++ b/hw/loongarch/virt-fdt-build.c
81
+ { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 },
121
@@ -XXX,XX +XXX,XX @@ void virt_fdt_setup(LoongArchVirtMachineState *lvms)
82
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
122
* Put the FDT into the memory map as a ROM image: this will ensure
83
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
123
* the FDT is copied again upon reset, even if addr points into RAM.
84
{ "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
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,
85
--
240
--
86
2.20.1
241
2.43.0
87
88
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
From: Richard Henderson <richard.henderson@linaro.org>
1
Currently we hardcode at compile time whether the floatx80 default
2
Infinity value has the explicit integer bit set or not (x86 sets it;
3
m68k does not). To be able to compile softfloat once for all targets
4
we'd like to move this setting to runtime.
2
5
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Define a new FloatX80Behaviour enum which is a set of flags that
4
Message-id: 20190215192302.27855-5-richard.henderson@linaro.org
7
define the target's floatx80 handling. Initially we define just one
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
flag, for whether the default Infinity has the Integer bit set or
6
[PMM: fixed a couple of comment typos]
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.
32
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Reviewed-by: Richard Henderson <richard.henderson@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
8
---
38
---
9
target/arm/cpu.h | 10 +++++
39
include/fpu/softfloat-helpers.h | 12 ++++++++++++
10
target/arm/helper.h | 3 ++
40
include/fpu/softfloat-types.h | 13 +++++++++++++
11
target/arm/cpu.c | 1 +
41
include/fpu/softfloat.h | 1 +
12
target/arm/cpu64.c | 2 +
42
fpu/softfloat.c | 7 +++----
13
target/arm/translate-a64.c | 26 +++++++++++
43
target/m68k/cpu.c | 6 ++++++
14
target/arm/translate.c | 10 +++++
44
fpu/softfloat-specialize.c.inc | 10 ++++++++++
15
target/arm/vfp_helper.c | 88 ++++++++++++++++++++++++++++++++++++++
45
6 files changed, 45 insertions(+), 4 deletions(-)
16
7 files changed, 140 insertions(+)
17
46
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
19
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
49
--- a/include/fpu/softfloat-helpers.h
21
+++ b/target/arm/cpu.h
50
+++ b/include/fpu/softfloat-helpers.h
22
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id)
51
@@ -XXX,XX +XXX,XX @@ static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
23
return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0;
52
status->floatx80_rounding_precision = val;
24
}
53
}
25
54
26
+static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
55
+static inline void set_floatx80_behaviour(FloatX80Behaviour b,
56
+ float_status *status)
27
+{
57
+{
28
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0;
58
+ status->floatx80_behaviour = b;
29
+}
59
+}
30
+
60
+
31
static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
61
static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
62
float_status *status)
32
{
63
{
33
return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
64
@@ -XXX,XX +XXX,XX @@ get_floatx80_rounding_precision(const float_status *status)
34
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
65
return status->floatx80_rounding_precision;
35
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
36
}
66
}
37
67
38
+static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
68
+static inline FloatX80Behaviour
69
+get_floatx80_behaviour(const float_status *status)
39
+{
70
+{
40
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
71
+ return status->floatx80_behaviour;
41
+}
72
+}
42
+
73
+
43
static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
74
static inline Float2NaNPropRule
75
get_float_2nan_prop_rule(const float_status *status)
44
{
76
{
45
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
77
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
46
diff --git a/target/arm/helper.h b/target/arm/helper.h
47
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/helper.h
79
--- a/include/fpu/softfloat-types.h
49
+++ b/target/arm/helper.h
80
+++ b/include/fpu/softfloat-types.h
50
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(rintd_exact, TCG_CALL_NO_RWG, f64, f64, ptr)
81
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
51
DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
82
float_ftz_before_rounding = 1,
52
DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
83
} FloatFTZDetection;
53
84
54
+DEF_HELPER_FLAGS_2(vjcvt, TCG_CALL_NO_RWG, i32, f64, env)
85
+/*
55
+DEF_HELPER_FLAGS_2(fjcvtzs, TCG_CALL_NO_RWG, i64, f64, ptr)
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;
56
+
96
+
57
/* neon_helper.c */
97
/*
58
DEF_HELPER_FLAGS_3(neon_qadd_u8, TCG_CALL_NO_RWG, i32, env, i32, i32)
98
* Floating Point Status. Individual architectures may maintain
59
DEF_HELPER_FLAGS_3(neon_qadd_s8, TCG_CALL_NO_RWG, i32, env, i32, i32)
99
* several versions of float_status for different functions. The
60
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
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
61
index XXXXXXX..XXXXXXX 100644
109
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/cpu.c
110
--- a/include/fpu/softfloat.h
63
+++ b/target/arm/cpu.c
111
+++ b/include/fpu/softfloat.h
64
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
112
@@ -XXX,XX +XXX,XX @@ float128 floatx80_to_float128(floatx80, float_status *status);
65
cpu->isar.id_isar5 = t;
113
| The pattern for an extended double-precision inf.
66
114
*----------------------------------------------------------------------------*/
67
t = cpu->isar.id_isar6;
115
extern const floatx80 floatx80_infinity;
68
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
116
+floatx80 floatx80_default_inf(bool zSign, float_status *status);
69
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
117
70
cpu->isar.id_isar6 = t;
118
/*----------------------------------------------------------------------------
71
119
| Software IEC/IEEE extended double-precision operations.
72
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
120
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
73
index XXXXXXX..XXXXXXX 100644
121
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/cpu64.c
122
--- a/fpu/softfloat.c
75
+++ b/target/arm/cpu64.c
123
+++ b/fpu/softfloat.c
76
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
124
@@ -XXX,XX +XXX,XX @@ static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
77
cpu->isar.id_aa64isar0 = t;
125
78
126
case float_class_inf:
79
t = cpu->isar.id_aa64isar1;
127
/* x86 and m68k differ in the setting of the integer bit. */
80
+ t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
128
- frac = floatx80_infinity_low;
81
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
129
+ frac = s->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero ?
82
t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */
130
+ 0 : (1ULL << 63);
83
t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
131
exp = fmt->exp_max;
84
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
132
break;
85
cpu->isar.id_isar5 = u;
133
86
134
@@ -XXX,XX +XXX,XX @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
87
u = cpu->isar.id_isar6;
135
) {
88
+ u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
136
return packFloatx80( zSign, 0x7FFE, ~ roundMask );
89
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
137
}
90
cpu->isar.id_isar6 = u;
138
- return packFloatx80(zSign,
91
139
- floatx80_infinity_high,
92
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
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
93
index XXXXXXX..XXXXXXX 100644
146
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/translate-a64.c
147
--- a/target/m68k/cpu.c
95
+++ b/target/arm/translate-a64.c
148
+++ b/target/m68k/cpu.c
96
@@ -XXX,XX +XXX,XX @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
149
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
97
}
150
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
98
}
151
/* Default NaN: sign bit clear, all frac bits set */
99
152
set_float_default_nan_pattern(0b01111111, &env->fp_status);
100
+static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
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)
101
+{
171
+{
102
+ TCGv_i64 t = read_fp_dreg(s, rn);
172
+ /*
103
+ TCGv_ptr fpstatus = get_fpstatus_ptr(false);
173
+ * Whether the Integer bit is set in the default Infinity is
104
+
174
+ * target dependent.
105
+ gen_helper_fjcvtzs(t, t, fpstatus);
175
+ */
106
+
176
+ bool z = status->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero;
107
+ tcg_temp_free_ptr(fpstatus);
177
+ return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
108
+
109
+ tcg_gen_ext32u_i64(cpu_reg(s, rd), t);
110
+ tcg_gen_extrh_i64_i32(cpu_ZF, t);
111
+ tcg_gen_movi_i32(cpu_CF, 0);
112
+ tcg_gen_movi_i32(cpu_NF, 0);
113
+ tcg_gen_movi_i32(cpu_VF, 0);
114
+
115
+ tcg_temp_free_i64(t);
116
+}
178
+}
117
+
179
+
118
/* Floating point <-> integer conversions
180
#define floatx80_infinity_high 0x7FFF
119
* 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
181
#if defined(TARGET_M68K)
120
* +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
182
#define floatx80_infinity_low UINT64_C(0x0000000000000000)
121
@@ -XXX,XX +XXX,XX @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
122
handle_fmov(s, rd, rn, type, itof);
123
break;
124
125
+ case 0b00111110: /* FJCVTZS */
126
+ if (!dc_isar_feature(aa64_jscvt, s)) {
127
+ goto do_unallocated;
128
+ } else if (fp_access_check(s)) {
129
+ handle_fjcvtzs(s, rd, rn);
130
+ }
131
+ break;
132
+
133
default:
134
do_unallocated:
135
unallocated_encoding(s);
136
diff --git a/target/arm/translate.c b/target/arm/translate.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/target/arm/translate.c
139
+++ b/target/arm/translate.c
140
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
141
rm_is_dp = false;
142
break;
143
144
+ case 0x13: /* vjcvt */
145
+ if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
146
+ return 1;
147
+ }
148
+ rd_is_dp = false;
149
+ break;
150
+
151
default:
152
return 1;
153
}
154
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
155
case 17: /* fsito */
156
gen_vfp_sito(dp, 0);
157
break;
158
+ case 19: /* vjcvt */
159
+ gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
160
+ break;
161
case 20: /* fshto */
162
gen_vfp_shto(dp, 16 - rm, 0);
163
break;
164
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/vfp_helper.c
167
+++ b/target/arm/vfp_helper.c
168
@@ -XXX,XX +XXX,XX @@ int arm_rmode_to_sf(int rmode)
169
}
170
return rmode;
171
}
172
+
173
+/*
174
+ * Implement float64 to int32_t conversion without saturation;
175
+ * the result is supplied modulo 2^32.
176
+ */
177
+uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus)
178
+{
179
+ float_status *status = vstatus;
180
+ uint32_t exp, sign;
181
+ uint64_t frac;
182
+ uint32_t inexact = 1; /* !Z */
183
+
184
+ sign = extract64(value, 63, 1);
185
+ exp = extract64(value, 52, 11);
186
+ frac = extract64(value, 0, 52);
187
+
188
+ if (exp == 0) {
189
+ /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
190
+ inexact = sign;
191
+ if (frac != 0) {
192
+ if (status->flush_inputs_to_zero) {
193
+ float_raise(float_flag_input_denormal, status);
194
+ } else {
195
+ float_raise(float_flag_inexact, status);
196
+ inexact = 1;
197
+ }
198
+ }
199
+ frac = 0;
200
+ } else if (exp == 0x7ff) {
201
+ /* This operation raises Invalid for both NaN and overflow (Inf). */
202
+ float_raise(float_flag_invalid, status);
203
+ frac = 0;
204
+ } else {
205
+ int true_exp = exp - 1023;
206
+ int shift = true_exp - 52;
207
+
208
+ /* Restore implicit bit. */
209
+ frac |= 1ull << 52;
210
+
211
+ /* Shift the fraction into place. */
212
+ if (shift >= 0) {
213
+ /* The number is so large we must shift the fraction left. */
214
+ if (shift >= 64) {
215
+ /* The fraction is shifted out entirely. */
216
+ frac = 0;
217
+ } else {
218
+ frac <<= shift;
219
+ }
220
+ } else if (shift > -64) {
221
+ /* Normal case -- shift right and notice if bits shift out. */
222
+ inexact = (frac << (64 + shift)) != 0;
223
+ frac >>= -shift;
224
+ } else {
225
+ /* The fraction is shifted out entirely. */
226
+ frac = 0;
227
+ }
228
+
229
+ /* Notice overflow or inexact exceptions. */
230
+ if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) {
231
+ /* Overflow, for which this operation raises invalid. */
232
+ float_raise(float_flag_invalid, status);
233
+ inexact = 1;
234
+ } else if (inexact) {
235
+ float_raise(float_flag_inexact, status);
236
+ }
237
+
238
+ /* Honor the sign. */
239
+ if (sign) {
240
+ frac = -frac;
241
+ }
242
+ }
243
+
244
+ /* Pack the result and the env->ZF representation of Z together. */
245
+ return deposit64(frac, 32, 32, inexact);
246
+}
247
+
248
+uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
249
+{
250
+ uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status);
251
+ uint32_t result = pair;
252
+ uint32_t z = (pair >> 32) == 0;
253
+
254
+ /* Store Z, clear NCV, in FPSCR.NZCV. */
255
+ env->vfp.xregs[ARM_VFP_FPSCR]
256
+ = (env->vfp.xregs[ARM_VFP_FPSCR] & ~CPSR_NZCV) | (z * CPSR_Z);
257
+
258
+ return result;
259
+}
260
--
183
--
261
2.20.1
184
2.43.0
262
185
263
186
diff view generated by jsdifflib
1
Coverity points out (CID 1398632, CID 1398650) that we
1
The global const floatx80_infinity is (unlike all the other
2
leak a couple of allocated strings in the error-exit
2
float*_infinity values) target-specific, because whether the explicit
3
code path for setting up the MHUs in the ARMSSE.
3
Integer bit is set or not varies between m68k and i386. We want to
4
Fix this bug by moving the allocate-and-free of each
4
be able to compile softfloat once for multiple targets, so we can't
5
string to be closer to the use, so we do the free before
5
continue to use a single global whose value needs to be different
6
doing the error-exit check.
6
between targets.
7
7
8
Fixes: f8574705f62b38a ("hw/arm/armsse: Add unimplemented-device stubs for MHUs")
8
Replace the direct uses of floatx80_infinity in target/m68k with
9
calls to the new floatx80_default_inf() function.
10
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190215113707.24553-1-peter.maydell@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
12
---
16
---
13
hw/arm/armsse.c | 10 ++++++----
17
target/m68k/softfloat.c | 47 ++++++++++++++---------------------------
14
1 file changed, 6 insertions(+), 4 deletions(-)
18
1 file changed, 16 insertions(+), 31 deletions(-)
15
19
16
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
20
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/armsse.c
22
--- a/target/m68k/softfloat.c
19
+++ b/hw/arm/armsse.c
23
+++ b/target/m68k/softfloat.c
20
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
24
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
21
25
if ((uint64_t) (aSig << 1)) {
22
if (info->has_mhus) {
26
return propagateFloatx80NaN(a, b, status);
23
for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
27
}
24
- char *name = g_strdup_printf("MHU%d", i);
28
- return packFloatx80(aSign, floatx80_infinity.high,
25
- char *port = g_strdup_printf("port[%d]", i + 3);
29
- floatx80_infinity.low);
26
+ char *name;
30
+ return floatx80_default_inf(aSign, status);
27
+ char *port;
31
}
28
32
if (aExp == 0) {
29
+ name = g_strdup_printf("MHU%d", i);
33
if (aSig == 0) {
30
qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
34
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
31
qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
35
float_raise(float_flag_invalid, status);
32
object_property_set_bool(OBJECT(&s->mhu[i]), true,
36
return floatx80_default_nan(status);
33
"realized", &err);
37
}
34
+ g_free(name);
38
- return packFloatx80(0, floatx80_infinity.high, floatx80_infinity.low);
35
if (err) {
39
+ return floatx80_default_inf(0, status);
36
error_propagate(errp, err);
40
}
37
return;
41
38
}
42
if (aExp == 0 && aSig == 0) {
39
+ port = g_strdup_printf("port[%d]", i + 3);
43
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
40
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
44
if (aSign && aExp >= one_exp) {
41
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
45
if (aExp == one_exp && aSig == one_sig) {
42
port, &err);
46
float_raise(float_flag_divbyzero, status);
43
+ g_free(port);
47
- return packFloatx80(aSign, floatx80_infinity.high,
44
if (err) {
48
- floatx80_infinity.low);
45
error_propagate(errp, err);
49
+ return floatx80_default_inf(aSign, status);
46
return;
50
}
47
}
51
float_raise(float_flag_invalid, status);
48
- g_free(name);
52
return floatx80_default_nan(status);
49
- g_free(port);
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);
50
}
60
}
51
}
61
}
52
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) {
53
--
180
--
54
2.20.1
181
2.43.0
55
182
56
183
diff view generated by jsdifflib
1
In commit 4b635cf7a95e501211 we added a QOM property to the ARMSSE
1
The global const floatx80_infinity is (unlike all the other
2
object, but forgot to add it to the documentation comment in the
2
float*_infinity values) target-specific, because whether the explicit
3
header. Correct the omission.
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.
4
7
5
Fixes: 4b635cf7a95e501211 ("hw/arm/armsse: Make SRAM bank size configurable")
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
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@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
8
---
19
---
9
include/hw/arm/armsse.h | 2 ++
20
target/i386/tcg/fpu_helper.c | 7 +++----
10
1 file changed, 2 insertions(+)
21
1 file changed, 3 insertions(+), 4 deletions(-)
11
22
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
23
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armsse.h
25
--- a/target/i386/tcg/fpu_helper.c
15
+++ b/include/hw/arm/armsse.h
26
+++ b/target/i386/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
17
* being the same for both, to avoid having to have separate Property
28
} else if (floatx80_is_infinity(ST0)) {
18
* lists for different variants. This restriction can be relaxed later
29
fpush(env);
19
* if necessary.)
30
ST0 = ST1;
20
+ * + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
31
- ST1 = floatx80_infinity;
21
+ * address of each SRAM bank (and thus the total amount of internal SRAM)
32
+ ST1 = floatx80_default_inf(0, &env->fp_status);
22
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
33
} else {
23
* which are wired to its NVIC lines 32 .. n+32
34
int expdif;
24
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
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 {
25
--
48
--
26
2.20.1
49
2.43.0
27
50
28
51
diff view generated by jsdifflib
1
Wire up the PL031 RTC for the Musca board.
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.)
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.
2
13
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@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
5
---
18
---
6
hw/arm/musca.c | 26 +++++++++++++++++++++++---
19
include/fpu/softfloat.h | 2 +-
7
1 file changed, 23 insertions(+), 3 deletions(-)
20
target/i386/tcg/fpu_helper.c | 20 +++++++++++---------
21
target/m68k/fpu_helper.c | 2 +-
22
3 files changed, 13 insertions(+), 11 deletions(-)
8
23
9
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
24
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
10
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
11
--- a/hw/arm/musca.c
26
--- a/include/fpu/softfloat.h
12
+++ b/hw/arm/musca.c
27
+++ b/include/fpu/softfloat.h
13
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ static inline floatx80 floatx80_chs(floatx80 a)
14
#include "hw/misc/tz-mpc.h"
29
return a;
15
#include "hw/misc/tz-ppc.h"
16
#include "hw/misc/unimp.h"
17
+#include "hw/timer/pl031.h"
18
19
#define MUSCA_NUMIRQ_MAX 96
20
#define MUSCA_PPC_MAX 3
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
UnimplementedDeviceState spi;
23
UnimplementedDeviceState scc;
24
UnimplementedDeviceState timer;
25
- UnimplementedDeviceState rtc;
26
+ PL031State rtc;
27
UnimplementedDeviceState pvt;
28
UnimplementedDeviceState sdio;
29
UnimplementedDeviceState gpio;
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
*/
32
#define SYSCLK_FRQ 40000000
33
34
+static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
35
+{
36
+ /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
37
+ assert(irqno < MUSCA_NUMIRQ_MAX);
38
+
39
+ return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
40
+}
41
+
42
/*
43
* Most of the devices in the Musca board sit behind Peripheral Protection
44
* Controllers. These data structures define the layout of which devices
45
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
46
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
47
}
30
}
48
31
49
+static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
32
-static inline bool floatx80_is_infinity(floatx80 a)
50
+ const char *name, hwaddr size)
33
+static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
51
+{
52
+ PL031State *rtc = opaque;
53
+
54
+ sysbus_init_child_obj(OBJECT(mms), name, rtc, sizeof(mms->rtc), TYPE_PL031);
55
+ object_property_set_bool(OBJECT(rtc), true, "realized", &error_fatal);
56
+ sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39));
57
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
58
+}
59
+
60
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
61
const char *name, hwaddr size)
62
{
34
{
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
35
#if defined(TARGET_M68K)
64
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
36
return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
65
{ "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
37
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
66
{ "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
38
index XXXXXXX..XXXXXXX 100644
67
- { "rtc", make_unimp_dev, &mms->rtc, 0x8000, 0x1000 },
39
--- a/target/i386/tcg/fpu_helper.c
68
+ { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 },
40
+++ b/target/i386/tcg/fpu_helper.c
69
{ "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
41
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
70
{ "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
42
/* Pass this NaN through. */
71
{ "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
43
} else if (floatx80_is_zero(ST1) && !arg0_sign) {
72
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
44
/* Pass this zero through. */
73
{ "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
45
- } else if (((floatx80_is_infinity(ST0) && !floatx80_is_infinity(ST1)) ||
74
{ "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
46
+ } else if (((floatx80_is_infinity(ST0, &env->fp_status) &&
75
{ "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
47
+ !floatx80_is_infinity(ST1, &env->fp_status)) ||
76
- { "rtc", make_unimp_dev, &mms->rtc, 0x4010d000, 0x1000 },
48
arg0_exp - arg1_exp >= 80) &&
77
+ { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 },
49
!arg0_sign) {
78
{ "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
50
/*
79
{ "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
51
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
80
},
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;
81
--
126
--
82
2.20.1
127
2.43.0
83
128
84
129
diff view generated by jsdifflib
1
The Musca board puts its SRAM and flash behind TrustZone
1
In Intel terminology, a floatx80 Infinity with the explicit integer
2
Memory Protection Controllers (MPCs). Each MPC sits between
2
bit clear is a "pseudo-infinity"; for x86 these are not valid
3
the CPU and the RAM/flash, and also has a set of memory mapped
3
infinity values. m68k is looser and does not care whether the
4
control registers. Wire up the MPCs, and the memory behind them.
4
Integer bit is set or clear in an infinity.
5
For the moment we implement the flash as simple ROM, which
5
6
cannot be reprogrammed by the guest.
6
Move this setting to runtime rather than using an ifdef in
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.
7
11
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Message-id: 20250224111524.1101196-6-peter.maydell@linaro.org
16
Message-id: 20250217125055.160887-5-peter.maydell@linaro.org
10
---
17
---
11
hw/arm/musca.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++---
18
include/fpu/softfloat-types.h | 5 +++++
12
1 file changed, 147 insertions(+), 8 deletions(-)
19
include/fpu/softfloat.h | 18 +++++++++++-------
20
target/m68k/cpu.c | 4 +++-
21
fpu/softfloat-specialize.c.inc | 10 ----------
22
4 files changed, 19 insertions(+), 18 deletions(-)
13
23
14
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
24
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/musca.c
26
--- a/include/fpu/softfloat-types.h
17
+++ b/hw/arm/musca.c
27
+++ b/include/fpu/softfloat-types.h
18
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
19
#include "hw/arm/armsse.h"
29
typedef enum __attribute__((__packed__)) {
20
#include "hw/boards.h"
30
/* In the default Infinity value, is the Integer bit 0 ? */
21
#include "hw/core/split-irq.h"
31
floatx80_default_inf_int_bit_is_zero = 1,
22
+#include "hw/misc/tz-mpc.h"
32
+ /*
23
#include "hw/misc/tz-ppc.h"
33
+ * Are Pseudo-infinities (Inf with the Integer bit zero) valid?
24
#include "hw/misc/unimp.h"
34
+ * If so, floatx80_is_infinity() will return true for them.
25
35
+ */
26
#define MUSCA_NUMIRQ_MAX 96
36
+ floatx80_pseudo_inf_valid = 2,
27
#define MUSCA_PPC_MAX 3
37
} FloatX80Behaviour;
28
+#define MUSCA_MPC_MAX 5
38
39
/*
40
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/fpu/softfloat.h
43
+++ b/include/fpu/softfloat.h
44
@@ -XXX,XX +XXX,XX @@ float128 floatx80_to_float128(floatx80, float_status *status);
45
/*----------------------------------------------------------------------------
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)
55
{
56
-#if defined(TARGET_M68K)
57
- return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
58
-#else
59
- return (a.high & 0x7fff) == floatx80_infinity.high &&
60
- a.low == floatx80_infinity.low;
61
-#endif
62
+ /*
63
+ * It's target-specific whether the Integer bit is permitted
64
+ * to be 0 in a valid Infinity value. (x86 says no, m68k says yes).
65
+ */
66
+ bool intbit = a.low >> 63;
29
+
67
+
30
+typedef struct MPCInfo MPCInfo;
68
+ if (!intbit &&
31
69
+ !(status->floatx80_behaviour & floatx80_pseudo_inf_valid)) {
32
typedef enum MuscaType {
70
+ return false;
33
MUSCA_A,
71
+ }
34
@@ -XXX,XX +XXX,XX @@ typedef struct {
72
+ return (a.high & 0x7fff) == 0x7fff && !(a.low << 1);
35
uint32_t init_svtor;
36
int sram_addr_width;
37
int num_irqs;
38
+ const MPCInfo *mpc_info;
39
+ int num_mpcs;
40
} MuscaMachineClass;
41
42
typedef struct {
43
MachineState parent;
44
45
ARMSSE sse;
46
+ /* RAM and flash */
47
+ MemoryRegion ram[MUSCA_MPC_MAX];
48
SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
49
SplitIRQ sec_resp_splitter;
50
TZPPC ppc[MUSCA_PPC_MAX];
51
MemoryRegion container;
52
UnimplementedDeviceState eflash[2];
53
UnimplementedDeviceState qspi;
54
- UnimplementedDeviceState mpc[5];
55
+ TZMPC mpc[MUSCA_MPC_MAX];
56
UnimplementedDeviceState mhu[2];
57
UnimplementedDeviceState pwm[3];
58
UnimplementedDeviceState i2s;
59
@@ -XXX,XX +XXX,XX @@ typedef struct {
60
UnimplementedDeviceState pvt;
61
UnimplementedDeviceState sdio;
62
UnimplementedDeviceState gpio;
63
+ UnimplementedDeviceState cryptoisland;
64
} MuscaMachineState;
65
66
#define TYPE_MUSCA_MACHINE "musca"
67
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
68
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
69
}
73
}
70
74
71
+typedef enum MPCInfoType {
75
static inline bool floatx80_is_neg(floatx80 a)
72
+ MPC_RAM,
76
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
73
+ MPC_ROM,
77
index XXXXXXX..XXXXXXX 100644
74
+ MPC_CRYPTOISLAND,
78
--- a/target/m68k/cpu.c
75
+} MPCInfoType;
79
+++ b/target/m68k/cpu.c
76
+
80
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
77
+struct MPCInfo {
81
/*
78
+ const char *name;
82
* m68k-specific floatx80 behaviour:
79
+ hwaddr addr;
83
* * default Infinity values have a zero Integer bit
80
+ hwaddr size;
84
+ * * input Infinities may have the Integer bit either 0 or 1
81
+ MPCInfoType type;
85
*/
82
+};
86
- set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
83
+
87
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
84
+/* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */
88
+ floatx80_pseudo_inf_valid,
85
+static const MPCInfo a_mpc_info[] = { {
89
&env->fp_status);
86
+ .name = "qspi",
90
87
+ .type = MPC_ROM,
91
nan = floatx80_default_nan(&env->fp_status);
88
+ .addr = 0x00200000,
92
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
89
+ .size = 0x00800000,
93
index XXXXXXX..XXXXXXX 100644
90
+ }, {
94
--- a/fpu/softfloat-specialize.c.inc
91
+ .name = "sram",
95
+++ b/fpu/softfloat-specialize.c.inc
92
+ .type = MPC_RAM,
96
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_default_inf(bool zSign, float_status *status)
93
+ .addr = 0x00000000,
97
return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
94
+ .size = 0x00200000,
95
+ }
96
+};
97
+
98
+static const MPCInfo b1_mpc_info[] = { {
99
+ .name = "qspi",
100
+ .type = MPC_ROM,
101
+ .addr = 0x00000000,
102
+ .size = 0x02000000,
103
+ }, {
104
+ .name = "sram",
105
+ .type = MPC_RAM,
106
+ .addr = 0x0a400000,
107
+ .size = 0x00080000,
108
+ }, {
109
+ .name = "eflash0",
110
+ .type = MPC_ROM,
111
+ .addr = 0x0a000000,
112
+ .size = 0x00200000,
113
+ }, {
114
+ .name = "eflash1",
115
+ .type = MPC_ROM,
116
+ .addr = 0x0a200000,
117
+ .size = 0x00200000,
118
+ }, {
119
+ .name = "cryptoisland",
120
+ .type = MPC_CRYPTOISLAND,
121
+ .addr = 0x0a000000,
122
+ .size = 0x00200000,
123
+ }
124
+};
125
+
126
+static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
127
+ const char *name, hwaddr size)
128
+{
129
+ /*
130
+ * Create an MPC and the RAM or flash behind it.
131
+ * MPC 0: eFlash 0
132
+ * MPC 1: eFlash 1
133
+ * MPC 2: SRAM
134
+ * MPC 3: QSPI flash
135
+ * MPC 4: CryptoIsland
136
+ * For now we implement the flash regions as ROM (ie not programmable)
137
+ * (with their control interface memory regions being unimplemented
138
+ * stubs behind the PPCs).
139
+ * The whole CryptoIsland region behind its MPC is an unimplemented stub.
140
+ */
141
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
142
+ TZMPC *mpc = opaque;
143
+ int i = mpc - &mms->mpc[0];
144
+ MemoryRegion *downstream;
145
+ MemoryRegion *upstream;
146
+ UnimplementedDeviceState *uds;
147
+ char *mpcname;
148
+ const MPCInfo *mpcinfo = mmc->mpc_info;
149
+
150
+ mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name);
151
+
152
+ switch (mpcinfo[i].type) {
153
+ case MPC_ROM:
154
+ downstream = &mms->ram[i];
155
+ memory_region_init_rom(downstream, NULL, mpcinfo[i].name,
156
+ mpcinfo[i].size, &error_fatal);
157
+ break;
158
+ case MPC_RAM:
159
+ downstream = &mms->ram[i];
160
+ memory_region_init_ram(downstream, NULL, mpcinfo[i].name,
161
+ mpcinfo[i].size, &error_fatal);
162
+ break;
163
+ case MPC_CRYPTOISLAND:
164
+ /* We don't implement the CryptoIsland yet */
165
+ uds = &mms->cryptoisland;
166
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
167
+ sizeof(UnimplementedDeviceState),
168
+ TYPE_UNIMPLEMENTED_DEVICE);
169
+ qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name);
170
+ qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size);
171
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
172
+ downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
173
+ break;
174
+ default:
175
+ g_assert_not_reached();
176
+ }
177
+
178
+ sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->mpc[0]),
179
+ TYPE_TZ_MPC);
180
+ object_property_set_link(OBJECT(mpc), OBJECT(downstream),
181
+ "downstream", &error_fatal);
182
+ object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
183
+ /* Map the upstream end of the MPC into system memory */
184
+ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
185
+ memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream);
186
+ /* and connect its interrupt to the SSE-200 */
187
+ qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
188
+ qdev_get_gpio_in_named(DEVICE(&mms->sse),
189
+ "mpcexp_status", i));
190
+
191
+ g_free(mpcname);
192
+ /* Return the register interface MR for our caller to map behind the PPC */
193
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
194
+}
195
+
196
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
197
const char *name, hwaddr size)
198
{
199
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
200
{ "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
201
{ "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
202
{ "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
203
- { "mpc0", make_unimp_dev, &mms->mpc[0], 0x12000, 0x1000 },
204
- { "mpc1", make_unimp_dev, &mms->mpc[1], 0x13000, 0x1000 },
205
+ { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 },
206
+ { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 },
207
};
208
209
memory_region_init(container, OBJECT(mms), "musca-device-container", size);
210
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
211
int i;
212
213
assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
214
+ assert(mmc->num_mpcs <= MUSCA_MPC_MAX);
215
216
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
217
error_report("This board can only be used with CPU %s",
218
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
219
{ "eflash1", make_unimp_dev, &mms->eflash[1],
220
0x52500000, 0x1000 },
221
{ "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
222
- { "mpc0", make_unimp_dev, &mms->mpc[0], 0x52000000, 0x1000 },
223
- { "mpc1", make_unimp_dev, &mms->mpc[1], 0x52100000, 0x1000 },
224
- { "mpc2", make_unimp_dev, &mms->mpc[2], 0x52200000, 0x1000 },
225
- { "mpc3", make_unimp_dev, &mms->mpc[3], 0x52300000, 0x1000 },
226
+ { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 },
227
+ { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 },
228
+ { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 },
229
+ { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 },
230
{ "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
231
{ "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
232
{ }, /* port 9: unused */
233
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
234
{ }, /* port 11: unused */
235
{ }, /* port 12: unused */
236
{ }, /* port 13: unused */
237
- { "mpc4", make_unimp_dev, &mms->mpc[4], 0x52e00000, 0x1000 },
238
+ { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 },
239
},
240
}, {
241
.name = "apb_ppcexp1",
242
@@ -XXX,XX +XXX,XX @@ static void musca_a_class_init(ObjectClass *oc, void *data)
243
mmc->init_svtor = 0x10200000;
244
mmc->sram_addr_width = 15;
245
mmc->num_irqs = 64;
246
+ mmc->mpc_info = a_mpc_info;
247
+ mmc->num_mpcs = ARRAY_SIZE(a_mpc_info);
248
}
98
}
249
99
250
static void musca_b1_class_init(ObjectClass *oc, void *data)
100
-#define floatx80_infinity_high 0x7FFF
251
@@ -XXX,XX +XXX,XX @@ static void musca_b1_class_init(ObjectClass *oc, void *data)
101
-#if defined(TARGET_M68K)
252
mmc->init_svtor = 0x10000000;
102
-#define floatx80_infinity_low UINT64_C(0x0000000000000000)
253
mmc->sram_addr_width = 17;
103
-#else
254
mmc->num_irqs = 96;
104
-#define floatx80_infinity_low UINT64_C(0x8000000000000000)
255
+ mmc->mpc_info = b1_mpc_info;
105
-#endif
256
+ mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info);
106
-
257
}
107
-const floatx80 floatx80_infinity
258
108
- = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low);
259
static const TypeInfo musca_info = {
109
-
110
/*----------------------------------------------------------------------------
111
| Returns 1 if the half-precision floating-point value `a' is a quiet
112
| NaN; otherwise returns 0.
260
--
113
--
261
2.20.1
114
2.43.0
262
115
263
116
diff view generated by jsdifflib
1
The "background region" for a v8M MPU is a default which will be used
1
The definition of which floatx80 encodings are invalid is
2
(if enabled, and if the access is privileged) if the access does
2
target-specific. Currently we handle this with an ifdef, but we
3
not match any specific MPU region. We were incorrectly using it
3
would like to defer this decision to runtime. In preparation, pass a
4
always (by putting the condition at the wrong nesting level). This
4
float_status argument to floatx80_invalid_encoding().
5
meant that we would always return the default background permissions
6
rather than the correct permissions for a specific region, and also
7
that we would not return the right information in response to a
8
TT instruction.
9
5
10
Move the check for the background region to the same place in the
6
We will change the implementation from ifdef to looking at
11
logic as the equivalent v8M MPUCheck() pseudocode puts it.
7
the status argument in the following commit.
12
This in turn means we must adjust the condition we use to detect
13
matches in multiple regions to avoid false-positives.
14
8
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20190214113408.10214-1-peter.maydell@linaro.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20250224111524.1101196-7-peter.maydell@linaro.org
18
---
13
---
19
target/arm/helper.c | 8 +++++---
14
include/fpu/softfloat.h | 2 +-
20
1 file changed, 5 insertions(+), 3 deletions(-)
15
fpu/softfloat.c | 2 +-
16
target/i386/tcg/fpu_helper.c | 24 +++++++++++++-----------
17
3 files changed, 15 insertions(+), 13 deletions(-)
21
18
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
23
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper.c
21
--- a/include/fpu/softfloat.h
25
+++ b/target/arm/helper.c
22
+++ b/include/fpu/softfloat.h
26
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
23
@@ -XXX,XX +XXX,XX @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
27
hit = true;
24
| pseudo-denormals, which must still be correctly handled as inputs even
28
} else if (m_is_ppb_region(env, address)) {
25
| if they are never generated as outputs.
29
hit = true;
26
*----------------------------------------------------------------------------*/
30
- } else if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
27
-static inline bool floatx80_invalid_encoding(floatx80 a)
31
- hit = true;
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);
32
} else {
86
} else {
33
+ if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
87
if (exp0 == 0) {
34
+ hit = true;
88
@@ -XXX,XX +XXX,XX @@ void helper_fyl2xp1(CPUX86State *env)
35
+ }
89
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
36
+
90
float_raise(float_flag_invalid, &env->fp_status);
37
for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
91
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
38
/* region search */
92
- } else if (floatx80_invalid_encoding(ST0) ||
39
/* Note that the base address is bits [31:5] from the register
93
- floatx80_invalid_encoding(ST1)) {
40
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
94
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
41
*is_subpage = true;
95
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
42
}
96
float_raise(float_flag_invalid, &env->fp_status);
43
97
ST1 = floatx80_default_nan(&env->fp_status);
44
- if (hit) {
98
} else if (floatx80_is_any_nan(ST0)) {
45
+ if (matchregion != -1) {
99
@@ -XXX,XX +XXX,XX @@ void helper_fyl2x(CPUX86State *env)
46
/* Multiple regions match -- always a failure (unlike
100
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
47
* PMSAv7 where highest-numbered-region wins)
101
float_raise(float_flag_invalid, &env->fp_status);
48
*/
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)) {
49
--
129
--
50
2.20.1
130
2.43.0
51
131
52
132
diff view generated by jsdifflib
1
The PL011 UART has six interrupt lines:
1
Because floatx80 has an explicit integer bit, this permits some
2
* RX (receive data)
2
odd encodings where the integer bit is not set correctly for the
3
* TX (transmit data)
3
floating point value type. In In Intel terminology the
4
* RT (receive timeout)
4
categories are:
5
* MS (modem status)
5
exp == 0, int = 0, mantissa == 0 : zeroes
6
* E (errors)
6
exp == 0, int = 0, mantissa != 0 : denormals
7
* combined (logical OR of all the above)
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
8
14
9
So far we have only emulated the combined interrupt line;
15
The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
10
add support for the others, so that boards that wire them
16
x87 permits as input also pseudo-denormals.
11
up to different interrupt controller inputs can do so.
17
m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
18
19
Currently we have an ifdef in floatx80_invalid_encoding() to select
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: Richard Henderson <richard.henderson@linaro.org>
29
Reviewed-by: Richard Henderson <richard.henderson@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
15
---
33
---
16
include/hw/char/pl011.h | 2 +-
34
include/fpu/softfloat-types.h | 14 ++++++++
17
hw/char/pl011.c | 46 +++++++++++++++++++++++++++++++++++++++--
35
include/fpu/softfloat.h | 68 ++++++++++++++++++-----------------
18
2 files changed, 45 insertions(+), 3 deletions(-)
36
target/m68k/cpu.c | 28 ++++++++++++++-
37
3 files changed, 77 insertions(+), 33 deletions(-)
19
38
20
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
39
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
21
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/char/pl011.h
41
--- a/include/fpu/softfloat-types.h
23
+++ b/include/hw/char/pl011.h
42
+++ b/include/fpu/softfloat-types.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct PL011State {
43
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
25
int read_count;
44
/*
26
int read_trigger;
45
* Are Pseudo-infinities (Inf with the Integer bit zero) valid?
27
CharBackend chr;
46
* If so, floatx80_is_infinity() will return true for them.
28
- qemu_irq irq;
47
+ * If not, floatx80_invalid_encoding will return false for them,
29
+ qemu_irq irq[6];
48
+ * and using them as inputs to a float op will raise Invalid.
30
const unsigned char *id;
49
*/
31
} PL011State;
50
floatx80_pseudo_inf_valid = 2,
32
51
+ /*
33
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
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
34
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/char/pl011.c
68
--- a/include/fpu/softfloat.h
36
+++ b/hw/char/pl011.c
69
+++ b/include/fpu/softfloat.h
37
@@ -XXX,XX +XXX,XX @@
70
@@ -XXX,XX +XXX,XX @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
38
* This code is licensed under the GPL.
71
39
*/
72
/*----------------------------------------------------------------------------
40
73
| Return whether the given value is an invalid floatx80 encoding.
41
+/*
74
-| Invalid floatx80 encodings arise when the integer bit is not set, but
42
+ * QEMU interface:
75
-| the exponent is not zero. The only times the integer bit is permitted to
43
+ * + sysbus MMIO region 0: device registers
76
-| be zero is in subnormal numbers and the value zero.
44
+ * + sysbus IRQ 0: UARTINTR (combined interrupt line)
77
-| This includes what the Intel software developer's manual calls pseudo-NaNs,
45
+ * + sysbus IRQ 1: UARTRXINTR (receive FIFO interrupt line)
78
-| pseudo-infinities and un-normal numbers. It does not include
46
+ * + sysbus IRQ 2: UARTTXINTR (transmit FIFO interrupt line)
79
-| pseudo-denormals, which must still be correctly handled as inputs even
47
+ * + sysbus IRQ 3: UARTRTINTR (receive timeout interrupt line)
80
-| if they are never generated as outputs.
48
+ * + sysbus IRQ 4: UARTMSINTR (momem status interrupt line)
81
+| Invalid floatx80 encodings may arise when the integer bit is not set
49
+ * + sysbus IRQ 5: UARTEINTR (error interrupt line)
82
+| correctly; this is target-specific. In Intel terminology the
50
+ */
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
+ }
51
+
135
+
52
#include "qemu/osdep.h"
136
+ if ((a.high & 0x7fff) == 0x7fff) {
53
#include "hw/char/pl011.h"
137
+ if (a.low) {
54
#include "hw/sysbus.h"
138
+ return !(s->floatx80_behaviour & floatx80_pseudo_nan_valid);
55
@@ -XXX,XX +XXX,XX @@
139
+ } else {
56
#define PL011_FLAG_TXFF 0x20
140
+ return !(s->floatx80_behaviour & floatx80_pseudo_inf_valid);
57
#define PL011_FLAG_RXFE 0x10
141
+ }
58
142
+ } else {
59
+/* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
143
+ return !(s->floatx80_behaviour & floatx80_unnormal_valid);
60
+#define INT_OE (1 << 10)
61
+#define INT_BE (1 << 9)
62
+#define INT_PE (1 << 8)
63
+#define INT_FE (1 << 7)
64
+#define INT_RT (1 << 6)
65
+#define INT_TX (1 << 5)
66
+#define INT_RX (1 << 4)
67
+#define INT_DSR (1 << 3)
68
+#define INT_DCD (1 << 2)
69
+#define INT_CTS (1 << 1)
70
+#define INT_RI (1 << 0)
71
+#define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
72
+#define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
73
+
74
static const unsigned char pl011_id_arm[8] =
75
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
76
static const unsigned char pl011_id_luminary[8] =
77
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
78
79
+/* Which bits in the interrupt status matter for each outbound IRQ line ? */
80
+static const uint32_t irqmask[] = {
81
+ INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
82
+ INT_RX,
83
+ INT_TX,
84
+ INT_RT,
85
+ INT_MS,
86
+ INT_E,
87
+};
88
+
89
static void pl011_update(PL011State *s)
90
{
91
uint32_t flags;
92
+ int i;
93
94
flags = s->int_level & s->int_enabled;
95
trace_pl011_irq_state(flags != 0);
96
- qemu_set_irq(s->irq, flags != 0);
97
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
98
+ qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
99
+ }
144
+ }
100
}
145
}
101
146
102
static uint64_t pl011_read(void *opaque, hwaddr offset,
147
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
103
@@ -XXX,XX +XXX,XX @@ static void pl011_init(Object *obj)
148
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
104
{
149
index XXXXXXX..XXXXXXX 100644
105
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
150
--- a/target/m68k/cpu.c
106
PL011State *s = PL011(obj);
151
+++ b/target/m68k/cpu.c
107
+ int i;
152
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
108
153
* m68k-specific floatx80 behaviour:
109
memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
154
* * default Infinity values have a zero Integer bit
110
sysbus_init_mmio(sbd, &s->iomem);
155
* * input Infinities may have the Integer bit either 0 or 1
111
- sysbus_init_irq(sbd, &s->irq);
156
+ * * pseudo-denormals supported for input and output
112
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
157
+ * * don't raise Invalid for pseudo-NaN/pseudo-Inf/Unnormal
113
+ sysbus_init_irq(sbd, &s->irq[i]);
158
+ *
114
+ }
159
+ * With m68k, the explicit integer bit can be zero in the case of:
115
160
+ * - zeros (exp == 0, mantissa == 0)
116
s->read_trigger = 1;
161
+ * - denormalized numbers (exp == 0, mantissa != 0)
117
s->ifl = 0x12;
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);
118
--
189
--
119
2.20.1
190
2.43.0
120
191
121
192
diff view generated by jsdifflib
1
The Peripheral Protection Controller's handling of unused ports
1
Currently we compile-time set an 'm68k_denormal' flag in the FloatFmt
2
is that if there is nothing connected to the port's downstream
2
for floatx80 for m68k. This controls our handling of what the Intel
3
then it does not create the sysbus MMIO region for the upstream
3
documentation calls a "pseudo-denormal": a value where the exponent
4
end of the port. This results in odd behaviour when there is
4
field is zero and the explicit integer bit is set.
5
an unused port in the middle of the range: since sysbus MMIO
6
regions are implicitly consecutively allocated, any used ports
7
above the unused ones end up with sysbus MMIO region numbers
8
that don't match the port number.
9
5
10
Avoid this numbering mismatch by creating dummy MMIO regions
6
For x86, the x87 FPU is supposed to accept a pseudo-denormal as
11
for the unused ports. This doesn't change anything for our
7
input, but never generate one on output. For m68k, these values are
12
existing boards, which don't have any gaps in the middle of
8
permitted on input and may be produced on output.
13
the port ranges they use; but it will be needed for the Musca
9
14
board.
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.
15
22
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
26
Message-id: 20250224111524.1101196-9-peter.maydell@linaro.org
27
Message-id: 20250217125055.160887-7-peter.maydell@linaro.org
18
---
28
---
19
include/hw/misc/tz-ppc.h | 8 +++++++-
29
include/fpu/softfloat-types.h | 19 +++++++++++++++++++
20
hw/misc/tz-ppc.c | 32 ++++++++++++++++++++++++++++++++
30
fpu/softfloat.c | 9 ++++-----
21
2 files changed, 39 insertions(+), 1 deletion(-)
31
target/m68k/cpu.c | 3 ++-
32
fpu/softfloat-parts.c.inc | 27 ++++++++++++++++++++++++---
33
4 files changed, 49 insertions(+), 9 deletions(-)
22
34
23
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
35
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
24
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/misc/tz-ppc.h
37
--- a/include/fpu/softfloat-types.h
26
+++ b/include/hw/misc/tz-ppc.h
38
+++ b/include/fpu/softfloat-types.h
27
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
28
*
40
* and using them as inputs to a float op will raise Invalid.
29
* QEMU interface:
41
*/
30
* + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
42
floatx80_unnormal_valid = 8,
31
- * of each of the 16 ports of the PPC
43
+
32
+ * of each of the 16 ports of the PPC. When a port is unused (i.e. no
44
+ /*
33
+ * downstream MemoryRegion is connected to it) at the end of the 0..15
45
+ * If the exponent is 0 and the Integer bit is set, Intel call
34
+ * range then no sysbus MMIO region is created for its upstream. When an
46
+ * this a "pseudo-denormal"; x86 supports that only on input
35
+ * unused port lies in the middle of the range with other used ports at
47
+ * (treating them as denormals by ignoring the Integer bit).
36
+ * higher port numbers, a dummy MMIO region is created to ensure that
48
+ * For m68k, the integer bit is considered validly part of the
37
+ * port N's upstream is always sysbus MMIO region N. Dummy regions should
49
+ * input value when the exponent is 0, and may be 0 or 1,
38
+ * not be mapped, and will assert if any access is made to them.
50
+ * giving extra range. They may also be generated as outputs.
39
* + Property "port[0..15]": MemoryRegion defining the downstream device(s)
51
+ * (The m68k manual actually calls these values part of the
40
* for each of the 16 ports of the PPC
52
+ * normalized number range, not the denormalized number range.)
41
* + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
53
+ *
42
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
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
43
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/tz-ppc.c
67
--- a/fpu/softfloat.c
45
+++ b/hw/misc/tz-ppc.c
68
+++ b/fpu/softfloat.c
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps tz_ppc_ops = {
69
@@ -XXX,XX +XXX,XX @@ typedef struct {
47
.endianness = DEVICE_LITTLE_ENDIAN,
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,
96
},
48
};
97
};
49
98
50
+static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr,
99
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
51
+ unsigned size, bool is_write,
100
index XXXXXXX..XXXXXXX 100644
52
+ MemTxAttrs attrs)
101
--- a/target/m68k/cpu.c
53
+{
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)
120
{
54
+ /*
121
+ /*
55
+ * Board code should never map the upstream end of an unused port,
122
+ * It's target-dependent how to handle the case of exponent 0
56
+ * so we should never try to make a memory access to it.
123
+ * and Integer bit set. Intel calls these "pseudodenormals",
124
+ * and treats them as if the integer bit was 0, and never
125
+ * produces them on output. This is the default behaviour for QEMU.
126
+ * For m68k, the integer bit is considered validly part of the
127
+ * input value when the exponent is 0, and may be 0 or 1,
128
+ * giving extra range. They may also be generated as outputs.
129
+ * (The m68k manual actually calls these values part of the
130
+ * normalized number range, not the denormalized number range,
131
+ * but that distinction is not important for us, because
132
+ * m68k doesn't care about the input_denormal_used status flag.)
133
+ * floatx80_pseudo_denormal_valid selects the m68k behaviour,
134
+ * which changes both how we canonicalize such a value and
135
+ * how we uncanonicalize results.
57
+ */
136
+ */
58
+ g_assert_not_reached();
137
+ bool has_pseudo_denormals = fmt->has_explicit_bit &&
59
+}
138
+ (status->floatx80_behaviour & floatx80_pseudo_denormal_valid);
60
+
139
+
61
+static const MemoryRegionOps tz_ppc_dummy_ops = {
140
if (unlikely(p->exp == 0)) {
62
+ .valid.accepts = tz_ppc_dummy_accepts,
141
if (likely(frac_eqz(p))) {
63
+};
142
p->cls = float_class_zero;
64
+
143
@@ -XXX,XX +XXX,XX @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
65
static void tz_ppc_reset(DeviceState *dev)
144
int shift = frac_normalize(p);
66
{
145
p->cls = float_class_denormal;
67
TZPPC *s = TZ_PPC(dev);
146
p->exp = fmt->frac_shift - fmt->exp_bias
68
@@ -XXX,XX +XXX,XX @@ static void tz_ppc_realize(DeviceState *dev, Error **errp)
147
- - shift + !fmt->m68k_denormal;
69
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
148
+ - shift + !has_pseudo_denormals;
70
TZPPC *s = TZ_PPC(dev);
71
int i;
72
+ int max_port = 0;
73
74
/* We can't create the upstream end of the port until realize,
75
* as we don't know the size of the MR used as the downstream until then.
76
*/
77
for (i = 0; i < TZ_NUM_PORTS; i++) {
78
+ if (s->port[i].downstream) {
79
+ max_port = i;
80
+ }
81
+ }
82
+
83
+ for (i = 0; i <= max_port; i++) {
84
TZPPCPort *port = &s->port[i];
85
char *name;
86
uint64_t size;
87
88
if (!port->downstream) {
89
+ /*
90
+ * Create dummy sysbus MMIO region so the sysbus region
91
+ * numbering doesn't get out of sync with the port numbers.
92
+ * The size is entirely arbitrary.
93
+ */
94
+ name = g_strdup_printf("tz-ppc-dummy-port[%d]", i);
95
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_dummy_ops,
96
+ port, name, 0x10000);
97
+ sysbus_init_mmio(sbd, &port->upstream);
98
+ g_free(name);
99
continue;
100
}
149
}
101
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) {
102
--
178
--
103
2.20.1
179
2.43.0
104
180
105
181
diff view generated by jsdifflib
1
The region 0x40010000 .. 0x4001ffff and its secure-only alias
1
Currently we have a compile-time shortcut where we
2
at 0x50010000... are for per-CPU devices. We implement this by
2
return false from no_signaling_nans() on everything except
3
giving each CPU its own container memory region, where the
3
Xtensa, because we know that's the only target that
4
per-CPU devices live. Unfortunately, the alias region which
4
might ever set status->no_signaling_nans.
5
makes devices mapped at 0x4... addresses also appear at 0x5...
6
is only implemented in the overall "all CPUs" container. The
7
effect of this bug is that the CPU_IDENTITY register block appears
8
only at 0x4001f000, but not at the 0x5001f000 alias where it should
9
also appear. Guests (like very recent Arm Trusted Firmware-M)
10
which try to access it at 0x5001f000 will crash.
11
5
12
Fix this by moving the handling for this alias from the "all CPUs"
6
Remove the ifdef, so we always look at the status flag;
13
container to the per-CPU container. (We leave the aliases for
7
this has no behavioural change, but will be necessary
14
0x1... and 0x3... in the overall container, because there are
8
if we want to build softfloat once for all targets.
15
no per-CPU devices there.)
16
9
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20190215180500.6906-1-peter.maydell@linaro.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
19
Reviewed-by: Alex Bennée <alex.bennee@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
20
---
15
---
21
include/hw/arm/armsse.h | 2 +-
16
fpu/softfloat-specialize.c.inc | 4 ----
22
hw/arm/armsse.c | 26 ++++++++++++++++----------
17
1 file changed, 4 deletions(-)
23
2 files changed, 17 insertions(+), 11 deletions(-)
24
18
25
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
19
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/arm/armsse.h
21
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/include/hw/arm/armsse.h
22
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
23
@@ -XXX,XX +XXX,XX @@ this code that are retained.
30
MemoryRegion cpu_container[SSE_MAX_CPUS];
31
MemoryRegion alias1;
32
MemoryRegion alias2;
33
- MemoryRegion alias3;
34
+ MemoryRegion alias3[SSE_MAX_CPUS];
35
MemoryRegion sram[MAX_SRAM_BANKS];
36
37
qemu_irq *exp_irqs[SSE_MAX_CPUS];
38
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/armsse.c
41
+++ b/hw/arm/armsse.c
42
@@ -XXX,XX +XXX,XX @@ static bool irq_is_common[32] = {
43
/* 30, 31: reserved */
44
};
45
46
-/* Create an alias region of @size bytes starting at @base
47
+/*
48
+ * Create an alias region in @container of @size bytes starting at @base
49
* which mirrors the memory starting at @orig.
50
*/
24
*/
51
-static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
25
static inline bool no_signaling_nans(float_status *status)
52
- hwaddr base, hwaddr size, hwaddr orig)
53
+static void make_alias(ARMSSE *s, MemoryRegion *mr, MemoryRegion *container,
54
+ const char *name, hwaddr base, hwaddr size, hwaddr orig)
55
{
26
{
56
- memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
27
-#if defined(TARGET_XTENSA)
57
+ memory_region_init_alias(mr, NULL, name, container, orig, size);
28
return status->no_signaling_nans;
58
/* The alias is even lower priority than unimplemented_device regions */
29
-#else
59
- memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
30
- return false;
60
+ memory_region_add_subregion_overlap(container, base, mr, -1500);
31
-#endif
61
}
32
}
62
33
63
static void irq_status_forwarder(void *opaque, int n, int level)
34
/* Define how the architecture discriminates signaling NaNs.
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
}
66
67
/* Set up the big aliases first */
68
- make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
69
- make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
70
+ make_alias(s, &s->alias1, &s->container, "alias 1",
71
+ 0x10000000, 0x10000000, 0x00000000);
72
+ make_alias(s, &s->alias2, &s->container,
73
+ "alias 2", 0x30000000, 0x10000000, 0x20000000);
74
/* The 0x50000000..0x5fffffff region is not a pure alias: it has
75
* a few extra devices that only appear there (generally the
76
* control interfaces for the protection controllers).
77
* We implement this by mapping those devices over the top of this
78
- * alias MR at a higher priority.
79
+ * alias MR at a higher priority. Some of the devices in this range
80
+ * are per-CPU, so we must put this alias in the per-cpu containers.
81
*/
82
- make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
83
-
84
+ for (i = 0; i < info->num_cpus; i++) {
85
+ make_alias(s, &s->alias3[i], &s->cpu_container[i],
86
+ "alias 3", 0x50000000, 0x10000000, 0x40000000);
87
+ }
88
89
/* Security controller */
90
object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
91
--
35
--
92
2.20.1
36
2.43.0
93
37
94
38
diff view generated by jsdifflib
1
Create a new include file for the pl011's device struct,
1
Currently we have a compile-time shortcut where we return a hardcode
2
type macros, etc, so that it can be instantiated using
2
value from snan_bit_is_one() on everything except MIPS, because we
3
the "embedded struct" coding style.
3
know that's the only target that needs to change
4
status->no_signaling_nans at runtime.
5
6
Remove the ifdef, so we always look at the status flag. This means
7
we must update the two targets (HPPA and SH4) that were previously
8
hardcoded to return true so that they set the status flag correctly.
9
10
This has no behavioural change, but will be necessary if we want to
11
build softfloat once for all targets.
4
12
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20250224111524.1101196-11-peter.maydell@linaro.org
17
Message-id: 20250217125055.160887-9-peter.maydell@linaro.org
8
---
18
---
9
include/hw/char/pl011.h | 34 ++++++++++++++++++++++++++++++++++
19
target/hppa/fpu_helper.c | 1 +
10
hw/char/pl011.c | 31 ++-----------------------------
20
target/sh4/cpu.c | 1 +
11
2 files changed, 36 insertions(+), 29 deletions(-)
21
fpu/softfloat-specialize.c.inc | 7 -------
22
3 files changed, 2 insertions(+), 7 deletions(-)
12
23
13
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
24
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
14
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/char/pl011.h
26
--- a/target/hppa/fpu_helper.c
16
+++ b/include/hw/char/pl011.h
27
+++ b/target/hppa/fpu_helper.c
17
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
18
#ifndef HW_PL011_H
29
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
19
#define HW_PL011_H
30
/* Default NaN: sign bit clear, msb-1 frac bit set */
20
31
set_float_default_nan_pattern(0b00100000, &env->fp_status);
21
+#include "hw/sysbus.h"
32
+ set_snan_bit_is_one(true, &env->fp_status);
22
+#include "chardev/char-fe.h"
33
/*
23
+
34
* "PA-RISC 2.0 Architecture" says it is IMPDEF whether the flushing
24
+#define TYPE_PL011 "pl011"
35
* enabled by FPSR.D happens before or after rounding. We pick "before"
25
+#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
36
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
26
+
27
+/* This shares the same struct (and cast macro) as the base pl011 device */
28
+#define TYPE_PL011_LUMINARY "pl011_luminary"
29
+
30
+typedef struct PL011State {
31
+ SysBusDevice parent_obj;
32
+
33
+ MemoryRegion iomem;
34
+ uint32_t readbuff;
35
+ uint32_t flags;
36
+ uint32_t lcr;
37
+ uint32_t rsr;
38
+ uint32_t cr;
39
+ uint32_t dmacr;
40
+ uint32_t int_enabled;
41
+ uint32_t int_level;
42
+ uint32_t read_fifo[16];
43
+ uint32_t ilpr;
44
+ uint32_t ibrd;
45
+ uint32_t fbrd;
46
+ uint32_t ifl;
47
+ int read_pos;
48
+ int read_count;
49
+ int read_trigger;
50
+ CharBackend chr;
51
+ qemu_irq irq;
52
+ const unsigned char *id;
53
+} PL011State;
54
+
55
static inline DeviceState *pl011_create(hwaddr addr,
56
qemu_irq irq,
57
Chardev *chr)
58
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
59
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/char/pl011.c
38
--- a/target/sh4/cpu.c
61
+++ b/hw/char/pl011.c
39
+++ b/target/sh4/cpu.c
62
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
41
set_flush_to_zero(1, &env->fp_status);
42
#endif
43
set_default_nan_mode(1, &env->fp_status);
44
+ set_snan_bit_is_one(true, &env->fp_status);
45
/* sign bit clear, set all frac bits other than msb */
46
set_float_default_nan_pattern(0b00111111, &env->fp_status);
47
/*
48
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
49
index XXXXXXX..XXXXXXX 100644
50
--- a/fpu/softfloat-specialize.c.inc
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.
63
*/
57
*/
64
58
static inline bool snan_bit_is_one(float_status *status)
65
#include "qemu/osdep.h"
59
{
66
+#include "hw/char/pl011.h"
60
-#if defined(TARGET_MIPS)
67
#include "hw/sysbus.h"
61
return status->snan_bit_is_one;
68
#include "chardev/char-fe.h"
62
-#elif defined(TARGET_HPPA) || defined(TARGET_SH4)
69
#include "qemu/log.h"
63
- return 1;
70
#include "trace.h"
64
-#else
71
65
- return 0;
72
-#define TYPE_PL011 "pl011"
66
-#endif
73
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
74
-
75
-typedef struct PL011State {
76
- SysBusDevice parent_obj;
77
-
78
- MemoryRegion iomem;
79
- uint32_t readbuff;
80
- uint32_t flags;
81
- uint32_t lcr;
82
- uint32_t rsr;
83
- uint32_t cr;
84
- uint32_t dmacr;
85
- uint32_t int_enabled;
86
- uint32_t int_level;
87
- uint32_t read_fifo[16];
88
- uint32_t ilpr;
89
- uint32_t ibrd;
90
- uint32_t fbrd;
91
- uint32_t ifl;
92
- int read_pos;
93
- int read_count;
94
- int read_trigger;
95
- CharBackend chr;
96
- qemu_irq irq;
97
- const unsigned char *id;
98
-} PL011State;
99
-
100
#define PL011_INT_TX 0x20
101
#define PL011_INT_RX 0x10
102
103
@@ -XXX,XX +XXX,XX @@ static void pl011_luminary_init(Object *obj)
104
}
67
}
105
68
106
static const TypeInfo pl011_luminary_info = {
69
/*----------------------------------------------------------------------------
107
- .name = "pl011_luminary",
108
+ .name = TYPE_PL011_LUMINARY,
109
.parent = TYPE_PL011,
110
.instance_init = pl011_luminary_init,
111
};
112
--
70
--
113
2.20.1
71
2.43.0
114
72
115
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
Create a new include file for the pl031's device struct,
1
Now we have removed all the target-specifics from the softfloat code,
2
type macros, etc, so that it can be instantiated using
2
we can switch to building it once for the whole system rather than
3
the "embedded struct" coding style.
3
once per target.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20250224111524.1101196-13-peter.maydell@linaro.org
9
Message-id: 20250217125055.160887-11-peter.maydell@linaro.org
8
---
10
---
9
include/hw/timer/pl031.h | 44 ++++++++++++++++++++++++++++++++++++++++
11
fpu/softfloat.c | 3 ---
10
hw/timer/pl031.c | 25 +----------------------
12
fpu/meson.build | 2 +-
11
MAINTAINERS | 1 +
13
2 files changed, 1 insertion(+), 4 deletions(-)
12
3 files changed, 46 insertions(+), 24 deletions(-)
13
create mode 100644 include/hw/timer/pl031.h
14
14
15
diff --git a/include/hw/timer/pl031.h b/include/hw/timer/pl031.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
16
new file mode 100644
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/include/hw/timer/pl031.h
20
@@ -XXX,XX +XXX,XX @@
21
+/*
22
+ * ARM AMBA PrimeCell PL031 RTC
23
+ *
24
+ * Copyright (c) 2007 CodeSourcery
25
+ *
26
+ * This file is free software; you can redistribute it and/or modify
27
+ * it under the terms of the GNU General Public License version 2 as
28
+ * published by the Free Software Foundation.
29
+ *
30
+ * Contributions after 2012-01-13 are licensed under the terms of the
31
+ * GNU GPL, version 2 or (at your option) any later version.
32
+ */
33
+
34
+#ifndef HW_TIMER_PL031
35
+#define HW_TIMER_PL031
36
+
37
+#include "hw/sysbus.h"
38
+
39
+#define TYPE_PL031 "pl031"
40
+#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
41
+
42
+typedef struct PL031State {
43
+ SysBusDevice parent_obj;
44
+
45
+ MemoryRegion iomem;
46
+ QEMUTimer *timer;
47
+ qemu_irq irq;
48
+
49
+ /*
50
+ * Needed to preserve the tick_count across migration, even if the
51
+ * absolute value of the rtc_clock is different on the source and
52
+ * destination.
53
+ */
54
+ uint32_t tick_offset_vmstate;
55
+ uint32_t tick_offset;
56
+
57
+ uint32_t mr;
58
+ uint32_t lr;
59
+ uint32_t cr;
60
+ uint32_t im;
61
+ uint32_t is;
62
+} PL031State;
63
+
64
+#endif
65
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
66
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/timer/pl031.c
17
--- a/fpu/softfloat.c
68
+++ b/hw/timer/pl031.c
18
+++ b/fpu/softfloat.c
69
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ this code that are retained.
20
* version 2 or later. See the COPYING file in the top-level directory.
70
*/
21
*/
71
22
23
-/* softfloat (and in particular the code in softfloat-specialize.h) is
24
- * target-dependent and needs the TARGET_* macros.
25
- */
72
#include "qemu/osdep.h"
26
#include "qemu/osdep.h"
73
+#include "hw/timer/pl031.h"
27
#include <math.h>
74
#include "hw/sysbus.h"
28
#include "qemu/bitops.h"
75
#include "qemu/timer.h"
29
diff --git a/fpu/meson.build b/fpu/meson.build
76
#include "sysemu/sysemu.h"
77
@@ -XXX,XX +XXX,XX @@ do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
78
#define RTC_MIS 0x18 /* Masked interrupt status register */
79
#define RTC_ICR 0x1c /* Interrupt clear register */
80
81
-#define TYPE_PL031 "pl031"
82
-#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
83
-
84
-typedef struct PL031State {
85
- SysBusDevice parent_obj;
86
-
87
- MemoryRegion iomem;
88
- QEMUTimer *timer;
89
- qemu_irq irq;
90
-
91
- /* Needed to preserve the tick_count across migration, even if the
92
- * absolute value of the rtc_clock is different on the source and
93
- * destination.
94
- */
95
- uint32_t tick_offset_vmstate;
96
- uint32_t tick_offset;
97
-
98
- uint32_t mr;
99
- uint32_t lr;
100
- uint32_t cr;
101
- uint32_t im;
102
- uint32_t is;
103
-} PL031State;
104
-
105
static const unsigned char pl031_id[] = {
106
0x31, 0x10, 0x14, 0x00, /* Device ID */
107
0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
108
diff --git a/MAINTAINERS b/MAINTAINERS
109
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
110
--- a/MAINTAINERS
31
--- a/fpu/meson.build
111
+++ b/MAINTAINERS
32
+++ b/fpu/meson.build
112
@@ -XXX,XX +XXX,XX @@ F: hw/sd/pl181.c
33
@@ -1 +1 @@
113
F: hw/ssi/pl022.c
34
-specific_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
114
F: include/hw/ssi/pl022.h
35
+common_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
115
F: hw/timer/pl031.c
116
+F: include/hw/timer/pl031.h
117
F: include/hw/arm/primecell.h
118
F: hw/timer/cmsdk-apb-timer.c
119
F: include/hw/timer/cmsdk-apb-timer.h
120
--
36
--
121
2.20.1
37
2.43.0
122
38
123
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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/.
2
4
3
Move all of the fp helpers out of helper.c into a new file.
5
This leaves only the code relating to getting and setting the
4
This is code movement only. Since helper.c has no copyright
6
FPCR/FPSR/FPSCR in the original file. (Some of this also is
5
header, take the one from cpu.h for the new file.
7
TCG-only, but that needs more careful disentangling.)
6
8
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Having two vfp_helper.c files might seem a bit confusing,
8
Message-id: 20190215192302.27855-3-richard.henderson@linaro.org
10
but once we've finished moving all the helper code out
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
of the old file we are going to rename it to vfp_fpscr.c.
12
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
11
---
16
---
12
target/arm/Makefile.objs | 2 +-
17
target/arm/{ => tcg}/vfp_helper.c | 399 +----------
13
target/arm/helper.c | 1062 -------------------------------------
18
target/arm/vfp_helper.c | 1109 -----------------------------
14
target/arm/vfp_helper.c | 1088 ++++++++++++++++++++++++++++++++++++++
19
target/arm/tcg/meson.build | 1 +
15
3 files changed, 1089 insertions(+), 1063 deletions(-)
20
3 files changed, 4 insertions(+), 1505 deletions(-)
16
create mode 100644 target/arm/vfp_helper.c
21
copy target/arm/{ => tcg}/vfp_helper.c (71%)
17
22
18
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
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
19
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/Makefile.objs
28
--- a/target/arm/vfp_helper.c
21
+++ b/target/arm/Makefile.objs
29
+++ b/target/arm/tcg/vfp_helper.c
22
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
30
@@ -XXX,XX +XXX,XX @@
23
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
31
#include "internals.h"
24
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
32
#include "cpu-features.h"
25
obj-y += translate.o op_helper.o helper.o cpu.o
33
#include "fpu/softfloat.h"
26
-obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
34
-#ifdef CONFIG_TCG
27
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o vfp_helper.o
35
#include "qemu/log.h"
28
obj-y += gdbstub.o
36
-#endif
29
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
37
-
30
obj-$(TARGET_AARCH64) += pauth_helper.o
31
diff --git a/target/arm/helper.c b/target/arm/helper.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/helper.c
34
+++ b/target/arm/helper.c
35
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
36
return (a & mask) | (b & ~mask);
37
}
38
39
-/* VFP support. We follow the convention used for VFP instructions:
38
-/* VFP support. We follow the convention used for VFP instructions:
40
- Single precision routines have a "s" suffix, double precision a
39
- Single precision routines have a "s" suffix, double precision a
41
- "d" suffix. */
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
42
-
90
-
43
-/* Convert host exception flags to vfp form. */
91
-/* Convert host exception flags to vfp form. */
44
-static inline int vfp_exceptbits_from_host(int host_bits)
92
-static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
45
-{
93
-{
46
- int target_bits = 0;
94
- uint32_t target_bits = 0;
47
-
95
-
48
- if (host_bits & float_flag_invalid)
96
- if (host_bits & float_flag_invalid) {
49
- target_bits |= 1;
97
- target_bits |= FPSR_IOC;
50
- if (host_bits & float_flag_divbyzero)
98
- }
51
- target_bits |= 2;
99
- if (host_bits & float_flag_divbyzero) {
52
- if (host_bits & float_flag_overflow)
100
- target_bits |= FPSR_DZC;
53
- target_bits |= 4;
101
- }
54
- if (host_bits & (float_flag_underflow | float_flag_output_denormal))
102
- if (host_bits & float_flag_overflow) {
55
- target_bits |= 8;
103
- target_bits |= FPSR_OFC;
56
- if (host_bits & float_flag_inexact)
104
- }
57
- target_bits |= 0x10;
105
- if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
58
- if (host_bits & float_flag_input_denormal)
106
- target_bits |= FPSR_UFC;
59
- target_bits |= 0x80;
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
- }
60
- return target_bits;
124
- return target_bits;
61
-}
125
-}
62
-
126
-
63
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
127
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
64
-{
128
-{
65
- uint32_t i, fpscr;
129
- uint32_t a32_flags = 0, a64_flags = 0;
66
-
130
-
67
- fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
131
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
68
- | (env->vfp.vec_len << 16)
132
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
69
- | (env->vfp.vec_stride << 20);
70
-
71
- i = get_float_exception_flags(&env->vfp.fp_status);
72
- i |= get_float_exception_flags(&env->vfp.standard_fp_status);
73
- /* FZ16 does not generate an input denormal exception. */
133
- /* FZ16 does not generate an input denormal exception. */
74
- i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
134
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
75
- & ~float_flag_input_denormal);
135
- & ~float_flag_input_denormal_flushed);
76
- fpscr |= vfp_exceptbits_from_host(i);
136
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
77
-
137
- & ~float_flag_input_denormal_flushed);
78
- i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
138
-
79
- fpscr |= i ? FPCR_QC : 0;
139
- a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
80
-
140
- a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
81
- return fpscr;
141
- & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
82
-}
83
-
84
-uint32_t vfp_get_fpscr(CPUARMState *env)
85
-{
86
- return HELPER(vfp_get_fpscr)(env);
87
-}
88
-
89
-/* Convert vfp exception flags to target form. */
90
-static inline int vfp_exceptbits_to_host(int target_bits)
91
-{
92
- int host_bits = 0;
93
-
94
- if (target_bits & 1)
95
- host_bits |= float_flag_invalid;
96
- if (target_bits & 2)
97
- host_bits |= float_flag_divbyzero;
98
- if (target_bits & 4)
99
- host_bits |= float_flag_overflow;
100
- if (target_bits & 8)
101
- host_bits |= float_flag_underflow;
102
- if (target_bits & 0x10)
103
- host_bits |= float_flag_inexact;
104
- if (target_bits & 0x80)
105
- host_bits |= float_flag_input_denormal;
106
- return host_bits;
107
-}
108
-
109
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
110
-{
111
- int i;
112
- uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
113
-
114
- /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
115
- if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
116
- val &= ~FPCR_FZ16;
117
- }
118
-
119
- /*
142
- /*
120
- * We don't implement trapped exception handling, so the
143
- * We do not merge in flags from FPST_AH or FPST_AH_F16, because
121
- * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
144
- * they are used for insns that must not set the cumulative exception bits.
122
- *
145
- */
123
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
124
- * (which are stored in fp_status), and the other RES0 bits
125
- * in between, then we clear all of the low 16 bits.
126
- */
127
- env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
128
- env->vfp.vec_len = (val >> 16) & 7;
129
- env->vfp.vec_stride = (val >> 20) & 3;
130
-
146
-
131
- /*
147
- /*
132
- * The bit we set within fpscr_q is arbitrary; the register as a
148
- * Flushing an input denormal *only* because FPCR.FIZ == 1 does
133
- * whole being zero/non-zero is what counts.
149
- * not set FPSR.IDC; if FPCR.FZ is also set then this takes
134
- */
150
- * precedence and IDC is set (see the FPUnpackBase pseudocode).
135
- env->vfp.qc[0] = val & FPCR_QC;
151
- * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
136
- env->vfp.qc[1] = 0;
152
- * We only do this for the a64 flags because FIZ has no effect
137
- env->vfp.qc[2] = 0;
153
- * on AArch32 even if it is set.
138
- env->vfp.qc[3] = 0;
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;
139
-
193
-
140
- changed ^= val;
194
- changed ^= val;
195
- changed &= mask;
141
- if (changed & (3 << 22)) {
196
- if (changed & (3 << 22)) {
142
- i = (val >> 22) & 3;
197
- int i = (val >> 22) & 3;
143
- switch (i) {
198
- switch (i) {
144
- case FPROUNDING_TIEEVEN:
199
- case FPROUNDING_TIEEVEN:
145
- i = float_round_nearest_even;
200
- i = float_round_nearest_even;
146
- break;
201
- break;
147
- case FPROUNDING_POSINF:
202
- case FPROUNDING_POSINF:
...
...
152
- break;
207
- break;
153
- case FPROUNDING_ZERO:
208
- case FPROUNDING_ZERO:
154
- i = float_round_to_zero;
209
- i = float_round_to_zero;
155
- break;
210
- break;
156
- }
211
- }
157
- set_float_rounding_mode(i, &env->vfp.fp_status);
212
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
158
- set_float_rounding_mode(i, &env->vfp.fp_status_f16);
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]);
159
- }
216
- }
160
- if (changed & FPCR_FZ16) {
217
- if (changed & FPCR_FZ16) {
161
- bool ftz_enabled = val & FPCR_FZ16;
218
- bool ftz_enabled = val & FPCR_FZ16;
162
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
219
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
163
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_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]);
164
- }
227
- }
165
- if (changed & FPCR_FZ) {
228
- if (changed & FPCR_FZ) {
166
- bool ftz_enabled = val & FPCR_FZ;
229
- bool ftz_enabled = val & FPCR_FZ;
167
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
230
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
168
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
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]);
169
- }
243
- }
170
- if (changed & FPCR_DN) {
244
- if (changed & FPCR_DN) {
171
- bool dnan_enabled = val & FPCR_DN;
245
- bool dnan_enabled = val & FPCR_DN;
172
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
246
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
173
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
247
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
174
- }
248
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
175
-
249
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
176
- /* The exception flags are ORed together when we read fpscr so we
250
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
177
- * only need to preserve the current state in one of our
251
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
178
- * float_status values.
252
- }
179
- */
253
- if (changed & FPCR_AH) {
180
- i = vfp_exceptbits_to_host(val);
254
- bool ah_enabled = val & FPCR_AH;
181
- set_float_exception_flags(i, &env->vfp.fp_status);
255
-
182
- set_float_exception_flags(0, &env->vfp.fp_status_f16);
256
- if (ah_enabled) {
183
- set_float_exception_flags(0, &env->vfp.standard_fp_status);
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);
184
-}
427
-}
185
-
428
-
186
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
429
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
187
-{
430
-{
188
- HELPER(vfp_set_fpscr)(env, val);
431
- HELPER(vfp_set_fpscr)(env, val);
189
-}
432
-}
190
-
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
-
191
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
469
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
192
-
470
-
193
-#define VFP_BINOP(name) \
471
-#define VFP_BINOP(name) \
194
-float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
472
-dh_ctype_f16 VFP_HELPER(name, h)(dh_ctype_f16 a, dh_ctype_f16 b, float_status *fpst) \
195
-{ \
473
-{ \
196
- float_status *fpst = fpstp; \
474
- return float16_ ## name(a, b, fpst); \
475
-} \
476
-float32 VFP_HELPER(name, s)(float32 a, float32 b, float_status *fpst) \
477
-{ \
197
- return float32_ ## name(a, b, fpst); \
478
- return float32_ ## name(a, b, fpst); \
198
-} \
479
-} \
199
-float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
480
-float64 VFP_HELPER(name, d)(float64 a, float64 b, float_status *fpst) \
200
-{ \
481
-{ \
201
- float_status *fpst = fpstp; \
202
- return float64_ ## name(a, b, fpst); \
482
- return float64_ ## name(a, b, fpst); \
203
-}
483
-}
204
-VFP_BINOP(add)
484
-VFP_BINOP(add)
205
-VFP_BINOP(sub)
485
-VFP_BINOP(sub)
206
-VFP_BINOP(mul)
486
-VFP_BINOP(mul)
...
...
209
-VFP_BINOP(max)
489
-VFP_BINOP(max)
210
-VFP_BINOP(minnum)
490
-VFP_BINOP(minnum)
211
-VFP_BINOP(maxnum)
491
-VFP_BINOP(maxnum)
212
-#undef VFP_BINOP
492
-#undef VFP_BINOP
213
-
493
-
214
-float32 VFP_HELPER(neg, s)(float32 a)
494
-dh_ctype_f16 VFP_HELPER(sqrt, h)(dh_ctype_f16 a, float_status *fpst)
215
-{
495
-{
216
- return float32_chs(a);
496
- return float16_sqrt(a, fpst);
217
-}
497
-}
218
-
498
-
219
-float64 VFP_HELPER(neg, d)(float64 a)
499
-float32 VFP_HELPER(sqrt, s)(float32 a, float_status *fpst)
220
-{
500
-{
221
- return float64_chs(a);
501
- return float32_sqrt(a, fpst);
222
-}
502
-}
223
-
503
-
224
-float32 VFP_HELPER(abs, s)(float32 a)
504
-float64 VFP_HELPER(sqrt, d)(float64 a, float_status *fpst)
225
-{
505
-{
226
- return float32_abs(a);
506
- return float64_sqrt(a, fpst);
227
-}
507
-}
228
-
508
-
229
-float64 VFP_HELPER(abs, d)(float64 a)
509
-static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp)
230
-{
231
- return float64_abs(a);
232
-}
233
-
234
-float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
235
-{
236
- return float32_sqrt(a, &env->vfp.fp_status);
237
-}
238
-
239
-float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
240
-{
241
- return float64_sqrt(a, &env->vfp.fp_status);
242
-}
243
-
244
-static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
245
-{
510
-{
246
- uint32_t flags;
511
- uint32_t flags;
247
- switch (cmp) {
512
- switch (cmp) {
248
- case float_relation_equal:
513
- case float_relation_equal:
249
- flags = 0x6;
514
- flags = 0x6;
...
...
258
- flags = 0x3;
523
- flags = 0x3;
259
- break;
524
- break;
260
- default:
525
- default:
261
- g_assert_not_reached();
526
- g_assert_not_reached();
262
- }
527
- }
263
- env->vfp.xregs[ARM_VFP_FPSCR] =
528
- env->vfp.fpsr = deposit64(env->vfp.fpsr, 28, 4, flags); /* NZCV */
264
- deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
265
-}
529
-}
266
-
530
-
267
-/* XXX: check quiet/signaling case */
531
-/* XXX: check quiet/signaling case */
268
-#define DO_VFP_cmp(p, type) \
532
-#define DO_VFP_cmp(P, FLOATTYPE, ARGTYPE, FPST) \
269
-void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
533
-void VFP_HELPER(cmp, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
270
-{ \
534
-{ \
271
- softfloat_to_vfp_compare(env, \
535
- softfloat_to_vfp_compare(env, \
272
- type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
536
- FLOATTYPE ## _compare_quiet(a, b, &env->vfp.fp_status[FPST])); \
273
-} \
537
-} \
274
-void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
538
-void VFP_HELPER(cmpe, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
275
-{ \
539
-{ \
276
- softfloat_to_vfp_compare(env, \
540
- softfloat_to_vfp_compare(env, \
277
- type ## _compare(a, b, &env->vfp.fp_status)); \
541
- FLOATTYPE ## _compare(a, b, &env->vfp.fp_status[FPST])); \
278
-}
542
-}
279
-DO_VFP_cmp(s, float32)
543
-DO_VFP_cmp(h, float16, dh_ctype_f16, FPST_A32_F16)
280
-DO_VFP_cmp(d, float64)
544
-DO_VFP_cmp(s, float32, float32, FPST_A32)
545
-DO_VFP_cmp(d, float64, float64, FPST_A32)
281
-#undef DO_VFP_cmp
546
-#undef DO_VFP_cmp
282
-
547
-
283
-/* Integer to float and float to integer conversions */
548
-/* Integer to float and float to integer conversions */
284
-
549
-
285
-#define CONV_ITOF(name, ftype, fsz, sign) \
550
-#define CONV_ITOF(name, ftype, fsz, sign) \
286
-ftype HELPER(name)(uint32_t x, void *fpstp) \
551
-ftype HELPER(name)(uint32_t x, float_status *fpst) \
287
-{ \
552
-{ \
288
- float_status *fpst = fpstp; \
289
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
553
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
290
-}
554
-}
291
-
555
-
292
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
556
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
293
-sign##int32_t HELPER(name)(ftype x, void *fpstp) \
557
-sign##int32_t HELPER(name)(ftype x, float_status *fpst) \
294
-{ \
558
-{ \
295
- float_status *fpst = fpstp; \
296
- if (float##fsz##_is_any_nan(x)) { \
559
- if (float##fsz##_is_any_nan(x)) { \
297
- float_raise(float_flag_invalid, fpst); \
560
- float_raise(float_flag_invalid, fpst); \
298
- return 0; \
561
- return 0; \
299
- } \
562
- } \
300
- return float##fsz##_to_##sign##int32##round(x, fpst); \
563
- return float##fsz##_to_##sign##int32##round(x, fpst); \
...
...
315
-#undef CONV_ITOF
578
-#undef CONV_ITOF
316
-#undef CONV_FTOI
579
-#undef CONV_FTOI
317
-#undef FLOAT_CONVS
580
-#undef FLOAT_CONVS
318
-
581
-
319
-/* floating point conversion */
582
-/* floating point conversion */
320
-float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
583
-float64 VFP_HELPER(fcvtd, s)(float32 x, float_status *status)
321
-{
584
-{
322
- return float32_to_float64(x, &env->vfp.fp_status);
585
- return float32_to_float64(x, status);
323
-}
586
-}
324
-
587
-
325
-float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
588
-float32 VFP_HELPER(fcvts, d)(float64 x, float_status *status)
326
-{
589
-{
327
- return float64_to_float32(x, &env->vfp.fp_status);
590
- return float64_to_float32(x, status);
328
-}
591
-}
329
-
592
-
330
-/* VFP3 fixed point conversion. */
593
-uint32_t HELPER(bfcvt)(float32 x, float_status *status)
331
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
594
-{
332
-float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
595
- return float32_to_bfloat16(x, status);
333
- void *fpstp) \
596
-}
334
-{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
597
-
335
-
598
-uint32_t HELPER(bfcvt_pair)(uint64_t pair, float_status *status)
336
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
599
-{
337
-uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
600
- bfloat16 lo = float32_to_bfloat16(extract64(pair, 0, 32), status);
338
- void *fpst) \
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) \
339
-{ \
633
-{ \
340
- if (unlikely(float##fsz##_is_any_nan(x))) { \
634
- if (unlikely(float##fsz##_is_any_nan(x))) { \
341
- float_raise(float_flag_invalid, fpst); \
635
- float_raise(float_flag_invalid, fpst); \
342
- return 0; \
636
- return 0; \
343
- } \
637
- } \
344
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
638
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
345
-}
639
-}
346
-
640
-
347
-#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
641
-#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
348
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
642
-VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
349
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, 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, \
350
- float_round_to_zero, _round_to_zero) \
645
- float_round_to_zero, _round_to_zero) \
351
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
646
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
352
- get_float_rounding_mode(fpst), )
647
- get_float_rounding_mode(fpst), )
353
-
648
-
354
-#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
649
-#define VFP_CONV_FIX_A64(name, p, fsz, ftype, isz, itype) \
355
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
650
-VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
356
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
651
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
357
- get_float_rounding_mode(fpst), )
652
- get_float_rounding_mode(fpst), )
358
-
653
-
359
-VFP_CONV_FIX(sh, d, 64, 64, int16)
654
-VFP_CONV_FIX(sh, d, 64, float64, 64, int16)
360
-VFP_CONV_FIX(sl, d, 64, 64, int32)
655
-VFP_CONV_FIX(sl, d, 64, float64, 64, int32)
361
-VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
656
-VFP_CONV_FIX_A64(sq, d, 64, float64, 64, int64)
362
-VFP_CONV_FIX(uh, d, 64, 64, uint16)
657
-VFP_CONV_FIX(uh, d, 64, float64, 64, uint16)
363
-VFP_CONV_FIX(ul, d, 64, 64, uint32)
658
-VFP_CONV_FIX(ul, d, 64, float64, 64, uint32)
364
-VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
659
-VFP_CONV_FIX_A64(uq, d, 64, float64, 64, uint64)
365
-VFP_CONV_FIX(sh, s, 32, 32, int16)
660
-VFP_CONV_FIX(sh, s, 32, float32, 32, int16)
366
-VFP_CONV_FIX(sl, s, 32, 32, int32)
661
-VFP_CONV_FIX(sl, s, 32, float32, 32, int32)
367
-VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
662
-VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64)
368
-VFP_CONV_FIX(uh, s, 32, 32, uint16)
663
-VFP_CONV_FIX(uh, s, 32, float32, 32, uint16)
369
-VFP_CONV_FIX(ul, s, 32, 32, uint32)
664
-VFP_CONV_FIX(ul, s, 32, float32, 32, uint32)
370
-VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
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)
371
-
676
-
372
-#undef VFP_CONV_FIX
677
-#undef VFP_CONV_FIX
373
-#undef VFP_CONV_FIX_FLOAT
678
-#undef VFP_CONV_FIX_FLOAT
374
-#undef VFP_CONV_FLOAT_FIX_ROUND
679
-#undef VFP_CONV_FLOAT_FIX_ROUND
375
-#undef VFP_CONV_FIX_A64
680
-#undef VFP_CONV_FIX_A64
376
-
681
-
377
-uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
378
-{
379
- return int32_to_float16_scalbn(x, -shift, fpst);
380
-}
381
-
382
-uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
383
-{
384
- return uint32_to_float16_scalbn(x, -shift, fpst);
385
-}
386
-
387
-uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
388
-{
389
- return int64_to_float16_scalbn(x, -shift, fpst);
390
-}
391
-
392
-uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
393
-{
394
- return uint64_to_float16_scalbn(x, -shift, fpst);
395
-}
396
-
397
-uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
398
-{
399
- if (unlikely(float16_is_any_nan(x))) {
400
- float_raise(float_flag_invalid, fpst);
401
- return 0;
402
- }
403
- return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
404
- shift, fpst);
405
-}
406
-
407
-uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
408
-{
409
- if (unlikely(float16_is_any_nan(x))) {
410
- float_raise(float_flag_invalid, fpst);
411
- return 0;
412
- }
413
- return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
414
- shift, fpst);
415
-}
416
-
417
-uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
418
-{
419
- if (unlikely(float16_is_any_nan(x))) {
420
- float_raise(float_flag_invalid, fpst);
421
- return 0;
422
- }
423
- return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
424
- shift, fpst);
425
-}
426
-
427
-uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
428
-{
429
- if (unlikely(float16_is_any_nan(x))) {
430
- float_raise(float_flag_invalid, fpst);
431
- return 0;
432
- }
433
- return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
434
- shift, fpst);
435
-}
436
-
437
-uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
438
-{
439
- if (unlikely(float16_is_any_nan(x))) {
440
- float_raise(float_flag_invalid, fpst);
441
- return 0;
442
- }
443
- return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
444
- shift, fpst);
445
-}
446
-
447
-uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
448
-{
449
- if (unlikely(float16_is_any_nan(x))) {
450
- float_raise(float_flag_invalid, fpst);
451
- return 0;
452
- }
453
- return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
454
- shift, fpst);
455
-}
456
-
457
-/* Set the current fp rounding mode and return the old one.
682
-/* Set the current fp rounding mode and return the old one.
458
- * The argument is a softfloat float_round_ value.
683
- * The argument is a softfloat float_round_ value.
459
- */
684
- */
460
-uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
685
-uint32_t HELPER(set_rmode)(uint32_t rmode, float_status *fp_status)
461
-{
686
-{
462
- float_status *fp_status = fpstp;
463
-
464
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
687
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
465
- set_float_rounding_mode(rmode, fp_status);
688
- set_float_rounding_mode(rmode, fp_status);
466
-
689
-
467
- return prev_rmode;
690
- return prev_rmode;
468
-}
691
-}
469
-
692
-
470
-/* Set the current fp rounding mode in the standard fp status and return
471
- * the old one. This is for NEON instructions that need to change the
472
- * rounding mode but wish to use the standard FPSCR values for everything
473
- * else. Always set the rounding mode back to the correct value after
474
- * modifying it.
475
- * The argument is a softfloat float_round_ value.
476
- */
477
-uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
478
-{
479
- float_status *fp_status = &env->vfp.standard_fp_status;
480
-
481
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
482
- set_float_rounding_mode(rmode, fp_status);
483
-
484
- return prev_rmode;
485
-}
486
-
487
-/* Half precision conversions. */
693
-/* Half precision conversions. */
488
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
694
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, float_status *fpst,
695
- uint32_t ahp_mode)
489
-{
696
-{
490
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
697
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
491
- * it would affect flushing input denormals.
698
- * it would affect flushing input denormals.
492
- */
699
- */
493
- float_status *fpst = fpstp;
700
- bool save = get_flush_inputs_to_zero(fpst);
494
- flag save = get_flush_inputs_to_zero(fpst);
495
- set_flush_inputs_to_zero(false, fpst);
701
- set_flush_inputs_to_zero(false, fpst);
496
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
702
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
497
- set_flush_inputs_to_zero(save, fpst);
703
- set_flush_inputs_to_zero(save, fpst);
498
- return r;
704
- return r;
499
-}
705
-}
500
-
706
-
501
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
707
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, float_status *fpst,
708
- uint32_t ahp_mode)
502
-{
709
-{
503
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
710
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
504
- * it would affect flushing output denormals.
711
- * it would affect flushing output denormals.
505
- */
712
- */
506
- float_status *fpst = fpstp;
713
- bool save = get_flush_to_zero(fpst);
507
- flag save = get_flush_to_zero(fpst);
508
- set_flush_to_zero(false, fpst);
714
- set_flush_to_zero(false, fpst);
509
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
715
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
510
- set_flush_to_zero(save, fpst);
716
- set_flush_to_zero(save, fpst);
511
- return r;
717
- return r;
512
-}
718
-}
513
-
719
-
514
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
720
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, float_status *fpst,
721
- uint32_t ahp_mode)
515
-{
722
-{
516
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
723
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
517
- * it would affect flushing input denormals.
724
- * it would affect flushing input denormals.
518
- */
725
- */
519
- float_status *fpst = fpstp;
726
- bool save = get_flush_inputs_to_zero(fpst);
520
- flag save = get_flush_inputs_to_zero(fpst);
521
- set_flush_inputs_to_zero(false, fpst);
727
- set_flush_inputs_to_zero(false, fpst);
522
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
728
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
523
- set_flush_inputs_to_zero(save, fpst);
729
- set_flush_inputs_to_zero(save, fpst);
524
- return r;
730
- return r;
525
-}
731
-}
526
-
732
-
527
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
733
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, float_status *fpst,
734
- uint32_t ahp_mode)
528
-{
735
-{
529
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
736
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
530
- * it would affect flushing output denormals.
737
- * it would affect flushing output denormals.
531
- */
738
- */
532
- float_status *fpst = fpstp;
739
- bool save = get_flush_to_zero(fpst);
533
- flag save = get_flush_to_zero(fpst);
534
- set_flush_to_zero(false, fpst);
740
- set_flush_to_zero(false, fpst);
535
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
741
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
536
- set_flush_to_zero(save, fpst);
742
- set_flush_to_zero(save, fpst);
537
- return r;
743
- return r;
538
-}
539
-
540
-#define float32_two make_float32(0x40000000)
541
-#define float32_three make_float32(0x40400000)
542
-#define float32_one_point_five make_float32(0x3fc00000)
543
-
544
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
545
-{
546
- float_status *s = &env->vfp.standard_fp_status;
547
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
548
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
549
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
550
- float_raise(float_flag_input_denormal, s);
551
- }
552
- return float32_two;
553
- }
554
- return float32_sub(float32_two, float32_mul(a, b, s), s);
555
-}
556
-
557
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
558
-{
559
- float_status *s = &env->vfp.standard_fp_status;
560
- float32 product;
561
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
562
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
563
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
564
- float_raise(float_flag_input_denormal, s);
565
- }
566
- return float32_one_point_five;
567
- }
568
- product = float32_mul(a, b, s);
569
- return float32_div(float32_sub(float32_three, product, s), float32_two, s);
570
-}
744
-}
571
-
745
-
572
-/* NEON helpers. */
746
-/* NEON helpers. */
573
-
747
-
574
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
748
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
...
...
598
- assert(256 <= input && input < 512);
772
- assert(256 <= input && input < 512);
599
- a = (input * 2) + 1;
773
- a = (input * 2) + 1;
600
- b = (1 << 19) / a;
774
- b = (1 << 19) / a;
601
- r = (b + 1) >> 1;
775
- r = (b + 1) >> 1;
602
- assert(256 <= r && r < 512);
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);
603
- return r;
804
- return r;
604
-}
805
-}
605
-
806
-
606
-/*
807
-/*
607
- * Common wrapper to call recip_estimate
808
- * Common wrapper to call recip_estimate
...
...
610
- * bit) where the binary point is nominally at bit 52. Returns a
811
- * bit) where the binary point is nominally at bit 52. Returns a
611
- * float64 which can then be rounded to the appropriate size by the
812
- * float64 which can then be rounded to the appropriate size by the
612
- * callee.
813
- * callee.
613
- */
814
- */
614
-
815
-
615
-static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
816
-static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac,
817
- bool increasedprecision)
616
-{
818
-{
617
- uint32_t scaled, estimate;
819
- uint32_t scaled, estimate;
618
- uint64_t result_frac;
820
- uint64_t result_frac;
619
- int result_exp;
821
- int result_exp;
620
-
822
-
...
...
626
- } else {
828
- } else {
627
- frac <<= 1;
829
- frac <<= 1;
628
- }
830
- }
629
- }
831
- }
630
-
832
-
631
- /* scaled = UInt('1':fraction<51:44>) */
833
- if (increasedprecision) {
632
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
834
- /* scaled = UInt('1':fraction<51:41>) */
633
- estimate = recip_estimate(scaled);
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
- }
634
-
842
-
635
- result_exp = exp_off - *exp;
843
- result_exp = exp_off - *exp;
636
- result_frac = deposit64(0, 44, 8, estimate);
844
- if (increasedprecision) {
845
- result_frac = deposit64(0, 40, 12, estimate);
846
- } else {
847
- result_frac = deposit64(0, 44, 8, estimate);
848
- }
637
- if (result_exp == 0) {
849
- if (result_exp == 0) {
638
- result_frac = deposit64(result_frac >> 1, 51, 1, 1);
850
- result_frac = deposit64(result_frac >> 1, 51, 1, 1);
639
- } else if (result_exp == -1) {
851
- } else if (result_exp == -1) {
640
- result_frac = deposit64(result_frac >> 2, 50, 2, 1);
852
- result_frac = deposit64(result_frac >> 2, 50, 2, 1);
641
- result_exp = 0;
853
- result_exp = 0;
...
...
655
- return !sign_bit;
867
- return !sign_bit;
656
- case float_round_down: /* Round to -Inf */
868
- case float_round_down: /* Round to -Inf */
657
- return sign_bit;
869
- return sign_bit;
658
- case float_round_to_zero: /* Round to Zero */
870
- case float_round_to_zero: /* Round to Zero */
659
- return false;
871
- return false;
660
- }
872
- default:
661
-
873
- g_assert_not_reached();
662
- g_assert_not_reached();
874
- }
663
-}
875
-}
664
-
876
-
665
-uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
877
-uint32_t HELPER(recpe_f16)(uint32_t input, float_status *fpst)
666
-{
878
-{
667
- float_status *fpst = fpstp;
668
- float16 f16 = float16_squash_input_denormal(input, fpst);
879
- float16 f16 = float16_squash_input_denormal(input, fpst);
669
- uint32_t f16_val = float16_val(f16);
880
- uint32_t f16_val = float16_val(f16);
670
- uint32_t f16_sign = float16_is_neg(f16);
881
- uint32_t f16_sign = float16_is_neg(f16);
671
- int f16_exp = extract32(f16_val, 10, 5);
882
- int f16_exp = extract32(f16_val, 10, 5);
672
- uint32_t f16_frac = extract32(f16_val, 0, 10);
883
- uint32_t f16_frac = extract32(f16_val, 0, 10);
673
- uint64_t f64_frac;
884
- uint64_t f64_frac;
674
-
885
-
675
- if (float16_is_any_nan(f16)) {
886
- if (float16_is_any_nan(f16)) {
676
- float16 nan = f16;
887
- float16 nan = f16;
677
- if (float16_is_signaling_nan(f16, fpst)) {
888
- if (float16_is_signaling_nan(f16, fpst)) {
678
- float_raise(float_flag_invalid, fpst);
889
- float_raise(float_flag_invalid, fpst);
679
- nan = float16_silence_nan(f16, fpst);
890
- if (!fpst->default_nan_mode) {
891
- nan = float16_silence_nan(f16, fpst);
892
- }
680
- }
893
- }
681
- if (fpst->default_nan_mode) {
894
- if (fpst->default_nan_mode) {
682
- nan = float16_default_nan(fpst);
895
- nan = float16_default_nan(fpst);
683
- }
896
- }
684
- return nan;
897
- return nan;
...
...
699
- float_raise(float_flag_underflow, fpst);
912
- float_raise(float_flag_underflow, fpst);
700
- return float16_set_sign(float16_zero, float16_is_neg(f16));
913
- return float16_set_sign(float16_zero, float16_is_neg(f16));
701
- }
914
- }
702
-
915
-
703
- f64_frac = call_recip_estimate(&f16_exp, 29,
916
- f64_frac = call_recip_estimate(&f16_exp, 29,
704
- ((uint64_t) f16_frac) << (52 - 10));
917
- ((uint64_t) f16_frac) << (52 - 10), false);
705
-
918
-
706
- /* result = sign : result_exp<4:0> : fraction<51:42> */
919
- /* result = sign : result_exp<4:0> : fraction<51:42> */
707
- f16_val = deposit32(0, 15, 1, f16_sign);
920
- f16_val = deposit32(0, 15, 1, f16_sign);
708
- f16_val = deposit32(f16_val, 10, 5, f16_exp);
921
- f16_val = deposit32(f16_val, 10, 5, f16_exp);
709
- f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
922
- f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
710
- return make_float16(f16_val);
923
- return make_float16(f16_val);
711
-}
924
-}
712
-
925
-
713
-float32 HELPER(recpe_f32)(float32 input, void *fpstp)
926
-/*
714
-{
927
- * FEAT_RPRES means the f32 FRECPE has an "increased precision" variant
715
- float_status *fpst = fpstp;
928
- * which is used when FPCR.AH == 1.
929
- */
930
-static float32 do_recpe_f32(float32 input, float_status *fpst, bool rpres)
931
-{
716
- float32 f32 = float32_squash_input_denormal(input, fpst);
932
- float32 f32 = float32_squash_input_denormal(input, fpst);
717
- uint32_t f32_val = float32_val(f32);
933
- uint32_t f32_val = float32_val(f32);
718
- bool f32_sign = float32_is_neg(f32);
934
- bool f32_sign = float32_is_neg(f32);
719
- int f32_exp = extract32(f32_val, 23, 8);
935
- int f32_exp = extract32(f32_val, 23, 8);
720
- uint32_t f32_frac = extract32(f32_val, 0, 23);
936
- uint32_t f32_frac = extract32(f32_val, 0, 23);
721
- uint64_t f64_frac;
937
- uint64_t f64_frac;
722
-
938
-
723
- if (float32_is_any_nan(f32)) {
939
- if (float32_is_any_nan(f32)) {
724
- float32 nan = f32;
940
- float32 nan = f32;
725
- if (float32_is_signaling_nan(f32, fpst)) {
941
- if (float32_is_signaling_nan(f32, fpst)) {
726
- float_raise(float_flag_invalid, fpst);
942
- float_raise(float_flag_invalid, fpst);
727
- nan = float32_silence_nan(f32, fpst);
943
- if (!fpst->default_nan_mode) {
944
- nan = float32_silence_nan(f32, fpst);
945
- }
728
- }
946
- }
729
- if (fpst->default_nan_mode) {
947
- if (fpst->default_nan_mode) {
730
- nan = float32_default_nan(fpst);
948
- nan = float32_default_nan(fpst);
731
- }
949
- }
732
- return nan;
950
- return nan;
...
...
747
- float_raise(float_flag_underflow, fpst);
965
- float_raise(float_flag_underflow, fpst);
748
- return float32_set_sign(float32_zero, float32_is_neg(f32));
966
- return float32_set_sign(float32_zero, float32_is_neg(f32));
749
- }
967
- }
750
-
968
-
751
- f64_frac = call_recip_estimate(&f32_exp, 253,
969
- f64_frac = call_recip_estimate(&f32_exp, 253,
752
- ((uint64_t) f32_frac) << (52 - 23));
970
- ((uint64_t) f32_frac) << (52 - 23), rpres);
753
-
971
-
754
- /* result = sign : result_exp<7:0> : fraction<51:29> */
972
- /* result = sign : result_exp<7:0> : fraction<51:29> */
755
- f32_val = deposit32(0, 31, 1, f32_sign);
973
- f32_val = deposit32(0, 31, 1, f32_sign);
756
- f32_val = deposit32(f32_val, 23, 8, f32_exp);
974
- f32_val = deposit32(f32_val, 23, 8, f32_exp);
757
- f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
975
- f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
758
- return make_float32(f32_val);
976
- return make_float32(f32_val);
759
-}
977
-}
760
-
978
-
761
-float64 HELPER(recpe_f64)(float64 input, void *fpstp)
979
-float32 HELPER(recpe_f32)(float32 input, float_status *fpst)
762
-{
980
-{
763
- float_status *fpst = fpstp;
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
-{
764
- float64 f64 = float64_squash_input_denormal(input, fpst);
991
- float64 f64 = float64_squash_input_denormal(input, fpst);
765
- uint64_t f64_val = float64_val(f64);
992
- uint64_t f64_val = float64_val(f64);
766
- bool f64_sign = float64_is_neg(f64);
993
- bool f64_sign = float64_is_neg(f64);
767
- int f64_exp = extract64(f64_val, 52, 11);
994
- int f64_exp = extract64(f64_val, 52, 11);
768
- uint64_t f64_frac = extract64(f64_val, 0, 52);
995
- uint64_t f64_frac = extract64(f64_val, 0, 52);
769
-
996
-
770
- /* Deal with any special cases */
997
- /* Deal with any special cases */
771
- if (float64_is_any_nan(f64)) {
998
- if (float64_is_any_nan(f64)) {
772
- float64 nan = f64;
999
- float64 nan = f64;
773
- if (float64_is_signaling_nan(f64, fpst)) {
1000
- if (float64_is_signaling_nan(f64, fpst)) {
774
- float_raise(float_flag_invalid, fpst);
1001
- float_raise(float_flag_invalid, fpst);
775
- nan = float64_silence_nan(f64, fpst);
1002
- if (!fpst->default_nan_mode) {
1003
- nan = float64_silence_nan(f64, fpst);
1004
- }
776
- }
1005
- }
777
- if (fpst->default_nan_mode) {
1006
- if (fpst->default_nan_mode) {
778
- nan = float64_default_nan(fpst);
1007
- nan = float64_default_nan(fpst);
779
- }
1008
- }
780
- return nan;
1009
- return nan;
...
...
794
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
1023
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
795
- float_raise(float_flag_underflow, fpst);
1024
- float_raise(float_flag_underflow, fpst);
796
- return float64_set_sign(float64_zero, float64_is_neg(f64));
1025
- return float64_set_sign(float64_zero, float64_is_neg(f64));
797
- }
1026
- }
798
-
1027
-
799
- f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
1028
- f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac, false);
800
-
1029
-
801
- /* result = sign : result_exp<10:0> : fraction<51:0>; */
1030
- /* result = sign : result_exp<10:0> : fraction<51:0>; */
802
- f64_val = deposit64(0, 63, 1, f64_sign);
1031
- f64_val = deposit64(0, 63, 1, f64_sign);
803
- f64_val = deposit64(f64_val, 52, 11, f64_exp);
1032
- f64_val = deposit64(f64_val, 52, 11, f64_exp);
804
- f64_val = deposit64(f64_val, 0, 52, f64_frac);
1033
- f64_val = deposit64(f64_val, 0, 52, f64_frac);
...
...
828
- assert(256 <= estimate && estimate < 512);
1057
- assert(256 <= estimate && estimate < 512);
829
-
1058
-
830
- return estimate;
1059
- return estimate;
831
-}
1060
-}
832
-
1061
-
833
-
1062
-static int do_recip_sqrt_estimate_incprec(int a)
834
-static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
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)
835
-{
1092
-{
836
- int estimate;
1093
- int estimate;
837
- uint32_t scaled;
1094
- uint32_t scaled;
838
-
1095
-
839
- if (*exp == 0) {
1096
- if (*exp == 0) {
...
...
842
- *exp -= 1;
1099
- *exp -= 1;
843
- }
1100
- }
844
- frac = extract64(frac, 0, 51) << 1;
1101
- frac = extract64(frac, 0, 51) << 1;
845
- }
1102
- }
846
-
1103
-
847
- if (*exp & 1) {
1104
- if (increasedprecision) {
848
- /* scaled = UInt('01':fraction<51:45>) */
1105
- if (*exp & 1) {
849
- scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
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);
850
- } else {
1113
- } else {
851
- /* scaled = UInt('1':fraction<51:44>) */
1114
- if (*exp & 1) {
852
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1115
- /* scaled = UInt('01':fraction<51:45>) */
853
- }
1116
- scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
854
- estimate = do_recip_sqrt_estimate(scaled);
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
- }
855
-
1123
-
856
- *exp = (exp_off - *exp) / 2;
1124
- *exp = (exp_off - *exp) / 2;
857
- return extract64(estimate, 0, 8) << 44;
1125
- if (increasedprecision) {
858
-}
1126
- return extract64(estimate, 0, 12) << 40;
859
-
1127
- } else {
860
-uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
1128
- return extract64(estimate, 0, 8) << 44;
861
-{
1129
- }
862
- float_status *s = fpstp;
1130
-}
1131
-
1132
-uint32_t HELPER(rsqrte_f16)(uint32_t input, float_status *s)
1133
-{
863
- float16 f16 = float16_squash_input_denormal(input, s);
1134
- float16 f16 = float16_squash_input_denormal(input, s);
864
- uint16_t val = float16_val(f16);
1135
- uint16_t val = float16_val(f16);
865
- bool f16_sign = float16_is_neg(f16);
1136
- bool f16_sign = float16_is_neg(f16);
866
- int f16_exp = extract32(val, 10, 5);
1137
- int f16_exp = extract32(val, 10, 5);
867
- uint16_t f16_frac = extract32(val, 0, 10);
1138
- uint16_t f16_frac = extract32(val, 0, 10);
868
- uint64_t f64_frac;
1139
- uint64_t f64_frac;
869
-
1140
-
870
- if (float16_is_any_nan(f16)) {
1141
- if (float16_is_any_nan(f16)) {
871
- float16 nan = f16;
1142
- float16 nan = f16;
872
- if (float16_is_signaling_nan(f16, s)) {
1143
- if (float16_is_signaling_nan(f16, s)) {
873
- float_raise(float_flag_invalid, s);
1144
- float_raise(float_flag_invalid, s);
874
- nan = float16_silence_nan(f16, s);
1145
- if (!s->default_nan_mode) {
1146
- nan = float16_silence_nan(f16, s);
1147
- }
875
- }
1148
- }
876
- if (s->default_nan_mode) {
1149
- if (s->default_nan_mode) {
877
- nan = float16_default_nan(s);
1150
- nan = float16_default_nan(s);
878
- }
1151
- }
879
- return nan;
1152
- return nan;
...
...
890
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1163
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
891
- * preserving the parity of the exponent. */
1164
- * preserving the parity of the exponent. */
892
-
1165
-
893
- f64_frac = ((uint64_t) f16_frac) << (52 - 10);
1166
- f64_frac = ((uint64_t) f16_frac) << (52 - 10);
894
-
1167
-
895
- f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
1168
- f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac, false);
896
-
1169
-
897
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
1170
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
898
- val = deposit32(0, 15, 1, f16_sign);
1171
- val = deposit32(0, 15, 1, f16_sign);
899
- val = deposit32(val, 10, 5, f16_exp);
1172
- val = deposit32(val, 10, 5, f16_exp);
900
- val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
1173
- val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
901
- return make_float16(val);
1174
- return make_float16(val);
902
-}
1175
-}
903
-
1176
-
904
-float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
1177
-/*
905
-{
1178
- * FEAT_RPRES means the f32 FRSQRTE has an "increased precision" variant
906
- float_status *s = fpstp;
1179
- * which is used when FPCR.AH == 1.
1180
- */
1181
-static float32 do_rsqrte_f32(float32 input, float_status *s, bool rpres)
1182
-{
907
- float32 f32 = float32_squash_input_denormal(input, s);
1183
- float32 f32 = float32_squash_input_denormal(input, s);
908
- uint32_t val = float32_val(f32);
1184
- uint32_t val = float32_val(f32);
909
- uint32_t f32_sign = float32_is_neg(f32);
1185
- uint32_t f32_sign = float32_is_neg(f32);
910
- int f32_exp = extract32(val, 23, 8);
1186
- int f32_exp = extract32(val, 23, 8);
911
- uint32_t f32_frac = extract32(val, 0, 23);
1187
- uint32_t f32_frac = extract32(val, 0, 23);
912
- uint64_t f64_frac;
1188
- uint64_t f64_frac;
913
-
1189
-
914
- if (float32_is_any_nan(f32)) {
1190
- if (float32_is_any_nan(f32)) {
915
- float32 nan = f32;
1191
- float32 nan = f32;
916
- if (float32_is_signaling_nan(f32, s)) {
1192
- if (float32_is_signaling_nan(f32, s)) {
917
- float_raise(float_flag_invalid, s);
1193
- float_raise(float_flag_invalid, s);
918
- nan = float32_silence_nan(f32, s);
1194
- if (!s->default_nan_mode) {
1195
- nan = float32_silence_nan(f32, s);
1196
- }
919
- }
1197
- }
920
- if (s->default_nan_mode) {
1198
- if (s->default_nan_mode) {
921
- nan = float32_default_nan(s);
1199
- nan = float32_default_nan(s);
922
- }
1200
- }
923
- return nan;
1201
- return nan;
...
...
934
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1212
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
935
- * preserving the parity of the exponent. */
1213
- * preserving the parity of the exponent. */
936
-
1214
-
937
- f64_frac = ((uint64_t) f32_frac) << 29;
1215
- f64_frac = ((uint64_t) f32_frac) << 29;
938
-
1216
-
939
- f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
1217
- f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac, rpres);
940
-
1218
-
941
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
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
- */
942
- val = deposit32(0, 31, 1, f32_sign);
1224
- val = deposit32(0, 31, 1, f32_sign);
943
- val = deposit32(val, 23, 8, f32_exp);
1225
- val = deposit32(val, 23, 8, f32_exp);
944
- val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
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
- }
945
- return make_float32(val);
1231
- return make_float32(val);
946
-}
1232
-}
947
-
1233
-
948
-float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
1234
-float32 HELPER(rsqrte_f32)(float32 input, float_status *s)
949
-{
1235
-{
950
- float_status *s = fpstp;
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
-{
951
- float64 f64 = float64_squash_input_denormal(input, s);
1246
- float64 f64 = float64_squash_input_denormal(input, s);
952
- uint64_t val = float64_val(f64);
1247
- uint64_t val = float64_val(f64);
953
- bool f64_sign = float64_is_neg(f64);
1248
- bool f64_sign = float64_is_neg(f64);
954
- int f64_exp = extract64(val, 52, 11);
1249
- int f64_exp = extract64(val, 52, 11);
955
- uint64_t f64_frac = extract64(val, 0, 52);
1250
- uint64_t f64_frac = extract64(val, 0, 52);
956
-
1251
-
957
- if (float64_is_any_nan(f64)) {
1252
- if (float64_is_any_nan(f64)) {
958
- float64 nan = f64;
1253
- float64 nan = f64;
959
- if (float64_is_signaling_nan(f64, s)) {
1254
- if (float64_is_signaling_nan(f64, s)) {
960
- float_raise(float_flag_invalid, s);
1255
- float_raise(float_flag_invalid, s);
961
- nan = float64_silence_nan(f64, s);
1256
- if (!s->default_nan_mode) {
1257
- nan = float64_silence_nan(f64, s);
1258
- }
962
- }
1259
- }
963
- if (s->default_nan_mode) {
1260
- if (s->default_nan_mode) {
964
- nan = float64_default_nan(s);
1261
- nan = float64_default_nan(s);
965
- }
1262
- }
966
- return nan;
1263
- return nan;
...
...
972
- return float64_default_nan(s);
1269
- return float64_default_nan(s);
973
- } else if (float64_is_infinity(f64)) {
1270
- } else if (float64_is_infinity(f64)) {
974
- return float64_zero;
1271
- return float64_zero;
975
- }
1272
- }
976
-
1273
-
977
- f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
1274
- f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac, false);
978
-
1275
-
979
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
1276
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
980
- val = deposit64(0, 61, 1, f64_sign);
1277
- val = deposit64(0, 61, 1, f64_sign);
981
- val = deposit64(val, 52, 11, f64_exp);
1278
- val = deposit64(val, 52, 11, f64_exp);
982
- val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
1279
- val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
983
- return make_float64(val);
1280
- return make_float64(val);
984
-}
1281
-}
985
-
1282
-
986
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
1283
-uint32_t HELPER(recpe_u32)(uint32_t a)
987
-{
1284
-{
988
- /* float_status *s = fpstp; */
989
- int input, estimate;
1285
- int input, estimate;
990
-
1286
-
991
- if ((a & 0x80000000) == 0) {
1287
- if ((a & 0x80000000) == 0) {
992
- return 0xffffffff;
1288
- return 0xffffffff;
993
- }
1289
- }
...
...
996
- estimate = recip_estimate(input);
1292
- estimate = recip_estimate(input);
997
-
1293
-
998
- return deposit32(0, (32 - 9), 9, estimate);
1294
- return deposit32(0, (32 - 9), 9, estimate);
999
-}
1295
-}
1000
-
1296
-
1001
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
1297
-uint32_t HELPER(rsqrte_u32)(uint32_t a)
1002
-{
1298
-{
1003
- int estimate;
1299
- int estimate;
1004
-
1300
-
1005
- if ((a & 0xc0000000) == 0) {
1301
- if ((a & 0xc0000000) == 0) {
1006
- return 0xffffffff;
1302
- return 0xffffffff;
...
...
1010
-
1306
-
1011
- return deposit32(0, 23, 9, estimate);
1307
- return deposit32(0, 23, 9, estimate);
1012
-}
1308
-}
1013
-
1309
-
1014
-/* VFPv4 fused multiply-accumulate */
1310
-/* VFPv4 fused multiply-accumulate */
1015
-float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
1311
-dh_ctype_f16 VFP_HELPER(muladd, h)(dh_ctype_f16 a, dh_ctype_f16 b,
1016
-{
1312
- dh_ctype_f16 c, float_status *fpst)
1017
- float_status *fpst = fpstp;
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
-{
1018
- return float32_muladd(a, b, c, 0, fpst);
1320
- return float32_muladd(a, b, c, 0, fpst);
1019
-}
1321
-}
1020
-
1322
-
1021
-float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
1323
-float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c,
1022
-{
1324
- float_status *fpst)
1023
- float_status *fpst = fpstp;
1325
-{
1024
- return float64_muladd(a, b, c, 0, fpst);
1326
- return float64_muladd(a, b, c, 0, fpst);
1025
-}
1327
-}
1026
-
1328
-
1027
-/* ARMv8 round to integral */
1329
-/* ARMv8 round to integral */
1028
-float32 HELPER(rints_exact)(float32 x, void *fp_status)
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)
1029
-{
1336
-{
1030
- return float32_round_to_int(x, fp_status);
1337
- return float32_round_to_int(x, fp_status);
1031
-}
1338
-}
1032
-
1339
-
1033
-float64 HELPER(rintd_exact)(float64 x, void *fp_status)
1340
-float64 HELPER(rintd_exact)(float64 x, float_status *fp_status)
1034
-{
1341
-{
1035
- return float64_round_to_int(x, fp_status);
1342
- return float64_round_to_int(x, fp_status);
1036
-}
1343
-}
1037
-
1344
-
1038
-float32 HELPER(rints)(float32 x, void *fp_status)
1345
-dh_ctype_f16 HELPER(rinth)(dh_ctype_f16 x, float_status *fp_status)
1039
-{
1346
-{
1040
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1347
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1041
- float32 ret;
1348
- float16 ret;
1042
-
1349
-
1043
- ret = float32_round_to_int(x, fp_status);
1350
- ret = float16_round_to_int(x, fp_status);
1044
-
1351
-
1045
- /* Suppress any inexact exceptions the conversion produced */
1352
- /* Suppress any inexact exceptions the conversion produced */
1046
- if (!(old_flags & float_flag_inexact)) {
1353
- if (!(old_flags & float_flag_inexact)) {
1047
- new_flags = get_float_exception_flags(fp_status);
1354
- new_flags = get_float_exception_flags(fp_status);
1048
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1355
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1049
- }
1356
- }
1050
-
1357
-
1051
- return ret;
1358
- return ret;
1052
-}
1359
-}
1053
-
1360
-
1054
-float64 HELPER(rintd)(float64 x, void *fp_status)
1361
-float32 HELPER(rints)(float32 x, float_status *fp_status)
1055
-{
1362
-{
1056
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1363
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1057
- float64 ret;
1364
- float32 ret;
1058
-
1365
-
1059
- ret = float64_round_to_int(x, fp_status);
1366
- ret = float32_round_to_int(x, fp_status);
1060
-
1061
- new_flags = get_float_exception_flags(fp_status);
1062
-
1367
-
1063
- /* Suppress any inexact exceptions the conversion produced */
1368
- /* Suppress any inexact exceptions the conversion produced */
1064
- if (!(old_flags & float_flag_inexact)) {
1369
- if (!(old_flags & float_flag_inexact)) {
1065
- new_flags = get_float_exception_flags(fp_status);
1370
- new_flags = get_float_exception_flags(fp_status);
1066
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1371
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1067
- }
1372
- }
1068
-
1373
-
1069
- return ret;
1374
- return ret;
1070
-}
1375
-}
1071
-
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
-
1072
-/* Convert ARM rounding mode to softfloat */
1393
-/* Convert ARM rounding mode to softfloat */
1073
-int arm_rmode_to_sf(int rmode)
1394
-const FloatRoundMode arm_rmode_to_sf_map[] = {
1074
-{
1395
- [FPROUNDING_TIEEVEN] = float_round_nearest_even,
1075
- switch (rmode) {
1396
- [FPROUNDING_POSINF] = float_round_up,
1076
- case FPROUNDING_TIEAWAY:
1397
- [FPROUNDING_NEGINF] = float_round_down,
1077
- rmode = float_round_ties_away;
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
- }
1078
- break;
1549
- break;
1079
- case FPROUNDING_ODD:
1550
- case ARM_VFP_FPSID:
1080
- /* FIXME: add support for TIEAWAY and ODD */
1551
- if (!(arm_hcr_el2_eff(env) & HCR_TID0)) {
1081
- qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
1552
- return;
1082
- rmode);
1553
- }
1083
- /* fall through for now */
1554
- break;
1084
- case FPROUNDING_TIEEVEN:
1085
- default:
1555
- default:
1086
- rmode = float_round_nearest_even;
1556
- g_assert_not_reached();
1087
- break;
1557
- }
1088
- case FPROUNDING_POSINF:
1558
-
1089
- rmode = float_round_up;
1559
- syndrome = ((EC_FPIDTRAP << ARM_EL_EC_SHIFT)
1090
- break;
1560
- | ARM_EL_IL
1091
- case FPROUNDING_NEGINF:
1561
- | (1 << 24) | (0xe << 20) | (7 << 14)
1092
- rmode = float_round_down;
1562
- | (reg << 10) | (rt << 5) | 1);
1093
- break;
1563
-
1094
- case FPROUNDING_ZERO:
1564
- raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
1095
- rmode = float_round_to_zero;
1565
-}
1096
- break;
1566
-
1097
- }
1567
-#endif
1098
- return rmode;
1568
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
1099
-}
1569
index XXXXXXX..XXXXXXX 100644
1100
-
1570
--- a/target/arm/tcg/meson.build
1101
/* CRC helpers.
1571
+++ b/target/arm/tcg/meson.build
1102
* The upper bytes of val (above the number specified by 'bytes') must have
1572
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
1103
* been zeroed out by the caller.
1573
'vec_helper.c',
1104
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
1574
'tlb-insns.c',
1105
new file mode 100644
1575
'arith_helper.c',
1106
index XXXXXXX..XXXXXXX
1576
+ 'vfp_helper.c',
1107
--- /dev/null
1577
))
1108
+++ b/target/arm/vfp_helper.c
1578
1109
@@ -XXX,XX +XXX,XX @@
1579
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
1110
+/*
1111
+ * ARM VFP floating-point operations
1112
+ *
1113
+ * Copyright (c) 2003 Fabrice Bellard
1114
+ *
1115
+ * This library is free software; you can redistribute it and/or
1116
+ * modify it under the terms of the GNU Lesser General Public
1117
+ * License as published by the Free Software Foundation; either
1118
+ * version 2.1 of the License, or (at your option) any later version.
1119
+ *
1120
+ * This library is distributed in the hope that it will be useful,
1121
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1122
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1123
+ * Lesser General Public License for more details.
1124
+ *
1125
+ * You should have received a copy of the GNU Lesser General Public
1126
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1127
+ */
1128
+
1129
+#include "qemu/osdep.h"
1130
+#include "qemu/log.h"
1131
+#include "cpu.h"
1132
+#include "exec/helper-proto.h"
1133
+#include "fpu/softfloat.h"
1134
+#include "internals.h"
1135
+
1136
+
1137
+/* VFP support. We follow the convention used for VFP instructions:
1138
+ Single precision routines have a "s" suffix, double precision a
1139
+ "d" suffix. */
1140
+
1141
+/* Convert host exception flags to vfp form. */
1142
+static inline int vfp_exceptbits_from_host(int host_bits)
1143
+{
1144
+ int target_bits = 0;
1145
+
1146
+ if (host_bits & float_flag_invalid)
1147
+ target_bits |= 1;
1148
+ if (host_bits & float_flag_divbyzero)
1149
+ target_bits |= 2;
1150
+ if (host_bits & float_flag_overflow)
1151
+ target_bits |= 4;
1152
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal))
1153
+ target_bits |= 8;
1154
+ if (host_bits & float_flag_inexact)
1155
+ target_bits |= 0x10;
1156
+ if (host_bits & float_flag_input_denormal)
1157
+ target_bits |= 0x80;
1158
+ return target_bits;
1159
+}
1160
+
1161
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
1162
+{
1163
+ uint32_t i, fpscr;
1164
+
1165
+ fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
1166
+ | (env->vfp.vec_len << 16)
1167
+ | (env->vfp.vec_stride << 20);
1168
+
1169
+ i = get_float_exception_flags(&env->vfp.fp_status);
1170
+ i |= get_float_exception_flags(&env->vfp.standard_fp_status);
1171
+ /* FZ16 does not generate an input denormal exception. */
1172
+ i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
1173
+ & ~float_flag_input_denormal);
1174
+ fpscr |= vfp_exceptbits_from_host(i);
1175
+
1176
+ i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
1177
+ fpscr |= i ? FPCR_QC : 0;
1178
+
1179
+ return fpscr;
1180
+}
1181
+
1182
+uint32_t vfp_get_fpscr(CPUARMState *env)
1183
+{
1184
+ return HELPER(vfp_get_fpscr)(env);
1185
+}
1186
+
1187
+/* Convert vfp exception flags to target form. */
1188
+static inline int vfp_exceptbits_to_host(int target_bits)
1189
+{
1190
+ int host_bits = 0;
1191
+
1192
+ if (target_bits & 1)
1193
+ host_bits |= float_flag_invalid;
1194
+ if (target_bits & 2)
1195
+ host_bits |= float_flag_divbyzero;
1196
+ if (target_bits & 4)
1197
+ host_bits |= float_flag_overflow;
1198
+ if (target_bits & 8)
1199
+ host_bits |= float_flag_underflow;
1200
+ if (target_bits & 0x10)
1201
+ host_bits |= float_flag_inexact;
1202
+ if (target_bits & 0x80)
1203
+ host_bits |= float_flag_input_denormal;
1204
+ return host_bits;
1205
+}
1206
+
1207
+void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
1208
+{
1209
+ int i;
1210
+ uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
1211
+
1212
+ /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
1213
+ if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
1214
+ val &= ~FPCR_FZ16;
1215
+ }
1216
+
1217
+ /*
1218
+ * We don't implement trapped exception handling, so the
1219
+ * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
1220
+ *
1221
+ * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
1222
+ * (which are stored in fp_status), and the other RES0 bits
1223
+ * in between, then we clear all of the low 16 bits.
1224
+ */
1225
+ env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
1226
+ env->vfp.vec_len = (val >> 16) & 7;
1227
+ env->vfp.vec_stride = (val >> 20) & 3;
1228
+
1229
+ /*
1230
+ * The bit we set within fpscr_q is arbitrary; the register as a
1231
+ * whole being zero/non-zero is what counts.
1232
+ */
1233
+ env->vfp.qc[0] = val & FPCR_QC;
1234
+ env->vfp.qc[1] = 0;
1235
+ env->vfp.qc[2] = 0;
1236
+ env->vfp.qc[3] = 0;
1237
+
1238
+ changed ^= val;
1239
+ if (changed & (3 << 22)) {
1240
+ i = (val >> 22) & 3;
1241
+ switch (i) {
1242
+ case FPROUNDING_TIEEVEN:
1243
+ i = float_round_nearest_even;
1244
+ break;
1245
+ case FPROUNDING_POSINF:
1246
+ i = float_round_up;
1247
+ break;
1248
+ case FPROUNDING_NEGINF:
1249
+ i = float_round_down;
1250
+ break;
1251
+ case FPROUNDING_ZERO:
1252
+ i = float_round_to_zero;
1253
+ break;
1254
+ }
1255
+ set_float_rounding_mode(i, &env->vfp.fp_status);
1256
+ set_float_rounding_mode(i, &env->vfp.fp_status_f16);
1257
+ }
1258
+ if (changed & FPCR_FZ16) {
1259
+ bool ftz_enabled = val & FPCR_FZ16;
1260
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
1261
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
1262
+ }
1263
+ if (changed & FPCR_FZ) {
1264
+ bool ftz_enabled = val & FPCR_FZ;
1265
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
1266
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
1267
+ }
1268
+ if (changed & FPCR_DN) {
1269
+ bool dnan_enabled = val & FPCR_DN;
1270
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
1271
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
1272
+ }
1273
+
1274
+ /* The exception flags are ORed together when we read fpscr so we
1275
+ * only need to preserve the current state in one of our
1276
+ * float_status values.
1277
+ */
1278
+ i = vfp_exceptbits_to_host(val);
1279
+ set_float_exception_flags(i, &env->vfp.fp_status);
1280
+ set_float_exception_flags(0, &env->vfp.fp_status_f16);
1281
+ set_float_exception_flags(0, &env->vfp.standard_fp_status);
1282
+}
1283
+
1284
+void vfp_set_fpscr(CPUARMState *env, uint32_t val)
1285
+{
1286
+ HELPER(vfp_set_fpscr)(env, val);
1287
+}
1288
+
1289
+#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
1290
+
1291
+#define VFP_BINOP(name) \
1292
+float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
1293
+{ \
1294
+ float_status *fpst = fpstp; \
1295
+ return float32_ ## name(a, b, fpst); \
1296
+} \
1297
+float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
1298
+{ \
1299
+ float_status *fpst = fpstp; \
1300
+ return float64_ ## name(a, b, fpst); \
1301
+}
1302
+VFP_BINOP(add)
1303
+VFP_BINOP(sub)
1304
+VFP_BINOP(mul)
1305
+VFP_BINOP(div)
1306
+VFP_BINOP(min)
1307
+VFP_BINOP(max)
1308
+VFP_BINOP(minnum)
1309
+VFP_BINOP(maxnum)
1310
+#undef VFP_BINOP
1311
+
1312
+float32 VFP_HELPER(neg, s)(float32 a)
1313
+{
1314
+ return float32_chs(a);
1315
+}
1316
+
1317
+float64 VFP_HELPER(neg, d)(float64 a)
1318
+{
1319
+ return float64_chs(a);
1320
+}
1321
+
1322
+float32 VFP_HELPER(abs, s)(float32 a)
1323
+{
1324
+ return float32_abs(a);
1325
+}
1326
+
1327
+float64 VFP_HELPER(abs, d)(float64 a)
1328
+{
1329
+ return float64_abs(a);
1330
+}
1331
+
1332
+float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
1333
+{
1334
+ return float32_sqrt(a, &env->vfp.fp_status);
1335
+}
1336
+
1337
+float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
1338
+{
1339
+ return float64_sqrt(a, &env->vfp.fp_status);
1340
+}
1341
+
1342
+static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
1343
+{
1344
+ uint32_t flags;
1345
+ switch (cmp) {
1346
+ case float_relation_equal:
1347
+ flags = 0x6;
1348
+ break;
1349
+ case float_relation_less:
1350
+ flags = 0x8;
1351
+ break;
1352
+ case float_relation_greater:
1353
+ flags = 0x2;
1354
+ break;
1355
+ case float_relation_unordered:
1356
+ flags = 0x3;
1357
+ break;
1358
+ default:
1359
+ g_assert_not_reached();
1360
+ }
1361
+ env->vfp.xregs[ARM_VFP_FPSCR] =
1362
+ deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
1363
+}
1364
+
1365
+/* XXX: check quiet/signaling case */
1366
+#define DO_VFP_cmp(p, type) \
1367
+void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
1368
+{ \
1369
+ softfloat_to_vfp_compare(env, \
1370
+ type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
1371
+} \
1372
+void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
1373
+{ \
1374
+ softfloat_to_vfp_compare(env, \
1375
+ type ## _compare(a, b, &env->vfp.fp_status)); \
1376
+}
1377
+DO_VFP_cmp(s, float32)
1378
+DO_VFP_cmp(d, float64)
1379
+#undef DO_VFP_cmp
1380
+
1381
+/* Integer to float and float to integer conversions */
1382
+
1383
+#define CONV_ITOF(name, ftype, fsz, sign) \
1384
+ftype HELPER(name)(uint32_t x, void *fpstp) \
1385
+{ \
1386
+ float_status *fpst = fpstp; \
1387
+ return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
1388
+}
1389
+
1390
+#define CONV_FTOI(name, ftype, fsz, sign, round) \
1391
+sign##int32_t HELPER(name)(ftype x, void *fpstp) \
1392
+{ \
1393
+ float_status *fpst = fpstp; \
1394
+ if (float##fsz##_is_any_nan(x)) { \
1395
+ float_raise(float_flag_invalid, fpst); \
1396
+ return 0; \
1397
+ } \
1398
+ return float##fsz##_to_##sign##int32##round(x, fpst); \
1399
+}
1400
+
1401
+#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
1402
+ CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
1403
+ CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
1404
+ CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
1405
+
1406
+FLOAT_CONVS(si, h, uint32_t, 16, )
1407
+FLOAT_CONVS(si, s, float32, 32, )
1408
+FLOAT_CONVS(si, d, float64, 64, )
1409
+FLOAT_CONVS(ui, h, uint32_t, 16, u)
1410
+FLOAT_CONVS(ui, s, float32, 32, u)
1411
+FLOAT_CONVS(ui, d, float64, 64, u)
1412
+
1413
+#undef CONV_ITOF
1414
+#undef CONV_FTOI
1415
+#undef FLOAT_CONVS
1416
+
1417
+/* floating point conversion */
1418
+float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
1419
+{
1420
+ return float32_to_float64(x, &env->vfp.fp_status);
1421
+}
1422
+
1423
+float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
1424
+{
1425
+ return float64_to_float32(x, &env->vfp.fp_status);
1426
+}
1427
+
1428
+/* VFP3 fixed point conversion. */
1429
+#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1430
+float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
1431
+ void *fpstp) \
1432
+{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
1433
+
1434
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
1435
+uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
1436
+ void *fpst) \
1437
+{ \
1438
+ if (unlikely(float##fsz##_is_any_nan(x))) { \
1439
+ float_raise(float_flag_invalid, fpst); \
1440
+ return 0; \
1441
+ } \
1442
+ return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
1443
+}
1444
+
1445
+#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
1446
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1447
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1448
+ float_round_to_zero, _round_to_zero) \
1449
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1450
+ get_float_rounding_mode(fpst), )
1451
+
1452
+#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
1453
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1454
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1455
+ get_float_rounding_mode(fpst), )
1456
+
1457
+VFP_CONV_FIX(sh, d, 64, 64, int16)
1458
+VFP_CONV_FIX(sl, d, 64, 64, int32)
1459
+VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
1460
+VFP_CONV_FIX(uh, d, 64, 64, uint16)
1461
+VFP_CONV_FIX(ul, d, 64, 64, uint32)
1462
+VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
1463
+VFP_CONV_FIX(sh, s, 32, 32, int16)
1464
+VFP_CONV_FIX(sl, s, 32, 32, int32)
1465
+VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
1466
+VFP_CONV_FIX(uh, s, 32, 32, uint16)
1467
+VFP_CONV_FIX(ul, s, 32, 32, uint32)
1468
+VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
1469
+
1470
+#undef VFP_CONV_FIX
1471
+#undef VFP_CONV_FIX_FLOAT
1472
+#undef VFP_CONV_FLOAT_FIX_ROUND
1473
+#undef VFP_CONV_FIX_A64
1474
+
1475
+uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
1476
+{
1477
+ return int32_to_float16_scalbn(x, -shift, fpst);
1478
+}
1479
+
1480
+uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
1481
+{
1482
+ return uint32_to_float16_scalbn(x, -shift, fpst);
1483
+}
1484
+
1485
+uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
1486
+{
1487
+ return int64_to_float16_scalbn(x, -shift, fpst);
1488
+}
1489
+
1490
+uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
1491
+{
1492
+ return uint64_to_float16_scalbn(x, -shift, fpst);
1493
+}
1494
+
1495
+uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
1496
+{
1497
+ if (unlikely(float16_is_any_nan(x))) {
1498
+ float_raise(float_flag_invalid, fpst);
1499
+ return 0;
1500
+ }
1501
+ return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
1502
+ shift, fpst);
1503
+}
1504
+
1505
+uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
1506
+{
1507
+ if (unlikely(float16_is_any_nan(x))) {
1508
+ float_raise(float_flag_invalid, fpst);
1509
+ return 0;
1510
+ }
1511
+ return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
1512
+ shift, fpst);
1513
+}
1514
+
1515
+uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
1516
+{
1517
+ if (unlikely(float16_is_any_nan(x))) {
1518
+ float_raise(float_flag_invalid, fpst);
1519
+ return 0;
1520
+ }
1521
+ return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
1522
+ shift, fpst);
1523
+}
1524
+
1525
+uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
1526
+{
1527
+ if (unlikely(float16_is_any_nan(x))) {
1528
+ float_raise(float_flag_invalid, fpst);
1529
+ return 0;
1530
+ }
1531
+ return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
1532
+ shift, fpst);
1533
+}
1534
+
1535
+uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
1536
+{
1537
+ if (unlikely(float16_is_any_nan(x))) {
1538
+ float_raise(float_flag_invalid, fpst);
1539
+ return 0;
1540
+ }
1541
+ return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
1542
+ shift, fpst);
1543
+}
1544
+
1545
+uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
1546
+{
1547
+ if (unlikely(float16_is_any_nan(x))) {
1548
+ float_raise(float_flag_invalid, fpst);
1549
+ return 0;
1550
+ }
1551
+ return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
1552
+ shift, fpst);
1553
+}
1554
+
1555
+/* Set the current fp rounding mode and return the old one.
1556
+ * The argument is a softfloat float_round_ value.
1557
+ */
1558
+uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
1559
+{
1560
+ float_status *fp_status = fpstp;
1561
+
1562
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
1563
+ set_float_rounding_mode(rmode, fp_status);
1564
+
1565
+ return prev_rmode;
1566
+}
1567
+
1568
+/* Set the current fp rounding mode in the standard fp status and return
1569
+ * the old one. This is for NEON instructions that need to change the
1570
+ * rounding mode but wish to use the standard FPSCR values for everything
1571
+ * else. Always set the rounding mode back to the correct value after
1572
+ * modifying it.
1573
+ * The argument is a softfloat float_round_ value.
1574
+ */
1575
+uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
1576
+{
1577
+ float_status *fp_status = &env->vfp.standard_fp_status;
1578
+
1579
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
1580
+ set_float_rounding_mode(rmode, fp_status);
1581
+
1582
+ return prev_rmode;
1583
+}
1584
+
1585
+/* Half precision conversions. */
1586
+float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
1587
+{
1588
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1589
+ * it would affect flushing input denormals.
1590
+ */
1591
+ float_status *fpst = fpstp;
1592
+ flag save = get_flush_inputs_to_zero(fpst);
1593
+ set_flush_inputs_to_zero(false, fpst);
1594
+ float32 r = float16_to_float32(a, !ahp_mode, fpst);
1595
+ set_flush_inputs_to_zero(save, fpst);
1596
+ return r;
1597
+}
1598
+
1599
+uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
1600
+{
1601
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1602
+ * it would affect flushing output denormals.
1603
+ */
1604
+ float_status *fpst = fpstp;
1605
+ flag save = get_flush_to_zero(fpst);
1606
+ set_flush_to_zero(false, fpst);
1607
+ float16 r = float32_to_float16(a, !ahp_mode, fpst);
1608
+ set_flush_to_zero(save, fpst);
1609
+ return r;
1610
+}
1611
+
1612
+float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
1613
+{
1614
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1615
+ * it would affect flushing input denormals.
1616
+ */
1617
+ float_status *fpst = fpstp;
1618
+ flag save = get_flush_inputs_to_zero(fpst);
1619
+ set_flush_inputs_to_zero(false, fpst);
1620
+ float64 r = float16_to_float64(a, !ahp_mode, fpst);
1621
+ set_flush_inputs_to_zero(save, fpst);
1622
+ return r;
1623
+}
1624
+
1625
+uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
1626
+{
1627
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1628
+ * it would affect flushing output denormals.
1629
+ */
1630
+ float_status *fpst = fpstp;
1631
+ flag save = get_flush_to_zero(fpst);
1632
+ set_flush_to_zero(false, fpst);
1633
+ float16 r = float64_to_float16(a, !ahp_mode, fpst);
1634
+ set_flush_to_zero(save, fpst);
1635
+ return r;
1636
+}
1637
+
1638
+#define float32_two make_float32(0x40000000)
1639
+#define float32_three make_float32(0x40400000)
1640
+#define float32_one_point_five make_float32(0x3fc00000)
1641
+
1642
+float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
1643
+{
1644
+ float_status *s = &env->vfp.standard_fp_status;
1645
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
1646
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
1647
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
1648
+ float_raise(float_flag_input_denormal, s);
1649
+ }
1650
+ return float32_two;
1651
+ }
1652
+ return float32_sub(float32_two, float32_mul(a, b, s), s);
1653
+}
1654
+
1655
+float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
1656
+{
1657
+ float_status *s = &env->vfp.standard_fp_status;
1658
+ float32 product;
1659
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
1660
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
1661
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
1662
+ float_raise(float_flag_input_denormal, s);
1663
+ }
1664
+ return float32_one_point_five;
1665
+ }
1666
+ product = float32_mul(a, b, s);
1667
+ return float32_div(float32_sub(float32_three, product, s), float32_two, s);
1668
+}
1669
+
1670
+/* NEON helpers. */
1671
+
1672
+/* Constants 256 and 512 are used in some helpers; we avoid relying on
1673
+ * int->float conversions at run-time. */
1674
+#define float64_256 make_float64(0x4070000000000000LL)
1675
+#define float64_512 make_float64(0x4080000000000000LL)
1676
+#define float16_maxnorm make_float16(0x7bff)
1677
+#define float32_maxnorm make_float32(0x7f7fffff)
1678
+#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
1679
+
1680
+/* Reciprocal functions
1681
+ *
1682
+ * The algorithm that must be used to calculate the estimate
1683
+ * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
1684
+ */
1685
+
1686
+/* See RecipEstimate()
1687
+ *
1688
+ * input is a 9 bit fixed point number
1689
+ * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
1690
+ * result range 256 .. 511 for a number from 1.0 to 511/256.
1691
+ */
1692
+
1693
+static int recip_estimate(int input)
1694
+{
1695
+ int a, b, r;
1696
+ assert(256 <= input && input < 512);
1697
+ a = (input * 2) + 1;
1698
+ b = (1 << 19) / a;
1699
+ r = (b + 1) >> 1;
1700
+ assert(256 <= r && r < 512);
1701
+ return r;
1702
+}
1703
+
1704
+/*
1705
+ * Common wrapper to call recip_estimate
1706
+ *
1707
+ * The parameters are exponent and 64 bit fraction (without implicit
1708
+ * bit) where the binary point is nominally at bit 52. Returns a
1709
+ * float64 which can then be rounded to the appropriate size by the
1710
+ * callee.
1711
+ */
1712
+
1713
+static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
1714
+{
1715
+ uint32_t scaled, estimate;
1716
+ uint64_t result_frac;
1717
+ int result_exp;
1718
+
1719
+ /* Handle sub-normals */
1720
+ if (*exp == 0) {
1721
+ if (extract64(frac, 51, 1) == 0) {
1722
+ *exp = -1;
1723
+ frac <<= 2;
1724
+ } else {
1725
+ frac <<= 1;
1726
+ }
1727
+ }
1728
+
1729
+ /* scaled = UInt('1':fraction<51:44>) */
1730
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1731
+ estimate = recip_estimate(scaled);
1732
+
1733
+ result_exp = exp_off - *exp;
1734
+ result_frac = deposit64(0, 44, 8, estimate);
1735
+ if (result_exp == 0) {
1736
+ result_frac = deposit64(result_frac >> 1, 51, 1, 1);
1737
+ } else if (result_exp == -1) {
1738
+ result_frac = deposit64(result_frac >> 2, 50, 2, 1);
1739
+ result_exp = 0;
1740
+ }
1741
+
1742
+ *exp = result_exp;
1743
+
1744
+ return result_frac;
1745
+}
1746
+
1747
+static bool round_to_inf(float_status *fpst, bool sign_bit)
1748
+{
1749
+ switch (fpst->float_rounding_mode) {
1750
+ case float_round_nearest_even: /* Round to Nearest */
1751
+ return true;
1752
+ case float_round_up: /* Round to +Inf */
1753
+ return !sign_bit;
1754
+ case float_round_down: /* Round to -Inf */
1755
+ return sign_bit;
1756
+ case float_round_to_zero: /* Round to Zero */
1757
+ return false;
1758
+ }
1759
+
1760
+ g_assert_not_reached();
1761
+}
1762
+
1763
+uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
1764
+{
1765
+ float_status *fpst = fpstp;
1766
+ float16 f16 = float16_squash_input_denormal(input, fpst);
1767
+ uint32_t f16_val = float16_val(f16);
1768
+ uint32_t f16_sign = float16_is_neg(f16);
1769
+ int f16_exp = extract32(f16_val, 10, 5);
1770
+ uint32_t f16_frac = extract32(f16_val, 0, 10);
1771
+ uint64_t f64_frac;
1772
+
1773
+ if (float16_is_any_nan(f16)) {
1774
+ float16 nan = f16;
1775
+ if (float16_is_signaling_nan(f16, fpst)) {
1776
+ float_raise(float_flag_invalid, fpst);
1777
+ nan = float16_silence_nan(f16, fpst);
1778
+ }
1779
+ if (fpst->default_nan_mode) {
1780
+ nan = float16_default_nan(fpst);
1781
+ }
1782
+ return nan;
1783
+ } else if (float16_is_infinity(f16)) {
1784
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
1785
+ } else if (float16_is_zero(f16)) {
1786
+ float_raise(float_flag_divbyzero, fpst);
1787
+ return float16_set_sign(float16_infinity, float16_is_neg(f16));
1788
+ } else if (float16_abs(f16) < (1 << 8)) {
1789
+ /* Abs(value) < 2.0^-16 */
1790
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1791
+ if (round_to_inf(fpst, f16_sign)) {
1792
+ return float16_set_sign(float16_infinity, f16_sign);
1793
+ } else {
1794
+ return float16_set_sign(float16_maxnorm, f16_sign);
1795
+ }
1796
+ } else if (f16_exp >= 29 && fpst->flush_to_zero) {
1797
+ float_raise(float_flag_underflow, fpst);
1798
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
1799
+ }
1800
+
1801
+ f64_frac = call_recip_estimate(&f16_exp, 29,
1802
+ ((uint64_t) f16_frac) << (52 - 10));
1803
+
1804
+ /* result = sign : result_exp<4:0> : fraction<51:42> */
1805
+ f16_val = deposit32(0, 15, 1, f16_sign);
1806
+ f16_val = deposit32(f16_val, 10, 5, f16_exp);
1807
+ f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
1808
+ return make_float16(f16_val);
1809
+}
1810
+
1811
+float32 HELPER(recpe_f32)(float32 input, void *fpstp)
1812
+{
1813
+ float_status *fpst = fpstp;
1814
+ float32 f32 = float32_squash_input_denormal(input, fpst);
1815
+ uint32_t f32_val = float32_val(f32);
1816
+ bool f32_sign = float32_is_neg(f32);
1817
+ int f32_exp = extract32(f32_val, 23, 8);
1818
+ uint32_t f32_frac = extract32(f32_val, 0, 23);
1819
+ uint64_t f64_frac;
1820
+
1821
+ if (float32_is_any_nan(f32)) {
1822
+ float32 nan = f32;
1823
+ if (float32_is_signaling_nan(f32, fpst)) {
1824
+ float_raise(float_flag_invalid, fpst);
1825
+ nan = float32_silence_nan(f32, fpst);
1826
+ }
1827
+ if (fpst->default_nan_mode) {
1828
+ nan = float32_default_nan(fpst);
1829
+ }
1830
+ return nan;
1831
+ } else if (float32_is_infinity(f32)) {
1832
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
1833
+ } else if (float32_is_zero(f32)) {
1834
+ float_raise(float_flag_divbyzero, fpst);
1835
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
1836
+ } else if (float32_abs(f32) < (1ULL << 21)) {
1837
+ /* Abs(value) < 2.0^-128 */
1838
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1839
+ if (round_to_inf(fpst, f32_sign)) {
1840
+ return float32_set_sign(float32_infinity, f32_sign);
1841
+ } else {
1842
+ return float32_set_sign(float32_maxnorm, f32_sign);
1843
+ }
1844
+ } else if (f32_exp >= 253 && fpst->flush_to_zero) {
1845
+ float_raise(float_flag_underflow, fpst);
1846
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
1847
+ }
1848
+
1849
+ f64_frac = call_recip_estimate(&f32_exp, 253,
1850
+ ((uint64_t) f32_frac) << (52 - 23));
1851
+
1852
+ /* result = sign : result_exp<7:0> : fraction<51:29> */
1853
+ f32_val = deposit32(0, 31, 1, f32_sign);
1854
+ f32_val = deposit32(f32_val, 23, 8, f32_exp);
1855
+ f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
1856
+ return make_float32(f32_val);
1857
+}
1858
+
1859
+float64 HELPER(recpe_f64)(float64 input, void *fpstp)
1860
+{
1861
+ float_status *fpst = fpstp;
1862
+ float64 f64 = float64_squash_input_denormal(input, fpst);
1863
+ uint64_t f64_val = float64_val(f64);
1864
+ bool f64_sign = float64_is_neg(f64);
1865
+ int f64_exp = extract64(f64_val, 52, 11);
1866
+ uint64_t f64_frac = extract64(f64_val, 0, 52);
1867
+
1868
+ /* Deal with any special cases */
1869
+ if (float64_is_any_nan(f64)) {
1870
+ float64 nan = f64;
1871
+ if (float64_is_signaling_nan(f64, fpst)) {
1872
+ float_raise(float_flag_invalid, fpst);
1873
+ nan = float64_silence_nan(f64, fpst);
1874
+ }
1875
+ if (fpst->default_nan_mode) {
1876
+ nan = float64_default_nan(fpst);
1877
+ }
1878
+ return nan;
1879
+ } else if (float64_is_infinity(f64)) {
1880
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
1881
+ } else if (float64_is_zero(f64)) {
1882
+ float_raise(float_flag_divbyzero, fpst);
1883
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
1884
+ } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
1885
+ /* Abs(value) < 2.0^-1024 */
1886
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1887
+ if (round_to_inf(fpst, f64_sign)) {
1888
+ return float64_set_sign(float64_infinity, f64_sign);
1889
+ } else {
1890
+ return float64_set_sign(float64_maxnorm, f64_sign);
1891
+ }
1892
+ } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
1893
+ float_raise(float_flag_underflow, fpst);
1894
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
1895
+ }
1896
+
1897
+ f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
1898
+
1899
+ /* result = sign : result_exp<10:0> : fraction<51:0>; */
1900
+ f64_val = deposit64(0, 63, 1, f64_sign);
1901
+ f64_val = deposit64(f64_val, 52, 11, f64_exp);
1902
+ f64_val = deposit64(f64_val, 0, 52, f64_frac);
1903
+ return make_float64(f64_val);
1904
+}
1905
+
1906
+/* The algorithm that must be used to calculate the estimate
1907
+ * is specified by the ARM ARM.
1908
+ */
1909
+
1910
+static int do_recip_sqrt_estimate(int a)
1911
+{
1912
+ int b, estimate;
1913
+
1914
+ assert(128 <= a && a < 512);
1915
+ if (a < 256) {
1916
+ a = a * 2 + 1;
1917
+ } else {
1918
+ a = (a >> 1) << 1;
1919
+ a = (a + 1) * 2;
1920
+ }
1921
+ b = 512;
1922
+ while (a * (b + 1) * (b + 1) < (1 << 28)) {
1923
+ b += 1;
1924
+ }
1925
+ estimate = (b + 1) / 2;
1926
+ assert(256 <= estimate && estimate < 512);
1927
+
1928
+ return estimate;
1929
+}
1930
+
1931
+
1932
+static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
1933
+{
1934
+ int estimate;
1935
+ uint32_t scaled;
1936
+
1937
+ if (*exp == 0) {
1938
+ while (extract64(frac, 51, 1) == 0) {
1939
+ frac = frac << 1;
1940
+ *exp -= 1;
1941
+ }
1942
+ frac = extract64(frac, 0, 51) << 1;
1943
+ }
1944
+
1945
+ if (*exp & 1) {
1946
+ /* scaled = UInt('01':fraction<51:45>) */
1947
+ scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
1948
+ } else {
1949
+ /* scaled = UInt('1':fraction<51:44>) */
1950
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1951
+ }
1952
+ estimate = do_recip_sqrt_estimate(scaled);
1953
+
1954
+ *exp = (exp_off - *exp) / 2;
1955
+ return extract64(estimate, 0, 8) << 44;
1956
+}
1957
+
1958
+uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
1959
+{
1960
+ float_status *s = fpstp;
1961
+ float16 f16 = float16_squash_input_denormal(input, s);
1962
+ uint16_t val = float16_val(f16);
1963
+ bool f16_sign = float16_is_neg(f16);
1964
+ int f16_exp = extract32(val, 10, 5);
1965
+ uint16_t f16_frac = extract32(val, 0, 10);
1966
+ uint64_t f64_frac;
1967
+
1968
+ if (float16_is_any_nan(f16)) {
1969
+ float16 nan = f16;
1970
+ if (float16_is_signaling_nan(f16, s)) {
1971
+ float_raise(float_flag_invalid, s);
1972
+ nan = float16_silence_nan(f16, s);
1973
+ }
1974
+ if (s->default_nan_mode) {
1975
+ nan = float16_default_nan(s);
1976
+ }
1977
+ return nan;
1978
+ } else if (float16_is_zero(f16)) {
1979
+ float_raise(float_flag_divbyzero, s);
1980
+ return float16_set_sign(float16_infinity, f16_sign);
1981
+ } else if (f16_sign) {
1982
+ float_raise(float_flag_invalid, s);
1983
+ return float16_default_nan(s);
1984
+ } else if (float16_is_infinity(f16)) {
1985
+ return float16_zero;
1986
+ }
1987
+
1988
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1989
+ * preserving the parity of the exponent. */
1990
+
1991
+ f64_frac = ((uint64_t) f16_frac) << (52 - 10);
1992
+
1993
+ f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
1994
+
1995
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
1996
+ val = deposit32(0, 15, 1, f16_sign);
1997
+ val = deposit32(val, 10, 5, f16_exp);
1998
+ val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
1999
+ return make_float16(val);
2000
+}
2001
+
2002
+float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
2003
+{
2004
+ float_status *s = fpstp;
2005
+ float32 f32 = float32_squash_input_denormal(input, s);
2006
+ uint32_t val = float32_val(f32);
2007
+ uint32_t f32_sign = float32_is_neg(f32);
2008
+ int f32_exp = extract32(val, 23, 8);
2009
+ uint32_t f32_frac = extract32(val, 0, 23);
2010
+ uint64_t f64_frac;
2011
+
2012
+ if (float32_is_any_nan(f32)) {
2013
+ float32 nan = f32;
2014
+ if (float32_is_signaling_nan(f32, s)) {
2015
+ float_raise(float_flag_invalid, s);
2016
+ nan = float32_silence_nan(f32, s);
2017
+ }
2018
+ if (s->default_nan_mode) {
2019
+ nan = float32_default_nan(s);
2020
+ }
2021
+ return nan;
2022
+ } else if (float32_is_zero(f32)) {
2023
+ float_raise(float_flag_divbyzero, s);
2024
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
2025
+ } else if (float32_is_neg(f32)) {
2026
+ float_raise(float_flag_invalid, s);
2027
+ return float32_default_nan(s);
2028
+ } else if (float32_is_infinity(f32)) {
2029
+ return float32_zero;
2030
+ }
2031
+
2032
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
2033
+ * preserving the parity of the exponent. */
2034
+
2035
+ f64_frac = ((uint64_t) f32_frac) << 29;
2036
+
2037
+ f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
2038
+
2039
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
2040
+ val = deposit32(0, 31, 1, f32_sign);
2041
+ val = deposit32(val, 23, 8, f32_exp);
2042
+ val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
2043
+ return make_float32(val);
2044
+}
2045
+
2046
+float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
2047
+{
2048
+ float_status *s = fpstp;
2049
+ float64 f64 = float64_squash_input_denormal(input, s);
2050
+ uint64_t val = float64_val(f64);
2051
+ bool f64_sign = float64_is_neg(f64);
2052
+ int f64_exp = extract64(val, 52, 11);
2053
+ uint64_t f64_frac = extract64(val, 0, 52);
2054
+
2055
+ if (float64_is_any_nan(f64)) {
2056
+ float64 nan = f64;
2057
+ if (float64_is_signaling_nan(f64, s)) {
2058
+ float_raise(float_flag_invalid, s);
2059
+ nan = float64_silence_nan(f64, s);
2060
+ }
2061
+ if (s->default_nan_mode) {
2062
+ nan = float64_default_nan(s);
2063
+ }
2064
+ return nan;
2065
+ } else if (float64_is_zero(f64)) {
2066
+ float_raise(float_flag_divbyzero, s);
2067
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
2068
+ } else if (float64_is_neg(f64)) {
2069
+ float_raise(float_flag_invalid, s);
2070
+ return float64_default_nan(s);
2071
+ } else if (float64_is_infinity(f64)) {
2072
+ return float64_zero;
2073
+ }
2074
+
2075
+ f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
2076
+
2077
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
2078
+ val = deposit64(0, 61, 1, f64_sign);
2079
+ val = deposit64(val, 52, 11, f64_exp);
2080
+ val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
2081
+ return make_float64(val);
2082
+}
2083
+
2084
+uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
2085
+{
2086
+ /* float_status *s = fpstp; */
2087
+ int input, estimate;
2088
+
2089
+ if ((a & 0x80000000) == 0) {
2090
+ return 0xffffffff;
2091
+ }
2092
+
2093
+ input = extract32(a, 23, 9);
2094
+ estimate = recip_estimate(input);
2095
+
2096
+ return deposit32(0, (32 - 9), 9, estimate);
2097
+}
2098
+
2099
+uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
2100
+{
2101
+ int estimate;
2102
+
2103
+ if ((a & 0xc0000000) == 0) {
2104
+ return 0xffffffff;
2105
+ }
2106
+
2107
+ estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
2108
+
2109
+ return deposit32(0, 23, 9, estimate);
2110
+}
2111
+
2112
+/* VFPv4 fused multiply-accumulate */
2113
+float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
2114
+{
2115
+ float_status *fpst = fpstp;
2116
+ return float32_muladd(a, b, c, 0, fpst);
2117
+}
2118
+
2119
+float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
2120
+{
2121
+ float_status *fpst = fpstp;
2122
+ return float64_muladd(a, b, c, 0, fpst);
2123
+}
2124
+
2125
+/* ARMv8 round to integral */
2126
+float32 HELPER(rints_exact)(float32 x, void *fp_status)
2127
+{
2128
+ return float32_round_to_int(x, fp_status);
2129
+}
2130
+
2131
+float64 HELPER(rintd_exact)(float64 x, void *fp_status)
2132
+{
2133
+ return float64_round_to_int(x, fp_status);
2134
+}
2135
+
2136
+float32 HELPER(rints)(float32 x, void *fp_status)
2137
+{
2138
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
2139
+ float32 ret;
2140
+
2141
+ ret = float32_round_to_int(x, fp_status);
2142
+
2143
+ /* Suppress any inexact exceptions the conversion produced */
2144
+ if (!(old_flags & float_flag_inexact)) {
2145
+ new_flags = get_float_exception_flags(fp_status);
2146
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
2147
+ }
2148
+
2149
+ return ret;
2150
+}
2151
+
2152
+float64 HELPER(rintd)(float64 x, void *fp_status)
2153
+{
2154
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
2155
+ float64 ret;
2156
+
2157
+ ret = float64_round_to_int(x, fp_status);
2158
+
2159
+ new_flags = get_float_exception_flags(fp_status);
2160
+
2161
+ /* Suppress any inexact exceptions the conversion produced */
2162
+ if (!(old_flags & float_flag_inexact)) {
2163
+ new_flags = get_float_exception_flags(fp_status);
2164
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
2165
+ }
2166
+
2167
+ return ret;
2168
+}
2169
+
2170
+/* Convert ARM rounding mode to softfloat */
2171
+int arm_rmode_to_sf(int rmode)
2172
+{
2173
+ switch (rmode) {
2174
+ case FPROUNDING_TIEAWAY:
2175
+ rmode = float_round_ties_away;
2176
+ break;
2177
+ case FPROUNDING_ODD:
2178
+ /* FIXME: add support for TIEAWAY and ODD */
2179
+ qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
2180
+ rmode);
2181
+ /* fall through for now */
2182
+ case FPROUNDING_TIEEVEN:
2183
+ default:
2184
+ rmode = float_round_nearest_even;
2185
+ break;
2186
+ case FPROUNDING_POSINF:
2187
+ rmode = float_round_up;
2188
+ break;
2189
+ case FPROUNDING_NEGINF:
2190
+ rmode = float_round_down;
2191
+ break;
2192
+ case FPROUNDING_ZERO:
2193
+ rmode = float_round_to_zero;
2194
+ break;
2195
+ }
2196
+ return rmode;
2197
+}
2198
--
1580
--
2199
2.20.1
1581
2.43.0
2200
2201
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
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
The move of the Kconfig bits to hw/gpio is fixing a bug in 6328d8ffa6cb9d
4
("misc/pca955*: Move models under hw/gpio"), which moved the code but forgot to
5
move the Kconfig sections.
6
7
Fixes: 6328d8ffa6cb9d "misc/pca955*: Move models under hw/gpio"
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20250223114708.1780-4-shentey@gmail.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/gpio/Kconfig | 8 ++++++++
14
hw/misc/Kconfig | 8 --------
15
2 files changed, 8 insertions(+), 8 deletions(-)
16
17
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/gpio/Kconfig
20
+++ b/hw/gpio/Kconfig
21
@@ -XXX,XX +XXX,XX @@ config SIFIVE_GPIO
22
config STM32L4X5_GPIO
23
bool
24
25
+config PCA9552
26
+ bool
27
+ depends on I2C
28
+
29
+config PCA9554
30
+ bool
31
+ depends on I2C
32
+
33
config PCF8574
34
bool
35
depends on I2C
36
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/misc/Kconfig
39
+++ b/hw/misc/Kconfig
40
@@ -XXX,XX +XXX,XX @@ config EDU
41
default y if TEST_DEVICES
42
depends on PCI && MSI_NONBROKEN
43
44
-config PCA9552
45
- bool
46
- depends on I2C
47
-
48
-config PCA9554
49
- bool
50
- depends on I2C
51
-
52
config I2C_ECHO
53
bool
54
default y if TEST_DEVICES
55
--
56
2.43.0
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: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
There are lots of special cases within these insns. Split the
3
Fixes quite a few stack traces during the Linux boot process. Also provides the
4
major argument decode/loading/saving into no_output (compares),
4
clocks for devices added later, e.g. enet1.
5
rd_is_dp, and rm_is_dp.
6
5
7
We still need to special case argument load for compare (rd as
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
input, rm as zero) and vcvt fixed (rd as input+output), but lots
7
Message-id: 20250223114708.1780-6-shentey@gmail.com
9
of special cases do disappear.
10
11
Now that we have a full switch at the beginning, hoist the ISA
12
checks from the code generation.
13
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190215192302.27855-4-richard.henderson@linaro.org
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
10
---
19
target/arm/translate.c | 227 ++++++++++++++++++++---------------------
11
MAINTAINERS | 2 +
20
1 file changed, 111 insertions(+), 116 deletions(-)
12
docs/system/arm/imx8mp-evk.rst | 1 +
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
21
27
22
diff --git a/target/arm/translate.c b/target/arm/translate.c
28
diff --git a/MAINTAINERS b/MAINTAINERS
23
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/translate.c
30
--- a/MAINTAINERS
25
+++ b/target/arm/translate.c
31
+++ b/MAINTAINERS
26
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
32
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
27
}
33
S: Maintained
28
} else {
34
F: hw/arm/imx8mp-evk.c
29
/* data processing */
35
F: hw/arm/fsl-imx8mp.c
30
+ bool rd_is_dp = dp;
36
+F: hw/misc/imx8mp_*.c
31
+ bool rm_is_dp = dp;
37
F: include/hw/arm/fsl-imx8mp.h
32
+ bool no_output = false;
38
+F: include/hw/misc/imx8mp_*.h
33
+
39
F: docs/system/arm/imx8mp-evk.rst
34
/* The opcode is in bits 23, 21, 20 and 6. */
40
35
op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
41
MPS2 / MPS3
36
- if (dp) {
42
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
37
- if (op == 15) {
43
index XXXXXXX..XXXXXXX 100644
38
- /* rn is opcode */
44
--- a/docs/system/arm/imx8mp-evk.rst
39
- rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
45
+++ b/docs/system/arm/imx8mp-evk.rst
40
- } else {
46
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
41
- /* rn is register number */
47
* Up to 4 Cortex-A53 cores
42
- VFP_DREG_N(rn, insn);
48
* Generic Interrupt Controller (GICv3)
43
- }
49
* 4 UARTs
44
+ rn = VFP_SREG_N(insn);
50
+ * Clock Tree
45
51
46
- if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
52
Boot options
47
- ((rn & 0x1e) == 0x6))) {
53
------------
48
- /* Integer or single/half precision destination. */
54
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
49
- rd = VFP_SREG_D(insn);
55
index XXXXXXX..XXXXXXX 100644
50
- } else {
56
--- a/include/hw/arm/fsl-imx8mp.h
51
- VFP_DREG_D(rd, insn);
57
+++ b/include/hw/arm/fsl-imx8mp.h
52
- }
58
@@ -XXX,XX +XXX,XX @@
53
- if (op == 15 &&
59
#include "cpu.h"
54
- (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
60
#include "hw/char/imx_serial.h"
55
- ((rn & 0x1e) == 0x4))) {
61
#include "hw/intc/arm_gicv3_common.h"
56
- /* VCVT from int or half precision is always from S reg
62
+#include "hw/misc/imx8mp_analog.h"
57
- * regardless of dp bit. VCVT with immediate frac_bits
63
+#include "hw/misc/imx8mp_ccm.h"
58
- * has same format as SREG_M.
64
#include "qom/object.h"
59
+ if (op == 15) {
65
#include "qemu/units.h"
60
+ /* rn is opcode, encoded as per VFP_SREG_N. */
66
61
+ switch (rn) {
67
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
62
+ case 0x00: /* vmov */
68
63
+ case 0x01: /* vabs */
69
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
64
+ case 0x02: /* vneg */
70
GICv3State gic;
65
+ case 0x03: /* vsqrt */
71
+ IMX8MPCCMState ccm;
66
+ break;
72
+ IMX8MPAnalogState analog;
67
+
73
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
68
+ case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
74
};
69
+ case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
75
70
+ /*
76
diff --git a/include/hw/misc/imx8mp_analog.h b/include/hw/misc/imx8mp_analog.h
71
+ * VCVTB, VCVTT: only present with the halfprec extension
77
new file mode 100644
72
+ * UNPREDICTABLE if bit 8 is set prior to ARMv8
78
index XXXXXXX..XXXXXXX
73
+ * (we choose to UNDEF)
79
--- /dev/null
74
*/
80
+++ b/include/hw/misc/imx8mp_analog.h
75
- rm = VFP_SREG_M(insn);
81
@@ -XXX,XX +XXX,XX @@
76
- } else {
82
+/*
77
- VFP_DREG_M(rm, insn);
83
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
78
+ if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
84
+ *
79
+ !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
85
+ * i.MX8MP ANALOG IP block emulation code
80
+ return 1;
86
+ *
81
+ }
87
+ * SPDX-License-Identifier: GPL-2.0-or-later
82
+ rm_is_dp = false;
88
+ */
83
+ break;
89
+
84
+ case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
90
+#ifndef IMX8MP_ANALOG_H
85
+ case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
91
+#define IMX8MP_ANALOG_H
86
+ if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
92
+
87
+ !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
93
+#include "qom/object.h"
88
+ return 1;
94
+#include "hw/sysbus.h"
89
+ }
95
+
90
+ rd_is_dp = false;
96
+enum IMX8MPAnalogRegisters {
91
+ break;
97
+ ANALOG_AUDIO_PLL1_GEN_CTRL = 0x000 / 4,
92
+
98
+ ANALOG_AUDIO_PLL1_FDIV_CTL0 = 0x004 / 4,
93
+ case 0x08: case 0x0a: /* vcmp, vcmpz */
99
+ ANALOG_AUDIO_PLL1_FDIV_CTL1 = 0x008 / 4,
94
+ case 0x09: case 0x0b: /* vcmpe, vcmpez */
100
+ ANALOG_AUDIO_PLL1_SSCG_CTRL = 0x00c / 4,
95
+ no_output = true;
101
+ ANALOG_AUDIO_PLL1_MNIT_CTRL = 0x010 / 4,
96
+ break;
102
+ ANALOG_AUDIO_PLL2_GEN_CTRL = 0x014 / 4,
97
+
103
+ ANALOG_AUDIO_PLL2_FDIV_CTL0 = 0x018 / 4,
98
+ case 0x0c: /* vrintr */
104
+ ANALOG_AUDIO_PLL2_FDIV_CTL1 = 0x01c / 4,
99
+ case 0x0d: /* vrintz */
105
+ ANALOG_AUDIO_PLL2_SSCG_CTRL = 0x020 / 4,
100
+ case 0x0e: /* vrintx */
106
+ ANALOG_AUDIO_PLL2_MNIT_CTRL = 0x024 / 4,
101
+ break;
107
+ ANALOG_VIDEO_PLL1_GEN_CTRL = 0x028 / 4,
102
+
108
+ ANALOG_VIDEO_PLL1_FDIV_CTL0 = 0x02c / 4,
103
+ case 0x0f: /* vcvt double<->single */
109
+ ANALOG_VIDEO_PLL1_FDIV_CTL1 = 0x030 / 4,
104
+ rd_is_dp = !dp;
110
+ ANALOG_VIDEO_PLL1_SSCG_CTRL = 0x034 / 4,
105
+ break;
111
+ ANALOG_VIDEO_PLL1_MNIT_CTRL = 0x038 / 4,
106
+
112
+ ANALOG_DRAM_PLL_GEN_CTRL = 0x050 / 4,
107
+ case 0x10: /* vcvt.fxx.u32 */
113
+ ANALOG_DRAM_PLL_FDIV_CTL0 = 0x054 / 4,
108
+ case 0x11: /* vcvt.fxx.s32 */
114
+ ANALOG_DRAM_PLL_FDIV_CTL1 = 0x058 / 4,
109
+ rm_is_dp = false;
115
+ ANALOG_DRAM_PLL_SSCG_CTRL = 0x05c / 4,
110
+ break;
116
+ ANALOG_DRAM_PLL_MNIT_CTRL = 0x060 / 4,
111
+ case 0x18: /* vcvtr.u32.fxx */
117
+ ANALOG_GPU_PLL_GEN_CTRL = 0x064 / 4,
112
+ case 0x19: /* vcvtz.u32.fxx */
118
+ ANALOG_GPU_PLL_FDIV_CTL0 = 0x068 / 4,
113
+ case 0x1a: /* vcvtr.s32.fxx */
119
+ ANALOG_GPU_PLL_LOCKD_CTRL = 0x06c / 4,
114
+ case 0x1b: /* vcvtz.s32.fxx */
120
+ ANALOG_GPU_PLL_MNIT_CTRL = 0x070 / 4,
115
+ rd_is_dp = false;
121
+ ANALOG_VPU_PLL_GEN_CTRL = 0x074 / 4,
116
+ break;
122
+ ANALOG_VPU_PLL_FDIV_CTL0 = 0x078 / 4,
117
+
123
+ ANALOG_VPU_PLL_LOCKD_CTRL = 0x07c / 4,
118
+ case 0x14: /* vcvt fp <-> fixed */
124
+ ANALOG_VPU_PLL_MNIT_CTRL = 0x080 / 4,
119
+ case 0x15:
125
+ ANALOG_ARM_PLL_GEN_CTRL = 0x084 / 4,
120
+ case 0x16:
126
+ ANALOG_ARM_PLL_FDIV_CTL0 = 0x088 / 4,
121
+ case 0x17:
127
+ ANALOG_ARM_PLL_LOCKD_CTRL = 0x08c / 4,
122
+ case 0x1c:
128
+ ANALOG_ARM_PLL_MNIT_CTRL = 0x090 / 4,
123
+ case 0x1d:
129
+ ANALOG_SYS_PLL1_GEN_CTRL = 0x094 / 4,
124
+ case 0x1e:
130
+ ANALOG_SYS_PLL1_FDIV_CTL0 = 0x098 / 4,
125
+ case 0x1f:
131
+ ANALOG_SYS_PLL1_LOCKD_CTRL = 0x09c / 4,
126
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
132
+ ANALOG_SYS_PLL1_MNIT_CTRL = 0x100 / 4,
127
+ return 1;
133
+ ANALOG_SYS_PLL2_GEN_CTRL = 0x104 / 4,
128
+ }
134
+ ANALOG_SYS_PLL2_FDIV_CTL0 = 0x108 / 4,
129
+ /* Immediate frac_bits has same format as SREG_M. */
135
+ ANALOG_SYS_PLL2_LOCKD_CTRL = 0x10c / 4,
130
+ rm_is_dp = false;
136
+ ANALOG_SYS_PLL2_MNIT_CTRL = 0x110 / 4,
131
+ break;
137
+ ANALOG_SYS_PLL3_GEN_CTRL = 0x114 / 4,
132
+
138
+ ANALOG_SYS_PLL3_FDIV_CTL0 = 0x118 / 4,
133
+ default:
139
+ ANALOG_SYS_PLL3_LOCKD_CTRL = 0x11c / 4,
134
+ return 1;
140
+ ANALOG_SYS_PLL3_MNIT_CTRL = 0x120 / 4,
135
}
141
+ ANALOG_OSC_MISC_CFG = 0x124 / 4,
136
+ } else if (dp) {
142
+ ANALOG_ANAMIX_PLL_MNIT_CTL = 0x128 / 4,
137
+ /* rn is register number */
143
+
138
+ VFP_DREG_N(rn, insn);
144
+ ANALOG_DIGPROG = 0x800 / 4,
139
+ }
145
+ ANALOG_MAX,
140
+
146
+};
141
+ if (rd_is_dp) {
147
+
142
+ VFP_DREG_D(rd, insn);
148
+#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
143
+ } else {
149
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
144
+ rd = VFP_SREG_D(insn);
150
+
145
+ }
151
+struct IMX8MPAnalogState {
146
+ if (rm_is_dp) {
152
+ SysBusDevice parent_obj;
147
+ VFP_DREG_M(rm, insn);
153
+
148
} else {
154
+ struct {
149
- rn = VFP_SREG_N(insn);
155
+ MemoryRegion container;
150
- if (op == 15 && rn == 15) {
156
+ MemoryRegion analog;
151
- /* Double precision destination. */
157
+ } mmio;
152
- VFP_DREG_D(rd, insn);
158
+
153
- } else {
159
+ uint32_t analog[ANALOG_MAX];
154
- rd = VFP_SREG_D(insn);
160
+};
155
- }
161
+
156
- /* NB that we implicitly rely on the encoding for the frac_bits
162
+#endif /* IMX8MP_ANALOG_H */
157
- * in VCVT of fixed to float being the same as that of an SREG_M
163
diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
158
- */
164
new file mode 100644
159
rm = VFP_SREG_M(insn);
165
index XXXXXXX..XXXXXXX
160
}
166
--- /dev/null
161
167
+++ b/include/hw/misc/imx8mp_ccm.h
162
veclen = s->vec_len;
168
@@ -XXX,XX +XXX,XX @@
163
- if (op == 15 && rn > 3)
169
+/*
164
+ if (op == 15 && rn > 3) {
170
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
165
veclen = 0;
171
+ *
166
+ }
172
+ * i.MX 8M Plus CCM IP block emulation code
167
173
+ *
168
/* Shut up compiler warnings. */
174
+ * SPDX-License-Identifier: GPL-2.0-or-later
169
delta_m = 0;
175
+ */
170
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
176
+
171
/* Load the initial operands. */
177
+#ifndef IMX8MP_CCM_H
172
if (op == 15) {
178
+#define IMX8MP_CCM_H
173
switch (rn) {
179
+
174
- case 16:
180
+#include "hw/misc/imx_ccm.h"
175
- case 17:
181
+#include "qom/object.h"
176
- /* Integer source */
182
+
177
- gen_mov_F0_vreg(0, rm);
183
+enum IMX8MPCCMRegisters {
178
- break;
184
+ CCM_MAX = 0xc6fc / sizeof(uint32_t) + 1,
179
- case 8:
185
+};
180
- case 9:
186
+
181
- /* Compare */
187
+#define TYPE_IMX8MP_CCM "imx8mp.ccm"
182
+ case 0x08: case 0x09: /* Compare */
188
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPCCMState, IMX8MP_CCM)
183
gen_mov_F0_vreg(dp, rd);
189
+
184
gen_mov_F1_vreg(dp, rm);
190
+struct IMX8MPCCMState {
185
break;
191
+ IMXCCMState parent_obj;
186
- case 10:
192
+
187
- case 11:
193
+ MemoryRegion iomem;
188
- /* Compare with zero */
194
+
189
+ case 0x0a: case 0x0b: /* Compare with zero */
195
+ uint32_t ccm[CCM_MAX];
190
gen_mov_F0_vreg(dp, rd);
196
+};
191
gen_vfp_F1_ld0(dp);
197
+
192
break;
198
+#endif /* IMX8MP_CCM_H */
193
- case 20:
199
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
194
- case 21:
200
index XXXXXXX..XXXXXXX 100644
195
- case 22:
201
--- a/hw/arm/fsl-imx8mp.c
196
- case 23:
202
+++ b/hw/arm/fsl-imx8mp.c
197
- case 28:
203
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
198
- case 29:
204
199
- case 30:
205
object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
200
- case 31:
206
201
+ case 0x14: /* vcvt fp <-> fixed */
207
+ object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
202
+ case 0x15:
208
+
203
+ case 0x16:
209
+ object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
204
+ case 0x17:
210
+
205
+ case 0x1c:
211
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
206
+ case 0x1d:
212
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
207
+ case 0x1e:
213
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
208
+ case 0x1f:
214
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
209
/* Source and destination the same. */
215
}
210
gen_mov_F0_vreg(dp, rd);
216
}
211
break;
217
212
- case 4:
218
+ /* CCM */
213
- case 5:
219
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
214
- case 6:
220
+ return;
215
- case 7:
221
+ }
216
- /* VCVTB, VCVTT: only present with the halfprec extension
222
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
217
- * UNPREDICTABLE if bit 8 is set prior to ARMv8
223
+ fsl_imx8mp_memmap[FSL_IMX8MP_CCM].addr);
218
- * (we choose to UNDEF)
224
+
219
- */
225
+ /* Analog */
220
- if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
226
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
221
- !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
227
+ return;
222
- return 1;
228
+ }
223
- }
229
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
224
- if (!extract32(rn, 1, 1)) {
230
+ fsl_imx8mp_memmap[FSL_IMX8MP_ANA_PLL].addr);
225
- /* Half precision source. */
231
+
226
- gen_mov_F0_vreg(0, rm);
232
/* UARTs */
227
- break;
233
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
228
- }
234
struct {
229
- /* Otherwise fall through */
235
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
230
default:
236
/* Unimplemented devices */
231
/* One source operand. */
237
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
232
- gen_mov_F0_vreg(dp, rm);
238
switch (i) {
233
+ gen_mov_F0_vreg(rm_is_dp, rm);
239
+ case FSL_IMX8MP_ANA_PLL:
234
break;
240
+ case FSL_IMX8MP_CCM:
235
}
241
case FSL_IMX8MP_GIC_DIST:
236
} else {
242
case FSL_IMX8MP_GIC_REDIST:
237
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
243
case FSL_IMX8MP_RAM:
238
break;
244
diff --git a/hw/misc/imx8mp_analog.c b/hw/misc/imx8mp_analog.c
239
}
245
new file mode 100644
240
case 15: /* single<->double conversion */
246
index XXXXXXX..XXXXXXX
241
- if (dp)
247
--- /dev/null
242
+ if (dp) {
248
+++ b/hw/misc/imx8mp_analog.c
243
gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
249
@@ -XXX,XX +XXX,XX @@
244
- else
250
+/*
245
+ } else {
251
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
246
gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
252
+ *
247
+ }
253
+ * i.MX 8M Plus ANALOG IP block emulation code
248
break;
254
+ *
249
case 16: /* fuito */
255
+ * Based on hw/misc/imx7_ccm.c
250
gen_vfp_uito(dp, 0);
256
+ *
251
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
257
+ * SPDX-License-Identifier: GPL-2.0-or-later
252
gen_vfp_sito(dp, 0);
258
+ */
253
break;
259
+
254
case 20: /* fshto */
260
+#include "qemu/osdep.h"
255
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
261
+#include "qemu/log.h"
256
- return 1;
262
+
257
- }
263
+#include "hw/misc/imx8mp_analog.h"
258
gen_vfp_shto(dp, 16 - rm, 0);
264
+#include "migration/vmstate.h"
259
break;
265
+
260
case 21: /* fslto */
266
+#define ANALOG_PLL_LOCK BIT(31)
261
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
267
+
262
- return 1;
268
+static void imx8mp_analog_reset(DeviceState *dev)
263
- }
269
+{
264
gen_vfp_slto(dp, 32 - rm, 0);
270
+ IMX8MPAnalogState *s = IMX8MP_ANALOG(dev);
265
break;
271
+
266
case 22: /* fuhto */
272
+ memset(s->analog, 0, sizeof(s->analog));
267
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
273
+
268
- return 1;
274
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] = 0x00002010;
269
- }
275
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL0] = 0x00145032;
270
gen_vfp_uhto(dp, 16 - rm, 0);
276
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL1] = 0x00000000;
271
break;
277
+ s->analog[ANALOG_AUDIO_PLL1_SSCG_CTRL] = 0x00000000;
272
case 23: /* fulto */
278
+ s->analog[ANALOG_AUDIO_PLL1_MNIT_CTRL] = 0x00100103;
273
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
279
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] = 0x00002010;
274
- return 1;
280
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL0] = 0x00145032;
275
- }
281
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL1] = 0x00000000;
276
gen_vfp_ulto(dp, 32 - rm, 0);
282
+ s->analog[ANALOG_AUDIO_PLL2_SSCG_CTRL] = 0x00000000;
277
break;
283
+ s->analog[ANALOG_AUDIO_PLL2_MNIT_CTRL] = 0x00100103;
278
case 24: /* ftoui */
284
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] = 0x00002010;
279
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
285
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL0] = 0x00145032;
280
gen_vfp_tosiz(dp, 0);
286
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL1] = 0x00000000;
281
break;
287
+ s->analog[ANALOG_VIDEO_PLL1_SSCG_CTRL] = 0x00000000;
282
case 28: /* ftosh */
288
+ s->analog[ANALOG_VIDEO_PLL1_MNIT_CTRL] = 0x00100103;
283
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
289
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] = 0x00002010;
284
- return 1;
290
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL0] = 0x0012c032;
285
- }
291
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL1] = 0x00000000;
286
gen_vfp_tosh(dp, 16 - rm, 0);
292
+ s->analog[ANALOG_DRAM_PLL_SSCG_CTRL] = 0x00000000;
287
break;
293
+ s->analog[ANALOG_DRAM_PLL_MNIT_CTRL] = 0x00100103;
288
case 29: /* ftosl */
294
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] = 0x00000810;
289
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
295
+ s->analog[ANALOG_GPU_PLL_FDIV_CTL0] = 0x000c8031;
290
- return 1;
296
+ s->analog[ANALOG_GPU_PLL_LOCKD_CTRL] = 0x0010003f;
291
- }
297
+ s->analog[ANALOG_GPU_PLL_MNIT_CTRL] = 0x00280081;
292
gen_vfp_tosl(dp, 32 - rm, 0);
298
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] = 0x00000810;
293
break;
299
+ s->analog[ANALOG_VPU_PLL_FDIV_CTL0] = 0x0012c032;
294
case 30: /* ftouh */
300
+ s->analog[ANALOG_VPU_PLL_LOCKD_CTRL] = 0x0010003f;
295
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
301
+ s->analog[ANALOG_VPU_PLL_MNIT_CTRL] = 0x00280081;
296
- return 1;
302
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] = 0x00000810;
297
- }
303
+ s->analog[ANALOG_ARM_PLL_FDIV_CTL0] = 0x000fa031;
298
gen_vfp_touh(dp, 16 - rm, 0);
304
+ s->analog[ANALOG_ARM_PLL_LOCKD_CTRL] = 0x0010003f;
299
break;
305
+ s->analog[ANALOG_ARM_PLL_MNIT_CTRL] = 0x00280081;
300
case 31: /* ftoul */
306
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] = 0x0aaaa810;
301
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
307
+ s->analog[ANALOG_SYS_PLL1_FDIV_CTL0] = 0x00190032;
302
- return 1;
308
+ s->analog[ANALOG_SYS_PLL1_LOCKD_CTRL] = 0x0010003f;
303
- }
309
+ s->analog[ANALOG_SYS_PLL1_MNIT_CTRL] = 0x00280081;
304
gen_vfp_toul(dp, 32 - rm, 0);
310
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] = 0x0aaaa810;
305
break;
311
+ s->analog[ANALOG_SYS_PLL2_FDIV_CTL0] = 0x000fa031;
306
default: /* undefined */
312
+ s->analog[ANALOG_SYS_PLL2_LOCKD_CTRL] = 0x0010003f;
307
- return 1;
313
+ s->analog[ANALOG_SYS_PLL2_MNIT_CTRL] = 0x00280081;
308
+ g_assert_not_reached();
314
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] = 0x00000810;
309
}
315
+ s->analog[ANALOG_SYS_PLL3_FDIV_CTL0] = 0x000fa031;
310
break;
316
+ s->analog[ANALOG_SYS_PLL3_LOCKD_CTRL] = 0x0010003f;
311
default: /* undefined */
317
+ s->analog[ANALOG_SYS_PLL3_MNIT_CTRL] = 0x00280081;
312
return 1;
318
+ s->analog[ANALOG_OSC_MISC_CFG] = 0x00000000;
313
}
319
+ s->analog[ANALOG_ANAMIX_PLL_MNIT_CTL] = 0x00000000;
314
320
+ s->analog[ANALOG_DIGPROG] = 0x00824010;
315
- /* Write back the result. */
321
+
316
- if (op == 15 && (rn >= 8 && rn <= 11)) {
322
+ /* all PLLs need to be locked */
317
- /* Comparison, do nothing. */
323
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
318
- } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
324
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
319
- (rn & 0x1e) == 0x6)) {
325
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
320
- /* VCVT double to int: always integer result.
326
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
321
- * VCVT double to half precision is always a single
327
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
322
- * precision result.
328
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
323
- */
329
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
324
- gen_mov_vreg_F0(0, rd);
330
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
325
- } else if (op == 15 && rn == 15) {
331
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
326
- /* conversion */
332
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] |= ANALOG_PLL_LOCK;
327
- gen_mov_vreg_F0(!dp, rd);
333
+}
328
- } else {
334
+
329
- gen_mov_vreg_F0(dp, rd);
335
+static uint64_t imx8mp_analog_read(void *opaque, hwaddr offset, unsigned size)
330
+ /* Write back the result, if any. */
336
+{
331
+ if (!no_output) {
337
+ IMX8MPAnalogState *s = opaque;
332
+ gen_mov_vreg_F0(rd_is_dp, rd);
338
+
333
}
339
+ return s->analog[offset >> 2];
334
340
+}
335
/* break out of the loop if we have finished */
341
+
336
- if (veclen == 0)
342
+static void imx8mp_analog_write(void *opaque, hwaddr offset,
337
+ if (veclen == 0) {
343
+ uint64_t value, unsigned size)
338
break;
344
+{
339
+ }
345
+ IMX8MPAnalogState *s = opaque;
340
346
+
341
if (op == 15 && delta_m == 0) {
347
+ if (offset >> 2 == ANALOG_DIGPROG) {
342
/* single source one-many */
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
+{
528
+ /*
529
+ * This function is "consumed" by GPT emulation code. Some clocks
530
+ * have fixed frequencies and we can provide requested frequency
531
+ * easily. However for CCM provided clocks (like IPG) each GPT
532
+ * timer can have its own clock root.
533
+ * This means we need additional information when calling this
534
+ * function to know the requester's identity.
535
+ */
536
+ uint32_t freq = 0;
537
+
538
+ switch (clock) {
539
+ case CLK_NONE:
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',
343
--
634
--
344
2.20.1
635
2.43.0
345
346
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
The Musca-A and Musca-B1 development boards are based on the
1
From: Bernhard Beschow <shentey@gmail.com>
2
SSE-200 subsystem for embedded. Implement an initial skeleton
3
model of these boards, which are similar but not identical.
4
2
5
This commit creates the board model with the SSE and the IRQ
3
Linux checks for the PLLs in the PHY to be locked, so implement a model
6
splitters to wire IRQs up to its two CPUs. As yet there
4
emulating that.
7
are no devices and no memory: these will be added later.
8
5
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Message-id: 20250223114708.1780-9-shentey@gmail.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
10
---
12
hw/arm/Makefile.objs | 1 +
11
MAINTAINERS | 2 +
13
hw/arm/musca.c | 197 ++++++++++++++++++++++++++++++++
12
docs/system/arm/imx8mp-evk.rst | 1 +
14
MAINTAINERS | 6 +
13
include/hw/arm/fsl-imx8mp.h | 10 +++
15
default-configs/arm-softmmu.mak | 1 +
14
include/hw/pci-host/fsl_imx8m_phy.h | 28 +++++++++
16
4 files changed, 205 insertions(+)
15
hw/arm/fsl-imx8mp.c | 30 +++++++++
17
create mode 100644 hw/arm/musca.c
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
18
23
19
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
24
diff --git a/MAINTAINERS b/MAINTAINERS
20
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/Makefile.objs
26
--- a/MAINTAINERS
22
+++ b/hw/arm/Makefile.objs
27
+++ b/MAINTAINERS
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
28
@@ -XXX,XX +XXX,XX @@ S: Maintained
24
obj-$(CONFIG_MPS2) += mps2.o
29
F: hw/arm/imx8mp-evk.c
25
obj-$(CONFIG_MPS2) += mps2-tz.o
30
F: hw/arm/fsl-imx8mp.c
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
31
F: hw/misc/imx8mp_*.c
27
+obj-$(CONFIG_MUSCA) += musca.o
32
+F: hw/pci-host/fsl_imx8m_phy.c
28
obj-$(CONFIG_ARMSSE) += armsse.o
33
F: include/hw/arm/fsl-imx8mp.h
29
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
34
F: include/hw/misc/imx8mp_*.h
30
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
35
+F: include/hw/pci-host/fsl_imx8m_phy.h
31
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
36
F: docs/system/arm/imx8mp-evk.rst
37
38
MPS2 / MPS3
39
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
40
index XXXXXXX..XXXXXXX 100644
41
--- a/docs/system/arm/imx8mp-evk.rst
42
+++ b/docs/system/arm/imx8mp-evk.rst
43
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
44
* Generic Interrupt Controller (GICv3)
45
* 4 UARTs
46
* 3 USDHC Storage Controllers
47
+ * 1 Designware PCI Express Controller
48
* Secure Non-Volatile Storage (SNVS) including an RTC
49
* Clock Tree
50
51
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/include/hw/arm/fsl-imx8mp.h
54
+++ b/include/hw/arm/fsl-imx8mp.h
55
@@ -XXX,XX +XXX,XX @@
56
#include "hw/misc/imx7_snvs.h"
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
32
new file mode 100644
87
new file mode 100644
33
index XXXXXXX..XXXXXXX
88
index XXXXXXX..XXXXXXX
34
--- /dev/null
89
--- /dev/null
35
+++ b/hw/arm/musca.c
90
+++ b/include/hw/pci-host/fsl_imx8m_phy.h
36
@@ -XXX,XX +XXX,XX @@
91
@@ -XXX,XX +XXX,XX @@
37
+/*
92
+/*
38
+ * Arm Musca-B1 test chip board emulation
93
+ * i.MX8 PCIe PHY emulation
39
+ *
94
+ *
40
+ * Copyright (c) 2019 Linaro Limited
95
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
41
+ * Written by Peter Maydell
42
+ *
96
+ *
43
+ * This program is free software; you can redistribute it and/or modify
97
+ * SPDX-License-Identifier: GPL-2.0-or-later
44
+ * it under the terms of the GNU General Public License version 2 or
45
+ * (at your option) any later version.
46
+ */
98
+ */
47
+
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);
132
}
133
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 @@
48
+/*
181
+/*
49
+ * The Musca boards are a reference implementation of a system using
182
+ * i.MX8 PCIe PHY emulation
50
+ * the SSE-200 subsystem for embedded:
183
+ *
51
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-a-test-chip-board
184
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
52
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board
185
+ *
53
+ * We model the A and B1 variants of this board, as described in the TRMs:
186
+ * SPDX-License-Identifier: GPL-2.0-or-later
54
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101107_0000_00_en/index.html
55
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101312_0000_00_en/index.html
56
+ */
187
+ */
57
+
188
+
58
+#include "qemu/osdep.h"
189
+#include "qemu/osdep.h"
59
+#include "qemu/error-report.h"
190
+#include "hw/pci-host/fsl_imx8m_phy.h"
60
+#include "qapi/error.h"
191
+#include "hw/resettable.h"
61
+#include "exec/address-spaces.h"
192
+#include "migration/vmstate.h"
62
+#include "hw/arm/arm.h"
193
+
63
+#include "hw/arm/armsse.h"
194
+#define CMN_REG075 0x1d4
64
+#include "hw/boards.h"
195
+#define ANA_PLL_LOCK_DONE BIT(1)
65
+#include "hw/core/split-irq.h"
196
+#define ANA_PLL_AFC_DONE BIT(0)
66
+
197
+
67
+#define MUSCA_NUMIRQ_MAX 96
198
+static uint64_t fsl_imx8m_pcie_phy_read(void *opaque, hwaddr offset,
68
+
199
+ unsigned size)
69
+typedef enum MuscaType {
200
+{
70
+ MUSCA_A,
201
+ FslImx8mPciePhyState *s = opaque;
71
+ MUSCA_B1,
202
+
72
+} MuscaType;
203
+ if (offset == CMN_REG075) {
73
+
204
+ return s->data[offset] | ANA_PLL_LOCK_DONE | ANA_PLL_AFC_DONE;
74
+typedef struct {
205
+ }
75
+ MachineClass parent;
206
+
76
+ MuscaType type;
207
+ return s->data[offset];
77
+ uint32_t init_svtor;
208
+}
78
+ int sram_addr_width;
209
+
79
+ int num_irqs;
210
+static void fsl_imx8m_pcie_phy_write(void *opaque, hwaddr offset,
80
+} MuscaMachineClass;
211
+ uint64_t value, unsigned size)
81
+
212
+{
82
+typedef struct {
213
+ FslImx8mPciePhyState *s = opaque;
83
+ MachineState parent;
214
+
84
+
215
+ s->data[offset] = value;
85
+ ARMSSE sse;
216
+}
86
+ SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
217
+
87
+} MuscaMachineState;
218
+static const MemoryRegionOps fsl_imx8m_pcie_phy_ops = {
88
+
219
+ .read = fsl_imx8m_pcie_phy_read,
89
+#define TYPE_MUSCA_MACHINE "musca"
220
+ .write = fsl_imx8m_pcie_phy_write,
90
+#define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a")
221
+ .impl = {
91
+#define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1")
222
+ .min_access_size = 1,
92
+
223
+ .max_access_size = 1,
93
+#define MUSCA_MACHINE(obj) \
224
+ },
94
+ OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE)
225
+ .valid = {
95
+#define MUSCA_MACHINE_GET_CLASS(obj) \
226
+ .min_access_size = 1,
96
+ OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE)
227
+ .max_access_size = 8,
97
+#define MUSCA_MACHINE_CLASS(klass) \
228
+ },
98
+ OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE)
229
+ .endianness = DEVICE_LITTLE_ENDIAN,
99
+
100
+/*
101
+ * Main SYSCLK frequency in Hz
102
+ * TODO this should really be different for the two cores, but we
103
+ * don't model that in our SSE-200 model yet.
104
+ */
105
+#define SYSCLK_FRQ 40000000
106
+
107
+static void musca_init(MachineState *machine)
108
+{
109
+ MuscaMachineState *mms = MUSCA_MACHINE(machine);
110
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
111
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
112
+ MemoryRegion *system_memory = get_system_memory();
113
+ DeviceState *ssedev;
114
+ int i;
115
+
116
+ assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
117
+
118
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
119
+ error_report("This board can only be used with CPU %s",
120
+ mc->default_cpu_type);
121
+ exit(1);
122
+ }
123
+
124
+ sysbus_init_child_obj(OBJECT(machine), "sse-200", &mms->sse,
125
+ sizeof(mms->sse), TYPE_SSE200);
126
+ ssedev = DEVICE(&mms->sse);
127
+ object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory),
128
+ "memory", &error_fatal);
129
+ qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
130
+ qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
131
+ qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
132
+ qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
133
+ object_property_set_bool(OBJECT(&mms->sse), true, "realized",
134
+ &error_fatal);
135
+
136
+ /*
137
+ * We need to create splitters to feed the IRQ inputs
138
+ * for each CPU in the SSE-200 from each device in the board.
139
+ */
140
+ for (i = 0; i < mmc->num_irqs; i++) {
141
+ char *name = g_strdup_printf("musca-irq-splitter%d", i);
142
+ SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
143
+
144
+ object_initialize_child(OBJECT(machine), name,
145
+ splitter, sizeof(*splitter),
146
+ TYPE_SPLIT_IRQ, &error_fatal, NULL);
147
+ g_free(name);
148
+
149
+ object_property_set_int(OBJECT(splitter), 2, "num-lines",
150
+ &error_fatal);
151
+ object_property_set_bool(OBJECT(splitter), true, "realized",
152
+ &error_fatal);
153
+ qdev_connect_gpio_out(DEVICE(splitter), 0,
154
+ qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i));
155
+ qdev_connect_gpio_out(DEVICE(splitter), 1,
156
+ qdev_get_gpio_in_named(ssedev,
157
+ "EXP_CPU1_IRQ", i));
158
+ }
159
+
160
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
161
+}
162
+
163
+static void musca_class_init(ObjectClass *oc, void *data)
164
+{
165
+ MachineClass *mc = MACHINE_CLASS(oc);
166
+
167
+ mc->default_cpus = 2;
168
+ mc->min_cpus = mc->default_cpus;
169
+ mc->max_cpus = mc->default_cpus;
170
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
171
+ mc->init = musca_init;
172
+}
173
+
174
+static void musca_a_class_init(ObjectClass *oc, void *data)
175
+{
176
+ MachineClass *mc = MACHINE_CLASS(oc);
177
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
178
+
179
+ mc->desc = "ARM Musca-A board (dual Cortex-M33)";
180
+ mmc->type = MUSCA_A;
181
+ mmc->init_svtor = 0x10200000;
182
+ mmc->sram_addr_width = 15;
183
+ mmc->num_irqs = 64;
184
+}
185
+
186
+static void musca_b1_class_init(ObjectClass *oc, void *data)
187
+{
188
+ MachineClass *mc = MACHINE_CLASS(oc);
189
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
190
+
191
+ mc->desc = "ARM Musca-B1 board (dual Cortex-M33)";
192
+ mmc->type = MUSCA_B1;
193
+ /*
194
+ * This matches the DAPlink firmware which boots from QSPI. There
195
+ * is also a firmware blob which boots from the eFlash, which
196
+ * uses init_svtor = 0x1A000000. QEMU doesn't currently support that,
197
+ * though we could in theory expose a machine property on the command
198
+ * line to allow the user to request eFlash boot.
199
+ */
200
+ mmc->init_svtor = 0x10000000;
201
+ mmc->sram_addr_width = 17;
202
+ mmc->num_irqs = 96;
203
+}
204
+
205
+static const TypeInfo musca_info = {
206
+ .name = TYPE_MUSCA_MACHINE,
207
+ .parent = TYPE_MACHINE,
208
+ .abstract = true,
209
+ .instance_size = sizeof(MuscaMachineState),
210
+ .class_size = sizeof(MuscaMachineClass),
211
+ .class_init = musca_class_init,
212
+};
230
+};
213
+
231
+
214
+static const TypeInfo musca_a_info = {
232
+static void fsl_imx8m_pcie_phy_realize(DeviceState *dev, Error **errp)
215
+ .name = TYPE_MUSCA_A_MACHINE,
233
+{
216
+ .parent = TYPE_MUSCA_MACHINE,
234
+ FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(dev);
217
+ .class_init = musca_a_class_init,
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
+ }
218
+};
257
+};
219
+
258
+
220
+static const TypeInfo musca_b1_info = {
259
+static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, void *data)
221
+ .name = TYPE_MUSCA_B1_MACHINE,
260
+{
222
+ .parent = TYPE_MUSCA_MACHINE,
261
+ DeviceClass *dc = DEVICE_CLASS(klass);
223
+ .class_init = musca_b1_class_init,
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
+ }
224
+};
276
+};
225
+
277
+
226
+static void musca_machine_init(void)
278
+DEFINE_TYPES(fsl_imx8m_pcie_phy_types)
227
+{
279
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
228
+ type_register_static(&musca_info);
280
index XXXXXXX..XXXXXXX 100644
229
+ type_register_static(&musca_a_info);
281
--- a/hw/arm/Kconfig
230
+ type_register_static(&musca_b1_info);
282
+++ b/hw/arm/Kconfig
231
+}
283
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
232
+
284
233
+type_init(musca_machine_init);
285
config FSL_IMX8MP
234
diff --git a/MAINTAINERS b/MAINTAINERS
286
bool
235
index XXXXXXX..XXXXXXX 100644
287
+ imply PCI_DEVICES
236
--- a/MAINTAINERS
288
select ARM_GIC
237
+++ b/MAINTAINERS
289
select FSL_IMX8MP_ANALOG
238
@@ -XXX,XX +XXX,XX @@ F: include/hw/misc/iotkit-sysinfo.h
290
select FSL_IMX8MP_CCM
239
F: hw/misc/armsse-cpuid.c
291
select IMX
240
F: include/hw/misc/armsse-cpuid.h
292
+ select PCI_EXPRESS_DESIGNWARE
241
293
+ select PCI_EXPRESS_FSL_IMX8M_PHY
242
+Musca
294
select SDHCI
243
+M: Peter Maydell <peter.maydell@linaro.org>
295
select UNIMP
244
+L: qemu-arm@nongnu.org
296
245
+S: Maintained
297
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
246
+F: hw/arm/musca.c
298
index XXXXXXX..XXXXXXX 100644
247
+
299
--- a/hw/pci-host/Kconfig
248
Musicpal
300
+++ b/hw/pci-host/Kconfig
249
M: Jan Kiszka <jan.kiszka@web.de>
301
@@ -XXX,XX +XXX,XX @@ config ASTRO
250
M: Peter Maydell <peter.maydell@linaro.org>
302
bool
251
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
303
select PCI
252
index XXXXXXX..XXXXXXX 100644
304
253
--- a/default-configs/arm-softmmu.mak
305
+config PCI_EXPRESS_FSL_IMX8M_PHY
254
+++ b/default-configs/arm-softmmu.mak
306
+ bool
255
@@ -XXX,XX +XXX,XX @@ CONFIG_TUSB6010=y
307
+
256
CONFIG_IMX=y
308
config GT64120
257
CONFIG_MAINSTONE=y
309
bool
258
CONFIG_MPS2=y
310
select PCI
259
+CONFIG_MUSCA=y
311
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
260
CONFIG_NSERIES=y
312
index XXXXXXX..XXXXXXX 100644
261
CONFIG_RASPI=y
313
--- a/hw/pci-host/meson.build
262
CONFIG_REALVIEW=y
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
263
--
323
--
264
2.20.1
324
2.43.0
265
266
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
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-14-shentey@gmail.com
6
[PMM: drop static const from gpt_attrs 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
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(+)
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
* 6 I2C Controllers
23
* 3 SPI Controllers
24
* 3 Watchdogs
25
+ * 6 General Purpose Timers
26
* Secure Non-Volatile Storage (SNVS) including an RTC
27
* Clock Tree
28
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 "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;
141
+ }
142
+
143
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_addrs[i]);
144
+
145
+ if (i < FSL_IMX8MP_NUM_GPTS - 2) {
146
+ static const unsigned int gpt_irqs[FSL_IMX8MP_NUM_GPTS - 2] = {
147
+ FSL_IMX8MP_GPT1_IRQ,
148
+ FSL_IMX8MP_GPT2_IRQ,
149
+ FSL_IMX8MP_GPT3_IRQ,
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
235
--
236
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
For opcodes 0-5, move some if conditions into the structure
3
The i.MX 8M Plus SoC actually has two ethernet controllers, the usual ENET one
4
of a switch statement. For opcodes 6 & 7, decode everything
4
and a Designware one. There is no device model for the latter, so only add the
5
at once with a second switch.
5
ENET one.
6
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190215192302.27855-2-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/translate-a64.c | 94 ++++++++++++++++++++------------------
12
docs/system/arm/imx8mp-evk.rst | 1 +
13
1 file changed, 49 insertions(+), 45 deletions(-)
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(+)
14
18
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
19
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
21
--- a/docs/system/arm/imx8mp-evk.rst
18
+++ b/target/arm/translate-a64.c
22
+++ b/docs/system/arm/imx8mp-evk.rst
19
@@ -XXX,XX +XXX,XX @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
23
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
20
int type = extract32(insn, 22, 2);
24
* 4 UARTs
21
bool sbit = extract32(insn, 29, 1);
25
* 3 USDHC Storage Controllers
22
bool sf = extract32(insn, 31, 1);
26
* 1 Designware PCI Express Controller
23
+ bool itof = false;
27
+ * 1 Ethernet Controller
24
28
* 5 GPIO Controllers
25
if (sbit) {
29
* 6 I2C Controllers
26
- unallocated_encoding(s);
30
* 3 SPI Controllers
27
- return;
31
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
28
+ goto do_unallocated;
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);
29
}
75
}
30
76
31
- if (opcode > 5) {
77
+ object_initialize_child(obj, "eth0", &s->enet, TYPE_IMX_ENET);
32
- /* FMOV */
33
- bool itof = opcode & 1;
34
-
35
- if (rmode >= 2) {
36
- unallocated_encoding(s);
37
- return;
38
- }
39
-
40
- switch (sf << 3 | type << 1 | rmode) {
41
- case 0x0: /* 32 bit */
42
- case 0xa: /* 64 bit */
43
- case 0xd: /* 64 bit to top half of quad */
44
- break;
45
- case 0x6: /* 16-bit float, 32-bit int */
46
- case 0xe: /* 16-bit float, 64-bit int */
47
- if (dc_isar_feature(aa64_fp16, s)) {
48
- break;
49
- }
50
- /* fallthru */
51
- default:
52
- /* all other sf/type/rmode combinations are invalid */
53
- unallocated_encoding(s);
54
- return;
55
- }
56
-
57
- if (!fp_access_check(s)) {
58
- return;
59
- }
60
- handle_fmov(s, rd, rn, type, itof);
61
- } else {
62
- /* actual FP conversions */
63
- bool itof = extract32(opcode, 1, 1);
64
-
65
- if (rmode != 0 && opcode > 1) {
66
- unallocated_encoding(s);
67
- return;
68
+ switch (opcode) {
69
+ case 2: /* SCVTF */
70
+ case 3: /* UCVTF */
71
+ itof = true;
72
+ /* fallthru */
73
+ case 4: /* FCVTAS */
74
+ case 5: /* FCVTAU */
75
+ if (rmode != 0) {
76
+ goto do_unallocated;
77
}
78
+ /* fallthru */
79
+ case 0: /* FCVT[NPMZ]S */
80
+ case 1: /* FCVT[NPMZ]U */
81
switch (type) {
82
case 0: /* float32 */
83
case 1: /* float64 */
84
break;
85
case 3: /* float16 */
86
- if (dc_isar_feature(aa64_fp16, s)) {
87
- break;
88
+ if (!dc_isar_feature(aa64_fp16, s)) {
89
+ goto do_unallocated;
90
}
91
- /* fallthru */
92
+ break;
93
default:
94
- unallocated_encoding(s);
95
- return;
96
+ goto do_unallocated;
97
}
98
-
99
if (!fp_access_check(s)) {
100
return;
101
}
102
handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
103
+ break;
104
+
78
+
105
+ default:
79
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
106
+ switch (sf << 7 | type << 5 | rmode << 3 | opcode) {
80
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
107
+ case 0b01100110: /* FMOV half <-> 32-bit int */
81
TYPE_FSL_IMX8M_PCIE_PHY);
108
+ case 0b01100111:
82
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
109
+ case 0b11100110: /* FMOV half <-> 64-bit int */
83
qdev_get_gpio_in(gicdev, spi_table[i].irq));
110
+ case 0b11100111:
84
}
111
+ if (!dc_isar_feature(aa64_fp16, s)) {
85
112
+ goto do_unallocated;
86
+ /* ENET1 */
113
+ }
87
+ object_property_set_uint(OBJECT(&s->enet), "phy-num", s->phy_num,
114
+ /* fallthru */
88
+ &error_abort);
115
+ case 0b00000110: /* FMOV 32-bit */
89
+ object_property_set_uint(OBJECT(&s->enet), "tx-ring-num", 3, &error_abort);
116
+ case 0b00000111:
90
+ qemu_configure_nic_device(DEVICE(&s->enet), true, NULL);
117
+ case 0b10100110: /* FMOV 64-bit */
91
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->enet), errp)) {
118
+ case 0b10100111:
92
+ return;
119
+ case 0b11001110: /* FMOV top half of 128-bit */
93
+ }
120
+ case 0b11001111:
94
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0,
121
+ if (!fp_access_check(s)) {
95
+ fsl_imx8mp_memmap[FSL_IMX8MP_ENET1].addr);
122
+ return;
96
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0,
123
+ }
97
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_ENET1_MAC_IRQ));
124
+ itof = opcode & 1;
98
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1,
125
+ handle_fmov(s, rd, rn, type, itof);
99
+ qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IRQ));
126
+ break;
127
+
100
+
128
+ default:
101
/* SNVS */
129
+ do_unallocated:
102
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
130
+ unallocated_encoding(s);
103
return;
131
+ return;
104
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
132
+ }
105
case FSL_IMX8MP_GIC_REDIST:
133
+ break;
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)
134
}
113
}
135
}
114
}
136
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
137
--
153
--
138
2.20.1
154
2.43.0
139
140
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