1
The following changes since commit 7e7eb9f852a46b51a71ae9d82590b2e4d28827ee:
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
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-01-28' into staging (2021-01-28 22:43:18 +0000)
5
thanks
6
-- PMM
7
8
The following changes since commit b69801dd6b1eb4d107f7c2f643adf0a4e3ec9124:
9
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)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210129
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250225
8
15
9
for you to fetch changes up to 11749122e1a86866591306d43603d2795a3dea1a:
16
for you to fetch changes up to 1aaf3478684ff1cd02d1b36c32a00bfac9a5dbd5:
10
17
11
hw/arm/stellaris: Remove board-creation reset of STELLARIS_SYS (2021-01-29 10:47:29 +0000)
18
hw/arm/fsl-imx8mp: Add on-chip RAM (2025-02-25 17:24:00 +0000)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
target-arm queue:
21
target-arm queue:
15
* Implement ID_PFR2
22
* hw/arm/smmuv3: Fill u.f_cd_fetch.addr for SMMU_EVT_F_CD_FETCH
16
* Conditionalize DBGDIDR
23
* hw/arm/virt: Support larger highmem MMIO regions
17
* rename xlnx-zcu102.canbusN properties
24
* machine: Centralize -machine dumpdtb option handling and report
18
* provide powerdown/reset mechanism for secure firmware on 'virt' board
25
attempt to dump nonexistent DTB as an error
19
* hw/misc: Fix arith overflow in NPCM7XX PWM module
26
* fpu: remove target ifdefs and build it only once
20
* target/arm: Replace magic value by MMU_DATA_LOAD definition
27
* target/arm: Refactor to move TCG-only vfp_helper code into tcg/
21
* configure: fix preadv errors on Catalina macOS with new XCode
28
* target/arm/hvf: Disable SME feature
22
* Various configure and other cleanups in preparation for iOS support
29
* target/arm/hvf: sign extend the data for a load operation when SSE=1
23
* hvf: Add hypervisor entitlement to output binaries (needed for Big Sur)
30
* hw/misc/npcm_clk: fix buffer-overflow
24
* Implement pvpanic-pci device
31
* hw/arm: Add i.MX 8M Plus EVK board ("imx8mp-evk")
25
* Convert the CMSDK timer devices to the Clock framework
26
32
27
----------------------------------------------------------------
33
----------------------------------------------------------------
28
Alexander Graf (1):
34
Bernhard Beschow (16):
29
hvf: Add hypervisor entitlement to output binaries
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
30
51
31
Hao Wu (1):
52
Joelle van Dyne (2):
32
hw/misc: Fix arith overflow in NPCM7XX PWM module
53
target/arm/hvf: Disable SME feature
54
target/arm/hvf: sign extend the data for a load operation when SSE=1
33
55
34
Joelle van Dyne (7):
56
Matthew R. Ochs (1):
35
configure: cross-compiling with empty cross_prefix
57
hw/arm/virt: Support larger highmem MMIO regions
36
osdep: build with non-working system() function
37
darwin: remove redundant dependency declaration
38
darwin: fix cross-compiling for Darwin
39
configure: cross compile should use x86_64 cpu_family
40
darwin: detect CoreAudio for build
41
darwin: remove 64-bit build detection on 32-bit OS
42
58
43
Maxim Uvarov (3):
59
Nicolin Chen (1):
44
hw: gpio: implement gpio-pwr driver for qemu reset/poweroff
60
hw/arm/smmuv3: Fill u.f_cd_fetch.addr for SMMU_EVT_F_CD_FETCH
45
arm-virt: refactor gpios creation
46
arm-virt: add secure pl061 for reset/power down
47
61
48
Mihai Carabas (4):
62
Peter Maydell (22):
49
hw/misc/pvpanic: split-out generic and bus dependent code
63
monitor/hmp-cmds.c: Clean up hmp_dumpdtb printf
50
hw/misc/pvpanic: add PCI interface support
64
hw/openrisc: Support monitor dumpdtb command
51
pvpanic : update pvpanic spec document
65
hw/mips/boston: Check for error return from boston_fdt_filter()
52
tests/qtest: add a test case for pvpanic-pci
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
53
85
54
Paolo Bonzini (1):
86
Pierrick Bouvier (1):
55
arm: rename xlnx-zcu102.canbusN properties
87
hw/misc/npcm_clk: fix buffer-overflow
56
88
57
Peter Maydell (26):
89
MAINTAINERS | 13 +
58
configure: Move preadv check to meson.build
90
docs/system/arm/imx8mp-evk.rst | 70 ++++
59
ptimer: Add new ptimer_set_period_from_clock() function
91
docs/system/arm/virt.rst | 4 +
60
clock: Add new clock_has_source() function
92
docs/system/target-arm.rst | 1 +
61
tests: Add a simple test of the CMSDK APB timer
93
include/fpu/softfloat-helpers.h | 12 +
62
tests: Add a simple test of the CMSDK APB watchdog
94
include/fpu/softfloat-types.h | 51 +++
63
tests: Add a simple test of the CMSDK APB dual timer
95
include/fpu/softfloat.h | 91 ++---
64
hw/timer/cmsdk-apb-timer: Rename CMSDKAPBTIMER struct to CMSDKAPBTimer
96
include/hw/arm/fsl-imx8mp.h | 284 ++++++++++++++
65
hw/timer/cmsdk-apb-timer: Add Clock input
97
include/hw/loader-fit.h | 21 +-
66
hw/timer/cmsdk-apb-dualtimer: Add Clock input
98
include/hw/misc/imx8mp_analog.h | 81 ++++
67
hw/watchdog/cmsdk-apb-watchdog: Add Clock input
99
include/hw/misc/imx8mp_ccm.h | 30 ++
68
hw/arm/armsse: Rename "MAINCLK" property to "MAINCLK_FRQ"
100
include/hw/openrisc/boot.h | 3 +-
69
hw/arm/armsse: Wire up clocks
101
include/hw/pci-host/designware.h | 7 +
70
hw/arm/mps2: Inline CMSDK_APB_TIMER creation
102
include/hw/pci-host/fsl_imx8m_phy.h | 28 ++
71
hw/arm/mps2: Create and connect SYSCLK Clock
103
include/hw/timer/imx_gpt.h | 1 +
72
hw/arm/mps2-tz: Create and connect ARMSSE Clocks
104
include/hw/usb/hcd-dwc3.h | 2 +-
73
hw/arm/musca: Create and connect ARMSSE Clocks
105
include/system/device_tree.h | 2 -
74
hw/arm/stellaris: Convert SSYS to QOM device
106
target/arm/internals.h | 9 +
75
hw/arm/stellaris: Create Clock input for watchdog
107
fpu/softfloat.c | 23 +-
76
hw/timer/cmsdk-apb-timer: Convert to use Clock input
108
hw/arm/boot.c | 2 -
77
hw/timer/cmsdk-apb-dualtimer: Convert to use Clock input
109
hw/arm/fsl-imx8mp.c | 714 ++++++++++++++++++++++++++++++++++++
78
hw/watchdog/cmsdk-apb-watchdog: Convert to use Clock input
110
hw/arm/imx8mp-evk.c | 74 ++++
79
tests/qtest/cmsdk-apb-watchdog-test: Test clock changes
111
hw/arm/smmuv3.c | 2 +-
80
hw/arm/armsse: Use Clock to set system_clock_scale
112
hw/arm/virt.c | 52 ++-
81
arm: Don't set freq properties on CMSDK timer, dualtimer, watchdog, ARMSSE
113
hw/core/loader-fit.c | 38 +-
82
arm: Remove frq properties on CMSDK timer, dualtimer, watchdog, ARMSSE
114
hw/core/machine.c | 23 ++
83
hw/arm/stellaris: Remove board-creation reset of STELLARIS_SYS
115
hw/loongarch/virt-fdt-build.c | 1 -
84
116
hw/mips/boston.c | 16 +-
85
Philippe Mathieu-Daudé (1):
117
hw/misc/imx8mp_analog.c | 160 ++++++++
86
target/arm: Replace magic value by MMU_DATA_LOAD definition
118
hw/misc/imx8mp_ccm.c | 175 +++++++++
87
119
hw/misc/npcm_clk.c | 5 +-
88
Richard Henderson (2):
120
hw/openrisc/boot.c | 8 +-
89
target/arm: Implement ID_PFR2
121
hw/openrisc/openrisc_sim.c | 2 +-
90
target/arm: Conditionalize DBGDIDR
122
hw/openrisc/virt.c | 2 +-
91
123
hw/pci-host/designware.c | 18 +-
92
docs/devel/clocks.rst | 16 +++
124
hw/pci-host/fsl_imx8m_phy.c | 98 +++++
93
docs/specs/pci-ids.txt | 1 +
125
hw/ppc/e500.c | 1 -
94
docs/specs/pvpanic.txt | 13 ++-
126
hw/ppc/pegasos2.c | 1 -
95
docs/system/arm/virt.rst | 2 +
127
hw/ppc/pnv.c | 1 -
96
configure | 78 ++++++++------
128
hw/ppc/spapr.c | 1 -
97
meson.build | 34 ++++++-
129
hw/riscv/boot.c | 2 -
98
include/hw/arm/armsse.h | 14 ++-
130
hw/timer/imx_gpt.c | 25 ++
99
include/hw/arm/virt.h | 2 +
131
hw/usb/hcd-dwc3.c | 5 +
100
include/hw/clock.h | 15 +++
132
monitor/hmp-cmds.c | 2 +-
101
include/hw/misc/pvpanic.h | 24 ++++-
133
system/device_tree-stub.c | 5 +-
102
include/hw/pci/pci.h | 1 +
134
system/device_tree.c | 22 +-
103
include/hw/ptimer.h | 22 ++++
135
target/arm/hvf/hvf.c | 16 +
104
include/hw/timer/cmsdk-apb-dualtimer.h | 5 +-
136
target/arm/tcg-stubs.c | 22 ++
105
include/hw/timer/cmsdk-apb-timer.h | 34 ++-----
137
target/arm/{ => tcg}/vfp_helper.c | 189 +---------
106
include/hw/watchdog/cmsdk-apb-watchdog.h | 5 +-
138
target/arm/vfp_fpscr.c | 155 ++++++++
107
include/qemu/osdep.h | 12 +++
139
target/hppa/fpu_helper.c | 1 +
108
include/qemu/typedefs.h | 1 +
140
target/i386/tcg/fpu_helper.c | 51 +--
109
target/arm/cpu.h | 1 +
141
target/m68k/cpu.c | 35 ++
110
hw/arm/armsse.c | 48 ++++++---
142
target/m68k/fpu_helper.c | 2 +-
111
hw/arm/mps2-tz.c | 14 ++-
143
target/m68k/softfloat.c | 47 +--
112
hw/arm/mps2.c | 28 ++++-
144
target/sh4/cpu.c | 1 +
113
hw/arm/musca.c | 13 ++-
145
fpu/softfloat-parts.c.inc | 27 +-
114
hw/arm/stellaris.c | 170 +++++++++++++++++++++++--------
146
fpu/softfloat-specialize.c.inc | 29 +-
115
hw/arm/virt.c | 111 ++++++++++++++++----
147
fpu/meson.build | 2 +-
116
hw/arm/xlnx-zcu102.c | 4 +-
148
hw/arm/Kconfig | 24 ++
117
hw/core/ptimer.c | 34 +++++++
149
hw/arm/meson.build | 2 +
118
hw/gpio/gpio_pwr.c | 70 +++++++++++++
150
hw/gpio/Kconfig | 8 +
119
hw/misc/npcm7xx_pwm.c | 23 ++++-
151
hw/misc/Kconfig | 14 +-
120
hw/misc/pvpanic-isa.c | 94 +++++++++++++++++
152
hw/misc/meson.build | 2 +
121
hw/misc/pvpanic-pci.c | 94 +++++++++++++++++
153
hw/pci-host/Kconfig | 3 +
122
hw/misc/pvpanic.c | 85 ++--------------
154
hw/pci-host/meson.build | 1 +
123
hw/timer/cmsdk-apb-dualtimer.c | 53 +++++++---
155
target/arm/meson.build | 2 +-
124
hw/timer/cmsdk-apb-timer.c | 55 +++++-----
156
target/arm/tcg/meson.build | 1 +
125
hw/watchdog/cmsdk-apb-watchdog.c | 29 ++++--
157
68 files changed, 2439 insertions(+), 383 deletions(-)
126
target/arm/helper.c | 27 +++--
158
create mode 100644 docs/system/arm/imx8mp-evk.rst
127
target/arm/kvm64.c | 2 +
159
create mode 100644 include/hw/arm/fsl-imx8mp.h
128
tests/qtest/cmsdk-apb-dualtimer-test.c | 130 +++++++++++++++++++++++
160
create mode 100644 include/hw/misc/imx8mp_analog.h
129
tests/qtest/cmsdk-apb-timer-test.c | 75 ++++++++++++++
161
create mode 100644 include/hw/misc/imx8mp_ccm.h
130
tests/qtest/cmsdk-apb-watchdog-test.c | 131 ++++++++++++++++++++++++
162
create mode 100644 include/hw/pci-host/fsl_imx8m_phy.h
131
tests/qtest/npcm7xx_pwm-test.c | 4 +-
163
create mode 100644 hw/arm/fsl-imx8mp.c
132
tests/qtest/pvpanic-pci-test.c | 94 +++++++++++++++++
164
create mode 100644 hw/arm/imx8mp-evk.c
133
tests/qtest/xlnx-can-test.c | 30 +++---
165
create mode 100644 hw/misc/imx8mp_analog.c
134
MAINTAINERS | 3 +
166
create mode 100644 hw/misc/imx8mp_ccm.c
135
accel/hvf/entitlements.plist | 8 ++
167
create mode 100644 hw/pci-host/fsl_imx8m_phy.c
136
hw/arm/Kconfig | 1 +
168
rename target/arm/{ => tcg}/vfp_helper.c (90%)
137
hw/gpio/Kconfig | 3 +
169
create mode 100644 target/arm/vfp_fpscr.c
138
hw/gpio/meson.build | 1 +
139
hw/i386/Kconfig | 2 +-
140
hw/misc/Kconfig | 12 ++-
141
hw/misc/meson.build | 4 +-
142
scripts/entitlement.sh | 13 +++
143
tests/qtest/meson.build | 6 +-
144
52 files changed, 1432 insertions(+), 319 deletions(-)
145
create mode 100644 hw/gpio/gpio_pwr.c
146
create mode 100644 hw/misc/pvpanic-isa.c
147
create mode 100644 hw/misc/pvpanic-pci.c
148
create mode 100644 tests/qtest/cmsdk-apb-dualtimer-test.c
149
create mode 100644 tests/qtest/cmsdk-apb-timer-test.c
150
create mode 100644 tests/qtest/cmsdk-apb-watchdog-test.c
151
create mode 100644 tests/qtest/pvpanic-pci-test.c
152
create mode 100644 accel/hvf/entitlements.plist
153
create mode 100755 scripts/entitlement.sh
154
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Nicolin Chen <nicolinc@nvidia.com>
2
2
3
cpu_get_phys_page_debug() uses 'DATA LOAD' MMU access type.
3
When we fill in the SMMUEventInfo for SMMU_EVT_F_CD_FETCH we write
4
the address into the f_ste_fetch member of the union, but then when
5
we come to read it back in smmuv3_record_event() we will (correctly)
6
be using the f_cd_fetch member.
4
7
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
This is more like a cosmetics fix since the f_cd_fetch and f_ste_fetch are
6
Message-id: 20210127232822.3530782-1-f4bug@amsat.org
9
basically the same field since they are in the exact same union with exact
10
same type, but it's conceptually wrong. Use the correct union member.
11
12
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
13
Message-id: 20250220213832.80289-1-nicolinc@nvidia.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
16
---
10
target/arm/helper.c | 2 +-
17
hw/arm/smmuv3.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
18
1 file changed, 1 insertion(+), 1 deletion(-)
12
19
13
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
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
22
--- a/hw/arm/smmuv3.c
16
+++ b/target/arm/helper.c
23
+++ b/hw/arm/smmuv3.c
17
@@ -XXX,XX +XXX,XX @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
24
@@ -XXX,XX +XXX,XX @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTransCfg *cfg,
18
25
qemu_log_mask(LOG_GUEST_ERROR,
19
*attrs = (MemTxAttrs) {};
26
"Cannot fetch pte at address=0x%"PRIx64"\n", addr);
20
27
event->type = SMMU_EVT_F_CD_FETCH;
21
- ret = get_phys_addr(env, addr, 0, mmu_idx, &phys_addr,
28
- event->u.f_ste_fetch.addr = addr;
22
+ ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &phys_addr,
29
+ event->u.f_cd_fetch.addr = addr;
23
attrs, &prot, &page_size, &fi, &cacheattrs);
30
return -EINVAL;
24
31
}
25
if (ret) {
32
for (i = 0; i < ARRAY_SIZE(buf->word); i++) {
26
--
33
--
27
2.20.1
34
2.43.0
28
29
diff view generated by jsdifflib
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
1
From: "Matthew R. Ochs" <mochs@nvidia.com>
2
2
3
No functional change. Just refactor code to better
3
The MMIO region size required to support virtualized environments with
4
support secure and normal world gpios.
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.
5
10
6
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
11
Example usage with 1TB MMIO region size:
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
22
---
10
hw/arm/virt.c | 57 ++++++++++++++++++++++++++++++++-------------------
23
docs/system/arm/virt.rst | 4 ++++
11
1 file changed, 36 insertions(+), 21 deletions(-)
24
hw/arm/virt.c | 52 +++++++++++++++++++++++++++++++++++++++-
25
2 files changed, 55 insertions(+), 1 deletion(-)
12
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:
13
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
42
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/virt.c
44
--- a/hw/arm/virt.c
16
+++ b/hw/arm/virt.c
45
+++ b/hw/arm/virt.c
17
@@ -XXX,XX +XXX,XX @@ static void virt_powerdown_req(Notifier *n, void *opaque)
46
@@ -XXX,XX +XXX,XX @@
18
}
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;
19
}
85
}
20
86
21
-static void create_gpio(const VirtMachineState *vms)
87
+static void virt_get_highmem_mmio_size(Object *obj, Visitor *v,
22
+static void create_gpio_keys(const VirtMachineState *vms,
88
+ const char *name, void *opaque,
23
+ DeviceState *pl061_dev,
89
+ Error **errp)
24
+ uint32_t phandle)
25
+{
90
+{
26
+ gpio_key_dev = sysbus_create_simple("gpio-key", -1,
91
+ uint64_t size = extended_memmap[VIRT_HIGH_PCIE_MMIO].size;
27
+ qdev_get_gpio_in(pl061_dev, 3));
28
+
92
+
29
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
93
+ visit_type_size(v, name, &size, errp);
30
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
31
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
32
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
33
+
34
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
35
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
36
+ "label", "GPIO Key Poweroff");
37
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
38
+ KEY_POWER);
39
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
40
+ "gpios", phandle, 3, 0);
41
+}
94
+}
42
+
95
+
43
+static void create_gpio_devices(const VirtMachineState *vms, int gpio,
96
+static void virt_set_highmem_mmio_size(Object *obj, Visitor *v,
44
+ MemoryRegion *mem)
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)
45
{
123
{
46
char *nodename;
124
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
47
DeviceState *pl061_dev;
125
"Set on/off to enable/disable high "
48
- hwaddr base = vms->memmap[VIRT_GPIO].base;
126
"memory region for PCI MMIO");
49
- hwaddr size = vms->memmap[VIRT_GPIO].size;
127
50
- int irq = vms->irqmap[VIRT_GPIO];
128
+ object_class_property_add(oc, "highmem-mmio-size", "size",
51
+ hwaddr base = vms->memmap[gpio].base;
129
+ virt_get_highmem_mmio_size,
52
+ hwaddr size = vms->memmap[gpio].size;
130
+ virt_set_highmem_mmio_size,
53
+ int irq = vms->irqmap[gpio];
131
+ NULL, NULL);
54
const char compat[] = "arm,pl061\0arm,primecell";
132
+ object_class_property_set_description(oc, "highmem-mmio-size",
55
+ SysBusDevice *s;
133
+ "Set the high memory region size "
56
134
+ "for PCI MMIO");
57
- pl061_dev = sysbus_create_simple("pl061", base,
58
- qdev_get_gpio_in(vms->gic, irq));
59
+ pl061_dev = qdev_new("pl061");
60
+ s = SYS_BUS_DEVICE(pl061_dev);
61
+ sysbus_realize_and_unref(s, &error_fatal);
62
+ memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
63
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
64
65
uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
66
nodename = g_strdup_printf("/pl061@%" PRIx64, base);
67
@@ -XXX,XX +XXX,XX @@ static void create_gpio(const VirtMachineState *vms)
68
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
69
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
70
71
- gpio_key_dev = sysbus_create_simple("gpio-key", -1,
72
- qdev_get_gpio_in(pl061_dev, 3));
73
- qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
74
- qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
75
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
76
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
77
-
78
- qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
79
- qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
80
- "label", "GPIO Key Poweroff");
81
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
82
- KEY_POWER);
83
- qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
84
- "gpios", phandle, 3, 0);
85
g_free(nodename);
86
+
135
+
87
+ /* Child gpio devices */
136
object_class_property_add_str(oc, "gic-version", virt_get_gic_version,
88
+ create_gpio_keys(vms, pl061_dev, phandle);
137
virt_set_gic_version);
89
}
138
object_class_property_set_description(oc, "gic-version",
90
91
static void create_virtio_devices(const VirtMachineState *vms)
92
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
93
if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
94
vms->acpi_dev = create_acpi_ged(vms);
95
} else {
96
- create_gpio(vms);
97
+ create_gpio_devices(vms, VIRT_GPIO, sysmem);
98
}
99
100
/* connect powerdown request */
101
--
139
--
102
2.20.1
140
2.43.0
103
104
diff view generated by jsdifflib
1
Use the MAINCLK Clock input to set the system_clock_scale variable
1
In hmp_dumpdtb(), we print a message when the command succeeds. This
2
rather than using the mainclk_frq property.
2
message is missing the trailing \n, so the HMP command prompt is
3
printed immediately after it. We also weren't capitalizing 'DTB', or
4
quoting the filename in the message. Fix these nits.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Message-id: 20250206151214.2947842-2-peter.maydell@linaro.org
8
Message-id: 20210128114145.20536-23-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-23-peter.maydell@linaro.org
10
---
10
---
11
hw/arm/armsse.c | 24 +++++++++++++++++++-----
11
monitor/hmp-cmds.c | 2 +-
12
1 file changed, 19 insertions(+), 5 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
13
14
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
14
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armsse.c
16
--- a/monitor/hmp-cmds.c
17
+++ b/hw/arm/armsse.c
17
+++ b/monitor/hmp-cmds.c
18
@@ -XXX,XX +XXX,XX @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
18
@@ -XXX,XX +XXX,XX @@ void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
19
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
20
}
21
22
+static void armsse_mainclk_update(void *opaque)
23
+{
24
+ ARMSSE *s = ARM_SSE(opaque);
25
+ /*
26
+ * Set system_clock_scale from our Clock input; this is what
27
+ * controls the tick rate of the CPU SysTick timer.
28
+ */
29
+ system_clock_scale = clock_ticks_to_ns(s->mainclk, 1);
30
+}
31
+
32
static void armsse_init(Object *obj)
33
{
34
ARMSSE *s = ARM_SSE(obj);
35
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
36
assert(info->sram_banks <= MAX_SRAM_BANKS);
37
assert(info->num_cpus <= SSE_MAX_CPUS);
38
39
- s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL);
40
+ s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
41
+ armsse_mainclk_update, s);
42
s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
43
44
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
45
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
46
return;
19
return;
47
}
20
}
48
21
49
- if (!s->mainclk_frq) {
22
- monitor_printf(mon, "dtb dumped to %s", filename);
50
- error_setg(errp, "MAINCLK_FRQ property was not set");
23
+ monitor_printf(mon, "DTB dumped to '%s'\n", filename);
51
- return;
52
+ if (!clock_has_source(s->mainclk)) {
53
+ error_setg(errp, "MAINCLK clock was not connected");
54
+ }
55
+ if (!clock_has_source(s->s32kclk)) {
56
+ error_setg(errp, "S32KCLK clock was not connected");
57
}
58
59
assert(info->num_cpus <= SSE_MAX_CPUS);
60
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
61
*/
62
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
63
64
- system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
65
+ /* Set initial system_clock_scale from MAINCLK */
66
+ armsse_mainclk_update(s);
67
}
24
}
68
25
#endif
69
static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
70
--
26
--
71
2.20.1
27
2.43.0
72
28
73
29
diff view generated by jsdifflib
1
As the first step in converting the CMSDK_APB_TIMER device to the
1
The openrisc machines don't set MachineState::fdt to point to their
2
Clock framework, add a Clock input. For the moment we do nothing
2
DTB blob. This means that although the command line '-machine
3
with this clock; we will change the behaviour from using the pclk-frq
3
dumpdtb=file.dtb' option works, the equivalent QMP and HMP monitor
4
property to using the Clock once all the users of this device have
4
commands do not, but instead produce the error "This machine doesn't
5
been converted to wire up the Clock.
5
have a FDT".
6
6
7
Since the device doesn't already have a doc comment for its "QEMU
7
Set MachineState::fdt in openrisc_load_fdt(), when we write it to
8
interface", we add one including the new Clock.
8
guest memory.
9
10
This is a migration compatibility break for machines mps2-an505,
11
mps2-an521, musca-a, musca-b1.
12
9
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Luc Michel <luc@lmichel.fr>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20250206151214.2947842-3-peter.maydell@linaro.org
17
Message-id: 20210128114145.20536-8-peter.maydell@linaro.org
18
Message-id: 20210121190622.22000-8-peter.maydell@linaro.org
19
---
14
---
20
include/hw/timer/cmsdk-apb-timer.h | 9 +++++++++
15
include/hw/openrisc/boot.h | 3 ++-
21
hw/timer/cmsdk-apb-timer.c | 7 +++++--
16
hw/openrisc/boot.c | 7 +++++--
22
2 files changed, 14 insertions(+), 2 deletions(-)
17
hw/openrisc/openrisc_sim.c | 2 +-
18
hw/openrisc/virt.c | 2 +-
19
4 files changed, 9 insertions(+), 5 deletions(-)
23
20
24
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
21
diff --git a/include/hw/openrisc/boot.h b/include/hw/openrisc/boot.h
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/timer/cmsdk-apb-timer.h
23
--- a/include/hw/openrisc/boot.h
27
+++ b/include/hw/timer/cmsdk-apb-timer.h
24
+++ b/include/hw/openrisc/boot.h
28
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
29
#include "hw/qdev-properties.h"
26
#define OPENRISC_BOOT_H
30
#include "hw/sysbus.h"
27
31
#include "hw/ptimer.h"
28
#include "exec/cpu-defs.h"
32
+#include "hw/clock.h"
29
+#include "hw/boards.h"
33
#include "qom/object.h"
30
34
31
hwaddr openrisc_load_kernel(ram_addr_t ram_size,
35
#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
32
const char *kernel_filename,
36
OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
33
@@ -XXX,XX +XXX,XX @@ hwaddr openrisc_load_kernel(ram_addr_t ram_size,
37
34
hwaddr openrisc_load_initrd(void *fdt, const char *filename,
38
+/*
35
hwaddr load_start, uint64_t mem_size);
39
+ * QEMU interface:
36
40
+ * + QOM property "pclk-frq": frequency at which the timer is clocked
37
-uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
41
+ * + Clock input "pclk": clock for the timer
38
+uint32_t openrisc_load_fdt(MachineState *ms, void *fdt, hwaddr load_start,
42
+ * + sysbus MMIO region 0: the register bank
39
uint64_t mem_size);
43
+ * + sysbus IRQ 0: timer interrupt TIMERINT
40
44
+ */
41
#endif /* OPENRISC_BOOT_H */
45
struct CMSDKAPBTimer {
42
diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
46
/*< private >*/
47
SysBusDevice parent_obj;
48
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
49
qemu_irq timerint;
50
uint32_t pclk_frq;
51
struct ptimer_state *timer;
52
+ Clock *pclk;
53
54
uint32_t ctrl;
55
uint32_t value;
56
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
57
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/timer/cmsdk-apb-timer.c
44
--- a/hw/openrisc/boot.c
59
+++ b/hw/timer/cmsdk-apb-timer.c
45
+++ b/hw/openrisc/boot.c
60
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ hwaddr openrisc_load_initrd(void *fdt, const char *filename,
61
#include "hw/sysbus.h"
47
return start + size;
62
#include "hw/irq.h"
63
#include "hw/registerfields.h"
64
+#include "hw/qdev-clock.h"
65
#include "hw/timer/cmsdk-apb-timer.h"
66
#include "migration/vmstate.h"
67
68
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
69
s, "cmsdk-apb-timer", 0x1000);
70
sysbus_init_mmio(sbd, &s->iomem);
71
sysbus_init_irq(sbd, &s->timerint);
72
+ s->pclk = qdev_init_clock_in(DEVICE(s), "pclk", NULL, NULL);
73
}
48
}
74
49
75
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
50
-uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
76
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
51
- uint64_t mem_size)
77
52
+uint32_t openrisc_load_fdt(MachineState *ms, void *fdt,
78
static const VMStateDescription cmsdk_apb_timer_vmstate = {
53
+ hwaddr load_start, uint64_t mem_size)
79
.name = "cmsdk-apb-timer",
54
{
80
- .version_id = 1,
55
uint32_t fdt_addr;
81
- .minimum_version_id = 1,
56
int ret;
82
+ .version_id = 2,
57
@@ -XXX,XX +XXX,XX @@ uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
83
+ .minimum_version_id = 2,
58
/* copy in the device tree */
84
.fields = (VMStateField[]) {
59
qemu_fdt_dumpdtb(fdt, fdtsize);
85
VMSTATE_PTIMER(timer, CMSDKAPBTimer),
60
86
+ VMSTATE_CLOCK(pclk, CMSDKAPBTimer),
61
+ /* Save FDT for dumpdtb monitor command */
87
VMSTATE_UINT32(ctrl, CMSDKAPBTimer),
62
+ ms->fdt = fdt;
88
VMSTATE_UINT32(value, CMSDKAPBTimer),
63
+
89
VMSTATE_UINT32(reload, CMSDKAPBTimer),
64
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
65
&address_space_memory);
66
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
67
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/openrisc/openrisc_sim.c
70
+++ b/hw/openrisc/openrisc_sim.c
71
@@ -XXX,XX +XXX,XX @@ static void openrisc_sim_init(MachineState *machine)
72
machine->initrd_filename,
73
load_addr, machine->ram_size);
74
}
75
- boot_info.fdt_addr = openrisc_load_fdt(state->fdt, load_addr,
76
+ boot_info.fdt_addr = openrisc_load_fdt(machine, state->fdt, load_addr,
77
machine->ram_size);
78
}
79
}
80
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/openrisc/virt.c
83
+++ b/hw/openrisc/virt.c
84
@@ -XXX,XX +XXX,XX @@ static void openrisc_virt_init(MachineState *machine)
85
machine->initrd_filename,
86
load_addr, machine->ram_size);
87
}
88
- boot_info.fdt_addr = openrisc_load_fdt(state->fdt, load_addr,
89
+ boot_info.fdt_addr = openrisc_load_fdt(machine, state->fdt, load_addr,
90
machine->ram_size);
91
}
92
}
90
--
93
--
91
2.20.1
94
2.43.0
92
95
93
96
diff view generated by jsdifflib
1
Create and connect the two clocks needed by the ARMSSE.
1
The function boston_fdt_filter() can return NULL on errors (in which
2
case it will print an error message). When we call this from the
3
non-FIT-image codepath, we aren't checking the return value, so we
4
will plough on with a NULL pointer, and segfault in fdt_totalsize().
5
Check for errors here.
2
6
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Message-id: 20250206151214.2947842-4-peter.maydell@linaro.org
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210128114145.20536-16-peter.maydell@linaro.org
8
Message-id: 20210121190622.22000-16-peter.maydell@linaro.org
9
---
10
---
10
hw/arm/musca.c | 12 ++++++++++++
11
hw/mips/boston.c | 4 ++++
11
1 file changed, 12 insertions(+)
12
1 file changed, 4 insertions(+)
12
13
13
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
14
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/musca.c
16
--- a/hw/mips/boston.c
16
+++ b/hw/arm/musca.c
17
+++ b/hw/mips/boston.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
18
#include "hw/misc/tz-ppc.h"
19
19
#include "hw/misc/unimp.h"
20
dtb_load_data = boston_fdt_filter(s, dtb_file_data,
20
#include "hw/rtc/pl031.h"
21
NULL, &dtb_vaddr);
21
+#include "hw/qdev-clock.h"
22
+ if (!dtb_load_data) {
22
#include "qom/object.h"
23
+ /* boston_fdt_filter() already printed the error for us */
23
24
+ exit(1);
24
#define MUSCA_NUMIRQ_MAX 96
25
+ }
25
@@ -XXX,XX +XXX,XX @@ struct MuscaMachineState {
26
26
UnimplementedDeviceState sdio;
27
/* Calculate real fdt size after filter */
27
UnimplementedDeviceState gpio;
28
dt_size = fdt_totalsize(dtb_load_data);
28
UnimplementedDeviceState cryptoisland;
29
+ Clock *sysclk;
30
+ Clock *s32kclk;
31
};
32
33
#define TYPE_MUSCA_MACHINE "musca"
34
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MuscaMachineState, MuscaMachineClass, MUSCA_MACHINE)
35
* don't model that in our SSE-200 model yet.
36
*/
37
#define SYSCLK_FRQ 40000000
38
+/* Slow 32Khz S32KCLK frequency in Hz */
39
+#define S32KCLK_FRQ (32 * 1000)
40
41
static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
42
{
43
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
44
exit(1);
45
}
46
47
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
48
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
49
+ mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
50
+ clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
51
+
52
object_initialize_child(OBJECT(machine), "sse-200", &mms->sse,
53
TYPE_SSE200);
54
ssedev = DEVICE(&mms->sse);
55
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
56
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
57
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
58
qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
59
+ qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
60
+ qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
61
/*
62
* Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
63
* CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
64
--
29
--
65
2.20.1
30
2.43.0
66
31
67
32
diff view generated by jsdifflib
1
Create and connect the Clock input for the watchdog device on the
1
The boston machine doesn't set MachineState::fdt to the DTB blob that
2
Stellaris boards. Because the Stellaris boards model the ability to
2
it has loaded or created, which means that the QMP/HMP dumpdtb
3
change the clock rate by programming PLL registers, we have to create
3
monitor commands don't work.
4
an output Clock on the ssys_state device and wire it up to the
4
5
watchdog.
5
Setting MachineState::fdt is easy in the non-FIT codepath: we can
6
6
simply do so immediately before loading the DTB into guest memory.
7
Note that the old comment on ssys_calculate_system_clock() got the
7
The FIT codepath is a bit more awkward as currently the FIT loader
8
units wrong -- system_clock_scale is in nanoseconds, not
8
throws away the memory that the FDT was in after it loads it into
9
milliseconds. Improve the commentary to clarify how we are
9
guest memory. So we add a void *pfdt argument to load_fit() for it
10
calculating the period.
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).
11
18
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20250206151214.2947842-5-peter.maydell@linaro.org
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20210128114145.20536-18-peter.maydell@linaro.org
17
Message-id: 20210121190622.22000-18-peter.maydell@linaro.org
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
---
22
---
20
hw/arm/stellaris.c | 43 +++++++++++++++++++++++++++++++------------
23
include/hw/loader-fit.h | 21 ++++++++++++++++++---
21
1 file changed, 31 insertions(+), 12 deletions(-)
24
hw/core/loader-fit.c | 38 +++++++++++++++++++++-----------------
22
25
hw/mips/boston.c | 11 +++++++----
23
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
26
3 files changed, 46 insertions(+), 24 deletions(-)
27
28
diff --git a/include/hw/loader-fit.h b/include/hw/loader-fit.h
24
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/stellaris.c
30
--- a/include/hw/loader-fit.h
26
+++ b/hw/arm/stellaris.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
27
@@ -XXX,XX +XXX,XX @@
67
@@ -XXX,XX +XXX,XX @@
28
#include "hw/watchdog/cmsdk-apb-watchdog.h"
68
29
#include "migration/vmstate.h"
69
#define FIT_LOADER_MAX_PATH (128)
30
#include "hw/misc/unimp.h"
70
31
+#include "hw/qdev-clock.h"
71
-static const void *fit_load_image_alloc(const void *itb, const char *name,
32
#include "cpu.h"
72
- int *poff, size_t *psz, Error **errp)
33
#include "qom/object.h"
73
+static void *fit_load_image_alloc(const void *itb, const char *name,
34
74
+ int *poff, size_t *psz, Error **errp)
35
@@ -XXX,XX +XXX,XX @@ struct ssys_state {
75
{
36
uint32_t clkvclr;
76
const void *data;
37
uint32_t ldoarst;
77
const char *comp;
38
qemu_irq irq;
78
@@ -XXX,XX +XXX,XX @@ static const void *fit_load_image_alloc(const void *itb, const char *name,
39
+ Clock *sysclk;
79
return NULL;
40
/* Properties (all read-only registers) */
80
}
41
uint32_t user0;
81
42
uint32_t user1;
82
- data = g_realloc(uncomp_data, uncomp_len);
43
@@ -XXX,XX +XXX,XX @@ static bool ssys_use_rcc2(ssys_state *s)
83
+ uncomp_data = g_realloc(uncomp_data, uncomp_len);
84
if (psz) {
85
*psz = uncomp_len;
86
}
87
- return data;
88
+ return uncomp_data;
89
}
90
91
error_setg(errp, "unknown compression '%s'", comp);
92
@@ -XXX,XX +XXX,XX @@ out:
93
94
static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
95
int cfg, void *opaque, const void *match_data,
96
- hwaddr kernel_end, Error **errp)
97
+ hwaddr kernel_end, void **pfdt, Error **errp)
98
{
99
ERRP_GUARD();
100
Error *err = NULL;
101
const char *name;
102
- const void *data;
103
- const void *load_data;
104
+ void *data;
105
hwaddr load_addr;
106
int img_off;
107
size_t sz;
108
@@ -XXX,XX +XXX,XX @@ static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
109
return 0;
110
}
111
112
- load_data = data = fit_load_image_alloc(itb, name, &img_off, &sz, errp);
113
+ data = fit_load_image_alloc(itb, name, &img_off, &sz, errp);
114
if (!data) {
115
error_prepend(errp, "unable to load FDT image from FIT: ");
116
return -EINVAL;
117
@@ -XXX,XX +XXX,XX @@ static int fit_load_fdt(const struct fit_loader *ldr, const void *itb,
118
}
119
120
if (ldr->fdt_filter) {
121
- load_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
122
+ void *filtered_data;
123
+
124
+ filtered_data = ldr->fdt_filter(opaque, data, match_data, &load_addr);
125
+ if (filtered_data != data) {
126
+ g_free(data);
127
+ data = filtered_data;
128
+ }
129
}
130
131
load_addr = ldr->addr_to_phys(opaque, load_addr);
132
- sz = fdt_totalsize(load_data);
133
- rom_add_blob_fixed(name, load_data, sz, load_addr);
134
+ sz = fdt_totalsize(data);
135
+ rom_add_blob_fixed(name, data, sz, load_addr);
136
137
- ret = 0;
138
+ *pfdt = data;
139
+ return 0;
140
out:
141
g_free((void *) data);
142
- if (data != load_data) {
143
- g_free((void *) load_data);
144
- }
145
return ret;
44
}
146
}
45
147
46
/*
148
@@ -XXX,XX +XXX,XX @@ out:
47
- * Caculate the sys. clock period in ms.
149
return ret;
48
+ * Calculate the system clock period. We only want to propagate
49
+ * this change to the rest of the system if we're not being called
50
+ * from migration post-load.
51
*/
52
-static void ssys_calculate_system_clock(ssys_state *s)
53
+static void ssys_calculate_system_clock(ssys_state *s, bool propagate_clock)
54
{
55
+ /*
56
+ * SYSDIV field specifies divisor: 0 == /1, 1 == /2, etc. Input
57
+ * clock is 200MHz, which is a period of 5 ns. Dividing the clock
58
+ * frequency by X is the same as multiplying the period by X.
59
+ */
60
if (ssys_use_rcc2(s)) {
61
system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
62
} else {
63
system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
64
}
65
+ clock_set_ns(s->sysclk, system_clock_scale);
66
+ if (propagate_clock) {
67
+ clock_propagate(s->sysclk);
68
+ }
69
}
150
}
70
151
71
static void ssys_write(void *opaque, hwaddr offset,
152
-int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
72
@@ -XXX,XX +XXX,XX @@ static void ssys_write(void *opaque, hwaddr offset,
153
+int load_fit(const struct fit_loader *ldr, const char *filename,
73
s->int_status |= (1 << 6);
154
+ void **pfdt, void *opaque)
74
}
155
{
75
s->rcc = value;
156
Error *err = NULL;
76
- ssys_calculate_system_clock(s);
157
const struct fit_loader_match *match;
77
+ ssys_calculate_system_clock(s, true);
158
@@ -XXX,XX +XXX,XX @@ int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
78
break;
159
goto out;
79
case 0x070: /* RCC2 */
160
}
80
if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
161
81
@@ -XXX,XX +XXX,XX @@ static void ssys_write(void *opaque, hwaddr offset,
162
- ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end,
82
s->int_status |= (1 << 6);
163
+ ret = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end, pfdt,
83
}
164
&err);
84
s->rcc2 = value;
165
if (ret) {
85
- ssys_calculate_system_clock(s);
166
error_report_err(err);
86
+ ssys_calculate_system_clock(s, true);
167
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
87
break;
168
index XXXXXXX..XXXXXXX 100644
88
case 0x100: /* RCGC0 */
169
--- a/hw/mips/boston.c
89
s->rcgc[0] = value;
170
+++ b/hw/mips/boston.c
90
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_reset_hold(Object *obj)
171
@@ -XXX,XX +XXX,XX @@ static void gen_firmware(void *p, hwaddr kernel_entry, hwaddr fdt_addr)
91
{
172
kernel_entry);
92
ssys_state *s = STELLARIS_SYS(obj);
93
94
- ssys_calculate_system_clock(s);
95
+ /* OK to propagate clocks from the hold phase */
96
+ ssys_calculate_system_clock(s, true);
97
}
173
}
98
174
99
static void stellaris_sys_reset_exit(Object *obj)
175
-static const void *boston_fdt_filter(void *opaque, const void *fdt_orig,
100
@@ -XXX,XX +XXX,XX @@ static int stellaris_sys_post_load(void *opaque, int version_id)
176
- const void *match_data, hwaddr *load_addr)
101
{
177
+static void *boston_fdt_filter(void *opaque, const void *fdt_orig,
102
ssys_state *s = opaque;
178
+ const void *match_data, hwaddr *load_addr)
103
179
{
104
- ssys_calculate_system_clock(s);
180
BostonState *s = BOSTON(opaque);
105
+ ssys_calculate_system_clock(s, false);
181
MachineState *machine = s->mach;
106
182
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
107
return 0;
183
if (kernel_size > 0) {
108
}
184
int dt_size;
109
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_sys = {
185
g_autofree const void *dtb_file_data = NULL;
110
VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
186
- g_autofree const void *dtb_load_data = NULL;
111
VMSTATE_UINT32(clkvclr, ssys_state),
187
+ void *dtb_load_data = NULL;
112
VMSTATE_UINT32(ldoarst, ssys_state),
188
hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB);
113
+ /* No field for sysclk -- handled in post-load instead */
189
hwaddr dtb_vaddr = cpu_mips_phys_to_kseg0(NULL, dtb_paddr);
114
VMSTATE_END_OF_LIST()
190
115
}
191
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
116
};
192
exit(1);
117
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_instance_init(Object *obj)
193
}
118
memory_region_init_io(&s->iomem, obj, &ssys_ops, s, "ssys", 0x00001000);
194
119
sysbus_init_mmio(sbd, &s->iomem);
195
+ machine->fdt = dtb_load_data;
120
sysbus_init_irq(sbd, &s->irq);
196
+
121
+ s->sysclk = qdev_init_clock_out(DEVICE(s), "SYSCLK");
197
/* Calculate real fdt size after filter */
122
}
198
dt_size = fdt_totalsize(dtb_load_data);
123
199
rom_add_blob_fixed("dtb", dtb_load_data, dt_size, dtb_paddr);
124
-static int stellaris_sys_init(uint32_t base, qemu_irq irq,
200
@@ -XXX,XX +XXX,XX @@ static void boston_mach_init(MachineState *machine)
125
- stellaris_board_info * board,
201
rom_ptr(dtb_paddr, dt_size));
126
- uint8_t *macaddr)
202
} else {
127
+static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
203
/* Try to load file as FIT */
128
+ stellaris_board_info *board,
204
- fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
129
+ uint8_t *macaddr)
205
+ fit_err = load_fit(&boston_fit_loader, machine->kernel_filename,
130
{
206
+ &machine->fdt, s);
131
DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
207
if (fit_err) {
132
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
208
error_report("unable to load kernel image");
133
@@ -XXX,XX +XXX,XX @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
209
exit(1);
134
*/
135
device_cold_reset(dev);
136
137
- return 0;
138
+ return dev;
139
}
140
141
/* I2C controller. */
142
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
143
int flash_size;
144
I2CBus *i2c;
145
DeviceState *dev;
146
+ DeviceState *ssys_dev;
147
int i;
148
int j;
149
150
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
151
}
152
}
153
154
- stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
155
- board, nd_table[0].macaddr.a);
156
+ ssys_dev = stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
157
+ board, nd_table[0].macaddr.a);
158
159
160
if (board->dc1 & (1 << 3)) { /* watchdog present */
161
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
162
/* system_clock_scale is valid now */
163
uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
164
qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
165
+ qdev_connect_clock_in(dev, "WDOGCLK",
166
+ qdev_get_clock_out(ssys_dev, "SYSCLK"));
167
168
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
169
sysbus_mmio_map(SYS_BUS_DEVICE(dev),
170
--
210
--
171
2.20.1
211
2.43.0
172
212
173
213
diff view generated by jsdifflib
1
Switch the CMSDK APB watchdog device over to using its Clock input;
1
Currently we handle the 'dumpdtb' machine sub-option ad-hoc in every
2
the wdogclk_frq property is now ignored.
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.
3
23
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-21-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-21-peter.maydell@linaro.org
10
---
26
---
11
hw/watchdog/cmsdk-apb-watchdog.c | 18 ++++++++++++++----
27
include/system/device_tree.h | 2 --
12
1 file changed, 14 insertions(+), 4 deletions(-)
28
hw/arm/boot.c | 2 --
13
29
hw/core/machine.c | 25 +++++++++++++++++++++++++
14
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
30
hw/loongarch/virt-fdt-build.c | 1 -
15
index XXXXXXX..XXXXXXX 100644
31
hw/mips/boston.c | 1 -
16
--- a/hw/watchdog/cmsdk-apb-watchdog.c
32
hw/openrisc/boot.c | 1 -
17
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
33
hw/ppc/e500.c | 1 -
18
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
34
hw/ppc/pegasos2.c | 1 -
19
ptimer_transaction_commit(s->timer);
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
71
@@ -XXX,XX +XXX,XX @@
72
#include "qemu/error-report.h"
73
#include "qapi/error.h"
74
#include "qapi/qapi-visit-machine.h"
75
+#include "qapi/qapi-commands-machine.h"
76
#include "qemu/madvise.h"
77
#include "qom/object_interfaces.h"
78
#include "system/cpus.h"
79
@@ -XXX,XX +XXX,XX @@ void qemu_remove_machine_init_done_notifier(Notifier *notify)
80
notifier_remove(notify);
20
}
81
}
21
82
22
+static void cmsdk_apb_watchdog_clk_update(void *opaque)
83
+static void handle_machine_dumpdtb(MachineState *ms)
23
+{
84
+{
24
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
85
+ if (!ms->dumpdtb) {
25
+
86
+ return;
26
+ ptimer_transaction_begin(s->timer);
87
+ }
27
+ ptimer_set_period_from_clock(s->timer, s->wdogclk, 1);
88
+ if (!ms->fdt) {
28
+ ptimer_transaction_commit(s->timer);
89
+ /* Silently ignore dumpdtb option if there is nothing to dump */
90
+ return;
91
+ }
92
+#ifdef CONFIG_FDT
93
+ qmp_dumpdtb(ms->dumpdtb, &error_fatal);
94
+ exit(0);
95
+#else
96
+ error_report("This machine doesn't have an FDT");
97
+ exit(1);
98
+#endif
29
+}
99
+}
30
+
100
+
31
static void cmsdk_apb_watchdog_init(Object *obj)
101
void qdev_machine_creation_done(void)
32
{
102
{
33
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
103
cpu_synchronize_all_post_init();
34
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
104
@@ -XXX,XX +XXX,XX @@ void qdev_machine_creation_done(void)
35
s, "cmsdk-apb-watchdog", 0x1000);
105
phase_advance(PHASE_MACHINE_READY);
36
sysbus_init_mmio(sbd, &s->iomem);
106
qdev_assert_realized_properly();
37
sysbus_init_irq(sbd, &s->wdogint);
107
38
- s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK", NULL, NULL);
108
+ /*
39
+ s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK",
109
+ * If the user used -machine dumpdtb=file.dtb to request that we
40
+ cmsdk_apb_watchdog_clk_update, s);
110
+ * dump the DTB to a file, do it now, and exit.
41
111
+ */
42
s->is_luminary = false;
112
+ handle_machine_dumpdtb(current_machine);
43
s->id = cmsdk_apb_watchdog_id;
113
+
44
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
114
/* TODO: once all bus devices are qdevified, this should be done
45
{
115
* when bus is created by qdev.c */
46
CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
116
/*
47
117
diff --git a/hw/loongarch/virt-fdt-build.c b/hw/loongarch/virt-fdt-build.c
48
- if (s->wdogclk_frq == 0) {
118
index XXXXXXX..XXXXXXX 100644
49
+ if (!clock_has_source(s->wdogclk)) {
119
--- a/hw/loongarch/virt-fdt-build.c
50
error_setg(errp,
120
+++ b/hw/loongarch/virt-fdt-build.c
51
- "CMSDK APB watchdog: wdogclk-frq property must be set");
121
@@ -XXX,XX +XXX,XX @@ void virt_fdt_setup(LoongArchVirtMachineState *lvms)
52
+ "CMSDK APB watchdog: WDOGCLK clock must be connected");
122
* Put the FDT into the memory map as a ROM image: this will ensure
53
return;
123
* the FDT is copied again upon reset, even if addr points into RAM.
124
*/
125
- qemu_fdt_dumpdtb(machine->fdt, lvms->fdt_size);
126
rom_add_blob_fixed_as("fdt", machine->fdt, lvms->fdt_size, FDT_BASE,
127
&address_space_memory);
128
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
129
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/mips/boston.c
132
+++ b/hw/mips/boston.c
133
@@ -XXX,XX +XXX,XX @@ static void *boston_fdt_filter(void *opaque, const void *fdt_orig,
134
1, ram_high_sz);
135
136
fdt = g_realloc(fdt, fdt_totalsize(fdt));
137
- qemu_fdt_dumpdtb(fdt, fdt_sz);
138
139
s->fdt_base = *load_addr;
140
141
diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hw/openrisc/boot.c
144
+++ b/hw/openrisc/boot.c
145
@@ -XXX,XX +XXX,XX @@ uint32_t openrisc_load_fdt(MachineState *ms, void *fdt,
146
/* Should only fail if we've built a corrupted tree */
147
g_assert(ret == 0);
148
/* copy in the device tree */
149
- qemu_fdt_dumpdtb(fdt, fdtsize);
150
151
/* Save FDT for dumpdtb monitor command */
152
ms->fdt = fdt;
153
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/ppc/e500.c
156
+++ b/hw/ppc/e500.c
157
@@ -XXX,XX +XXX,XX @@ static int ppce500_load_device_tree(PPCE500MachineState *pms,
158
159
done:
160
if (!dry_run) {
161
- qemu_fdt_dumpdtb(fdt, fdt_size);
162
cpu_physical_memory_write(addr, fdt, fdt_size);
163
164
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
165
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/hw/ppc/pegasos2.c
168
+++ b/hw/ppc/pegasos2.c
169
@@ -XXX,XX +XXX,XX @@ static void pegasos2_machine_reset(MachineState *machine, ResetType type)
170
d[1] = cpu_to_be64(pm->kernel_size - (pm->kernel_entry - pm->kernel_addr));
171
qemu_fdt_setprop(fdt, "/chosen", "qemu,boot-kernel", d, sizeof(d));
172
173
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
174
g_free(pm->fdt_blob);
175
pm->fdt_blob = fdt;
176
177
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/hw/ppc/pnv.c
180
+++ b/hw/ppc/pnv.c
181
@@ -XXX,XX +XXX,XX @@ static void pnv_reset(MachineState *machine, ResetType type)
182
_FDT((fdt_pack(fdt)));
54
}
183
}
55
184
56
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
185
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
57
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
186
cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
58
187
59
ptimer_transaction_begin(s->timer);
188
/* Update machine->fdt with latest fdt */
60
- ptimer_set_freq(s->timer, s->wdogclk_frq);
189
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
61
+ ptimer_set_period_from_clock(s->timer, s->wdogclk, 1);
190
index XXXXXXX..XXXXXXX 100644
62
ptimer_transaction_commit(s->timer);
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;
63
}
220
}
64
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,
65
--
240
--
66
2.20.1
241
2.43.0
67
68
diff view generated by jsdifflib
1
Create two input clocks on the ARMSSE devices, one for the normal
1
Currently if the user requests via -machine dumpdtb=file.dtb that we
2
MAINCLK, and one for the 32KHz S32KCLK, and wire these up to the
2
dump the DTB, but the machine doesn't have a DTB, we silently ignore
3
appropriate devices. The old property-based clock frequency setting
3
the option. This is confusing to users, and is a legacy of the old
4
will remain in place until conversion is complete.
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.
5
7
6
This is a migration compatibility break for machines mps2-an505,
8
Now we handle the option in one place in machine.c, we can provide
7
mps2-an521, musca-a, musca-b1.
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.
8
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
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Luc Michel <luc@lmichel.fr>
41
Message-id: 20250206151214.2947842-7-peter.maydell@linaro.org
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20210128114145.20536-12-peter.maydell@linaro.org
14
Message-id: 20210121190622.22000-12-peter.maydell@linaro.org
15
---
42
---
16
include/hw/arm/armsse.h | 6 ++++++
43
hw/core/machine.c | 6 ++----
17
hw/arm/armsse.c | 17 +++++++++++++++--
44
system/device_tree-stub.c | 5 ++++-
18
2 files changed, 21 insertions(+), 2 deletions(-)
45
system/device_tree.c | 7 ++++++-
46
3 files changed, 12 insertions(+), 6 deletions(-)
19
47
20
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
48
diff --git a/hw/core/machine.c b/hw/core/machine.c
21
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/armsse.h
50
--- a/hw/core/machine.c
23
+++ b/include/hw/arm/armsse.h
51
+++ b/hw/core/machine.c
24
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@ static void handle_machine_dumpdtb(MachineState *ms)
25
* per-CPU identity and control register blocks
53
if (!ms->dumpdtb) {
26
*
27
* QEMU interface:
28
+ * + Clock input "MAINCLK": clock for CPUs and most peripherals
29
+ * + Clock input "S32KCLK": slow 32KHz clock used for a few peripherals
30
* + QOM property "memory" is a MemoryRegion containing the devices provided
31
* by the board model.
32
* + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
33
@@ -XXX,XX +XXX,XX @@
34
#include "hw/misc/armsse-mhu.h"
35
#include "hw/misc/unimp.h"
36
#include "hw/or-irq.h"
37
+#include "hw/clock.h"
38
#include "hw/core/split-irq.h"
39
#include "hw/cpu/cluster.h"
40
#include "qom/object.h"
41
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
42
43
uint32_t nsccfg;
44
45
+ Clock *mainclk;
46
+ Clock *s32kclk;
47
+
48
/* Properties */
49
MemoryRegion *board_memory;
50
uint32_t exp_numirq;
51
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/armsse.c
54
+++ b/hw/arm/armsse.c
55
@@ -XXX,XX +XXX,XX @@
56
#include "hw/arm/armsse.h"
57
#include "hw/arm/boot.h"
58
#include "hw/irq.h"
59
+#include "hw/qdev-clock.h"
60
61
/* Format of the System Information block SYS_CONFIG register */
62
typedef enum SysConfigFormat {
63
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
64
assert(info->sram_banks <= MAX_SRAM_BANKS);
65
assert(info->num_cpus <= SSE_MAX_CPUS);
66
67
+ s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL);
68
+ s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
69
+
70
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
71
72
for (i = 0; i < info->num_cpus; i++) {
73
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
74
* map its upstream ends to the right place in the container.
75
*/
76
qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
77
+ qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
78
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
79
return;
54
return;
80
}
55
}
81
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
56
- if (!ms->fdt) {
82
&error_abort);
57
- /* Silently ignore dumpdtb option if there is nothing to dump */
83
58
- return;
84
qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
59
- }
85
+ qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
60
#ifdef CONFIG_FDT
86
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
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");
87
return;
104
return;
88
}
105
}
89
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
106
90
&error_abort);
91
92
qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
93
+ qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
94
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
95
return;
96
}
97
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
98
* 0x4002f000: S32K timer
99
*/
100
qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
101
+ qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
102
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
103
return;
104
}
105
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
106
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
107
108
qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
109
+ qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
110
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
111
return;
112
}
113
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
114
/* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
115
116
qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
117
+ qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
118
if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
119
return;
120
}
121
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
122
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
123
124
qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
125
+ qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
126
if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
127
return;
128
}
129
@@ -XXX,XX +XXX,XX @@ static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
130
131
static const VMStateDescription armsse_vmstate = {
132
.name = "iotkit",
133
- .version_id = 1,
134
- .minimum_version_id = 1,
135
+ .version_id = 2,
136
+ .minimum_version_id = 2,
137
.fields = (VMStateField[]) {
138
+ VMSTATE_CLOCK(mainclk, ARMSSE),
139
+ VMSTATE_CLOCK(s32kclk, ARMSSE),
140
VMSTATE_UINT32(nsccfg, ARMSSE),
141
VMSTATE_END_OF_LIST()
142
}
143
--
107
--
144
2.20.1
108
2.43.0
145
146
diff view generated by jsdifflib
1
Switch the CMSDK APB dualtimer device over to using its Clock input;
1
Currently we hardcode at compile time whether the floatx80 default
2
the pclk-frq property is now ignored.
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.
5
6
Define a new FloatX80Behaviour enum which is a set of flags that
7
define the target's floatx80 handling. Initially we define just one
8
flag, for whether the default Infinity has the Integer bit set or
9
not, but we will expand this in future commits to cover the other
10
floatx80 target specifics that we currently make compile-time
11
settings.
12
13
Define a new function floatx80_default_inf() which returns the
14
appropriate default Infinity value of the given sign, and use it in
15
the code that was previously directly using the compile-time constant
16
floatx80_infinity_{low,high} values when packing an infinity into a
17
floatx80.
18
19
Since floatx80 is highly unlikely to be supported in any new
20
architecture, and the existing code is generally written as "default
21
to like x87, with an ifdef for m68k", we make the default value for
22
the floatx80 behaviour flags be "what x87 does". This means we only
23
need to change the m68k target to specify the behaviour flags.
24
25
(Other users of floatx80 are the Arm NWFPE emulation, which is
26
obsolete and probably not actually doing the right thing anyway, and
27
the PPC xsrqpxp insn. Making the default be "like x87" avoids our
28
needing to review and test for behaviour changes there.)
29
30
We will clean up the remaining uses of the floatx80_infinity global
31
constant in subsequent commits.
3
32
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
34
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
35
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
36
Message-id: 20250224111524.1101196-2-peter.maydell@linaro.org
8
Message-id: 20210128114145.20536-20-peter.maydell@linaro.org
37
Message-id: 20250217125055.160887-2-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-20-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
---
38
---
12
hw/timer/cmsdk-apb-dualtimer.c | 42 ++++++++++++++++++++++++++++++----
39
include/fpu/softfloat-helpers.h | 12 ++++++++++++
13
1 file changed, 37 insertions(+), 5 deletions(-)
40
include/fpu/softfloat-types.h | 13 +++++++++++++
41
include/fpu/softfloat.h | 1 +
42
fpu/softfloat.c | 7 +++----
43
target/m68k/cpu.c | 6 ++++++
44
fpu/softfloat-specialize.c.inc | 10 ++++++++++
45
6 files changed, 45 insertions(+), 4 deletions(-)
14
46
15
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
47
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
16
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/timer/cmsdk-apb-dualtimer.c
49
--- a/include/fpu/softfloat-helpers.h
18
+++ b/hw/timer/cmsdk-apb-dualtimer.c
50
+++ b/include/fpu/softfloat-helpers.h
19
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
51
@@ -XXX,XX +XXX,XX @@ static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
20
qemu_set_irq(s->timerintc, timintc);
52
status->floatx80_rounding_precision = val;
21
}
53
}
22
54
23
+static int cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule *m)
55
+static inline void set_floatx80_behaviour(FloatX80Behaviour b,
56
+ float_status *status)
24
+{
57
+{
25
+ /* Return the divisor set by the current CONTROL.PRESCALE value */
58
+ status->floatx80_behaviour = b;
26
+ switch (FIELD_EX32(m->control, CONTROL, PRESCALE)) {
27
+ case 0:
28
+ return 1;
29
+ case 1:
30
+ return 16;
31
+ case 2:
32
+ case 3: /* UNDEFINED, we treat like 2 (and complained when it was set) */
33
+ return 256;
34
+ default:
35
+ g_assert_not_reached();
36
+ }
37
+}
59
+}
38
+
60
+
39
static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
61
static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
40
uint32_t newctrl)
62
float_status *status)
41
{
63
{
42
@@ -XXX,XX +XXX,XX @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
64
@@ -XXX,XX +XXX,XX @@ get_floatx80_rounding_precision(const float_status *status)
43
default:
65
return status->floatx80_rounding_precision;
44
g_assert_not_reached();
45
}
46
- ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
47
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk, divisor);
48
}
49
50
if (changed & R_CONTROL_MODE_MASK) {
51
@@ -XXX,XX +XXX,XX @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
52
* limit must both be set to 0xffff, so we wrap at 16 bits.
53
*/
54
ptimer_set_limit(m->timer, 0xffff, 1);
55
- ptimer_set_freq(m->timer, m->parent->pclk_frq);
56
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk,
57
+ cmsdk_dualtimermod_divisor(m));
58
ptimer_transaction_commit(m->timer);
59
}
66
}
60
67
61
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
68
+static inline FloatX80Behaviour
62
s->timeritop = 0;
69
+get_floatx80_behaviour(const float_status *status)
63
}
64
65
+static void cmsdk_apb_dualtimer_clk_update(void *opaque)
66
+{
70
+{
67
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
71
+ return status->floatx80_behaviour;
68
+ int i;
69
+
70
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
71
+ CMSDKAPBDualTimerModule *m = &s->timermod[i];
72
+ ptimer_transaction_begin(m->timer);
73
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk,
74
+ cmsdk_dualtimermod_divisor(m));
75
+ ptimer_transaction_commit(m->timer);
76
+ }
77
+}
72
+}
78
+
73
+
79
static void cmsdk_apb_dualtimer_init(Object *obj)
74
static inline Float2NaNPropRule
75
get_float_2nan_prop_rule(const float_status *status)
80
{
76
{
81
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
77
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
82
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_init(Object *obj)
78
index XXXXXXX..XXXXXXX 100644
83
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
79
--- a/include/fpu/softfloat-types.h
84
sysbus_init_irq(sbd, &s->timermod[i].timerint);
80
+++ b/include/fpu/softfloat-types.h
85
}
81
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
86
- s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", NULL, NULL);
82
float_ftz_before_rounding = 1,
87
+ s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
83
} FloatFTZDetection;
88
+ cmsdk_apb_dualtimer_clk_update, s);
84
89
}
85
+/*
90
86
+ * floatx80 is primarily used by x86 and m68k, and there are
91
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
87
+ * differences in the handling, largely related to the explicit
92
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
88
+ * Integer bit which floatx80 has and the other float formats do not.
93
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
89
+ * These flag values allow specification of the target's requirements
94
int i;
90
+ * and can be ORed together to set floatx80_behaviour.
95
91
+ */
96
- if (s->pclk_frq == 0) {
92
+typedef enum __attribute__((__packed__)) {
97
- error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
93
+ /* In the default Infinity value, is the Integer bit 0 ? */
98
+ if (!clock_has_source(s->timclk)) {
94
+ floatx80_default_inf_int_bit_is_zero = 1,
99
+ error_setg(errp, "CMSDK APB dualtimer: TIMCLK clock must be connected");
95
+} FloatX80Behaviour;
100
return;
96
+
101
}
97
/*
102
98
* Floating Point Status. Individual architectures may maintain
99
* several versions of float_status for different functions. The
100
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
101
uint16_t float_exception_flags;
102
FloatRoundMode float_rounding_mode;
103
FloatX80RoundPrec floatx80_rounding_precision;
104
+ FloatX80Behaviour floatx80_behaviour;
105
Float2NaNPropRule float_2nan_prop_rule;
106
Float3NaNPropRule float_3nan_prop_rule;
107
FloatInfZeroNaNRule float_infzeronan_rule;
108
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
109
index XXXXXXX..XXXXXXX 100644
110
--- a/include/fpu/softfloat.h
111
+++ b/include/fpu/softfloat.h
112
@@ -XXX,XX +XXX,XX @@ float128 floatx80_to_float128(floatx80, float_status *status);
113
| The pattern for an extended double-precision inf.
114
*----------------------------------------------------------------------------*/
115
extern const floatx80 floatx80_infinity;
116
+floatx80 floatx80_default_inf(bool zSign, float_status *status);
117
118
/*----------------------------------------------------------------------------
119
| Software IEC/IEEE extended double-precision operations.
120
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/fpu/softfloat.c
123
+++ b/fpu/softfloat.c
124
@@ -XXX,XX +XXX,XX @@ static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
125
126
case float_class_inf:
127
/* x86 and m68k differ in the setting of the integer bit. */
128
- frac = floatx80_infinity_low;
129
+ frac = s->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero ?
130
+ 0 : (1ULL << 63);
131
exp = fmt->exp_max;
132
break;
133
134
@@ -XXX,XX +XXX,XX @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
135
) {
136
return packFloatx80( zSign, 0x7FFE, ~ roundMask );
137
}
138
- return packFloatx80(zSign,
139
- floatx80_infinity_high,
140
- floatx80_infinity_low);
141
+ return floatx80_default_inf(zSign, status);
142
}
143
if ( zExp <= 0 ) {
144
isTiny = status->tininess_before_rounding
145
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/m68k/cpu.c
148
+++ b/target/m68k/cpu.c
149
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
150
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
151
/* Default NaN: sign bit clear, all frac bits set */
152
set_float_default_nan_pattern(0b01111111, &env->fp_status);
153
+ /*
154
+ * m68k-specific floatx80 behaviour:
155
+ * * default Infinity values have a zero Integer bit
156
+ */
157
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
158
+ &env->fp_status);
159
160
nan = floatx80_default_nan(&env->fp_status);
161
for (i = 0; i < 8; i++) {
162
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
163
index XXXXXXX..XXXXXXX 100644
164
--- a/fpu/softfloat-specialize.c.inc
165
+++ b/fpu/softfloat-specialize.c.inc
166
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_default_nan(float_status *status)
167
| The pattern for a default generated extended double-precision inf.
168
*----------------------------------------------------------------------------*/
169
170
+floatx80 floatx80_default_inf(bool zSign, float_status *status)
171
+{
172
+ /*
173
+ * Whether the Integer bit is set in the default Infinity is
174
+ * target dependent.
175
+ */
176
+ bool z = status->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero;
177
+ return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
178
+}
179
+
180
#define floatx80_infinity_high 0x7FFF
181
#if defined(TARGET_M68K)
182
#define floatx80_infinity_low UINT64_C(0x0000000000000000)
103
--
183
--
104
2.20.1
184
2.43.0
105
185
106
186
diff view generated by jsdifflib
1
While we transition the ARMSSE code from integer properties
1
The global const floatx80_infinity is (unlike all the other
2
specifying clock frequencies to Clock objects, we want to have the
2
float*_infinity values) target-specific, because whether the explicit
3
device provide both at once. We want the final name of the main
3
Integer bit is set or not varies between m68k and i386. We want to
4
input Clock to be "MAINCLK", following the hardware name.
4
be able to compile softfloat once for multiple targets, so we can't
5
Unfortunately creating an input Clock with a name X creates an
5
continue to use a single global whose value needs to be different
6
under-the-hood QOM property X; for "MAINCLK" this clashes with the
6
between targets.
7
existing UINT32 property of that name.
8
7
9
Rename the UINT32 property to MAINCLK_FRQ so it can coexist with the
8
Replace the direct uses of floatx80_infinity in target/m68k with
10
MAINCLK Clock; once the transition is complete MAINCLK_FRQ will be
9
calls to the new floatx80_default_inf() function.
11
deleted.
12
13
Commit created with:
14
perl -p -i -e 's/MAINCLK/MAINCLK_FRQ/g' hw/arm/{armsse,mps2-tz,musca}.c include/hw/arm/armsse.h
15
10
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Luc Michel <luc@lmichel.fr>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20250224111524.1101196-3-peter.maydell@linaro.org
20
Message-id: 20210128114145.20536-11-peter.maydell@linaro.org
15
Message-id: 20250217125055.160887-3-peter.maydell@linaro.org
21
Message-id: 20210121190622.22000-11-peter.maydell@linaro.org
22
---
16
---
23
include/hw/arm/armsse.h | 2 +-
17
target/m68k/softfloat.c | 47 ++++++++++++++---------------------------
24
hw/arm/armsse.c | 6 +++---
18
1 file changed, 16 insertions(+), 31 deletions(-)
25
hw/arm/mps2-tz.c | 2 +-
26
hw/arm/musca.c | 2 +-
27
4 files changed, 6 insertions(+), 6 deletions(-)
28
19
29
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
20
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
30
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/arm/armsse.h
22
--- a/target/m68k/softfloat.c
32
+++ b/include/hw/arm/armsse.h
23
+++ b/target/m68k/softfloat.c
33
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
34
* QEMU interface:
25
if ((uint64_t) (aSig << 1)) {
35
* + QOM property "memory" is a MemoryRegion containing the devices provided
26
return propagateFloatx80NaN(a, b, status);
36
* by the board model.
27
}
37
- * + QOM property "MAINCLK" is the frequency of the main system clock
28
- return packFloatx80(aSign, floatx80_infinity.high,
38
+ * + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
29
- floatx80_infinity.low);
39
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
30
+ return floatx80_default_inf(aSign, status);
40
* (In hardware, the SSE-200 permits the number of expansion interrupts
41
* for the two CPUs to be configured separately, but we restrict it to
42
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/armsse.c
45
+++ b/hw/arm/armsse.c
46
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
47
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
48
MemoryRegion *),
49
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
50
- DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
51
+ DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
52
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
53
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
54
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
55
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
56
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
57
MemoryRegion *),
58
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
59
- DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
60
+ DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
61
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
62
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
63
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
}
31
}
66
32
if (aExp == 0) {
67
if (!s->mainclk_frq) {
33
if (aSig == 0) {
68
- error_setg(errp, "MAINCLK property was not set");
34
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
69
+ error_setg(errp, "MAINCLK_FRQ property was not set");
35
float_raise(float_flag_invalid, status);
70
return;
36
return floatx80_default_nan(status);
37
}
38
- return packFloatx80(0, floatx80_infinity.high, floatx80_infinity.low);
39
+ return floatx80_default_inf(0, status);
71
}
40
}
72
41
73
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
42
if (aExp == 0 && aSig == 0) {
74
index XXXXXXX..XXXXXXX 100644
43
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
75
--- a/hw/arm/mps2-tz.c
44
if (aSign && aExp >= one_exp) {
76
+++ b/hw/arm/mps2-tz.c
45
if (aExp == one_exp && aSig == one_sig) {
77
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
46
float_raise(float_flag_divbyzero, status);
78
object_property_set_link(OBJECT(&mms->iotkit), "memory",
47
- return packFloatx80(aSign, floatx80_infinity.high,
79
OBJECT(system_memory), &error_abort);
48
- floatx80_infinity.low);
80
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
49
+ return floatx80_default_inf(aSign, status);
81
- qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
50
}
82
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
51
float_raise(float_flag_invalid, status);
83
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
52
return floatx80_default_nan(status);
84
53
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
85
/*
54
propagateFloatx80NaNOneArg(a, status);
86
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
55
}
87
index XXXXXXX..XXXXXXX 100644
56
if (aSign == 0) {
88
--- a/hw/arm/musca.c
57
- return packFloatx80(0, floatx80_infinity.high,
89
+++ b/hw/arm/musca.c
58
- floatx80_infinity.low);
90
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
59
+ return floatx80_default_inf(0, status);
91
qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
60
}
92
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
61
}
93
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
62
94
- qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
63
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
95
+ qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
64
if (aExp == 0) {
96
/*
65
if (aSig == 0) { /* zero */
97
* Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
66
float_raise(float_flag_divbyzero, status);
98
* CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
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) {
99
--
180
--
100
2.20.1
181
2.43.0
101
182
102
183
diff view generated by jsdifflib
1
As the first step in converting the CMSDK_APB_TIMER device to the
1
The global const floatx80_infinity is (unlike all the other
2
Clock framework, add a Clock input. For the moment we do nothing
2
float*_infinity values) target-specific, because whether the explicit
3
with this clock; we will change the behaviour from using the
3
Integer bit is set or not varies between m68k and i386. We want to
4
wdogclk-frq property to using the Clock once all the users of this
4
be able to compile softfloat once for multiple targets, so we can't
5
device have been converted to wire up the Clock.
5
continue to use a single global whose value needs to be different
6
between targets.
6
7
7
This is a migration compatibility break for machines mps2-an385,
8
Replace the direct uses of floatx80_infinity in target/i386 with
8
mps2-an386, mps2-an500, mps2-an511, mps2-an505, mps2-an521, musca-a,
9
calls to the new floatx80_default_inf() function. Note that because
9
musca-b1, lm3s811evb, lm3s6965evb.
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.
10
13
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20250224111524.1101196-4-peter.maydell@linaro.org
15
Message-id: 20210128114145.20536-10-peter.maydell@linaro.org
18
Message-id: 20250217125055.160887-4-peter.maydell@linaro.org
16
Message-id: 20210121190622.22000-10-peter.maydell@linaro.org
17
---
19
---
18
include/hw/watchdog/cmsdk-apb-watchdog.h | 3 +++
20
target/i386/tcg/fpu_helper.c | 7 +++----
19
hw/watchdog/cmsdk-apb-watchdog.c | 7 +++++--
21
1 file changed, 3 insertions(+), 4 deletions(-)
20
2 files changed, 8 insertions(+), 2 deletions(-)
21
22
22
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
23
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
23
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
25
--- a/target/i386/tcg/fpu_helper.c
25
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
26
+++ b/target/i386/tcg/fpu_helper.c
26
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
27
*
28
} else if (floatx80_is_infinity(ST0)) {
28
* QEMU interface:
29
fpush(env);
29
* + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
30
ST0 = ST1;
30
+ * + Clock input "WDOGCLK": clock for the watchdog's timer
31
- ST1 = floatx80_infinity;
31
* + sysbus MMIO region 0: the register bank
32
+ ST1 = floatx80_default_inf(0, &env->fp_status);
32
* + sysbus IRQ 0: watchdog interrupt
33
} else {
33
*
34
int expdif;
34
@@ -XXX,XX +XXX,XX @@
35
35
36
@@ -XXX,XX +XXX,XX @@ void helper_fscale(CPUX86State *env)
36
#include "hw/sysbus.h"
37
float_raise(float_flag_invalid, &env->fp_status);
37
#include "hw/ptimer.h"
38
ST0 = floatx80_default_nan(&env->fp_status);
38
+#include "hw/clock.h"
39
} else {
39
#include "qom/object.h"
40
- ST0 = (floatx80_is_neg(ST0) ?
40
41
- floatx80_chs(floatx80_infinity) :
41
#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
42
- floatx80_infinity);
42
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBWatchdog {
43
+ ST0 = floatx80_default_inf(floatx80_is_neg(ST0),
43
uint32_t wdogclk_frq;
44
+ &env->fp_status);
44
bool is_luminary;
45
}
45
struct ptimer_state *timer;
46
}
46
+ Clock *wdogclk;
47
} else {
47
48
uint32_t control;
49
uint32_t intstatus;
50
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/watchdog/cmsdk-apb-watchdog.c
53
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
54
@@ -XXX,XX +XXX,XX @@
55
#include "hw/irq.h"
56
#include "hw/qdev-properties.h"
57
#include "hw/registerfields.h"
58
+#include "hw/qdev-clock.h"
59
#include "hw/watchdog/cmsdk-apb-watchdog.h"
60
#include "migration/vmstate.h"
61
62
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
63
s, "cmsdk-apb-watchdog", 0x1000);
64
sysbus_init_mmio(sbd, &s->iomem);
65
sysbus_init_irq(sbd, &s->wdogint);
66
+ s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK", NULL, NULL);
67
68
s->is_luminary = false;
69
s->id = cmsdk_apb_watchdog_id;
70
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
71
72
static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
73
.name = "cmsdk-apb-watchdog",
74
- .version_id = 1,
75
- .minimum_version_id = 1,
76
+ .version_id = 2,
77
+ .minimum_version_id = 2,
78
.fields = (VMStateField[]) {
79
+ VMSTATE_CLOCK(wdogclk, CMSDKAPBWatchdog),
80
VMSTATE_PTIMER(timer, CMSDKAPBWatchdog),
81
VMSTATE_UINT32(control, CMSDKAPBWatchdog),
82
VMSTATE_UINT32(intstatus, CMSDKAPBWatchdog),
83
--
48
--
84
2.20.1
49
2.43.0
85
50
86
51
diff view generated by jsdifflib
1
Now that the watchdog device uses its Clock input rather than being
1
Unlike the other float formats, whether a floatx80 value is
2
passed the value of system_clock_scale at creation time, we can
2
considered to be an Infinity is target-dependent. (On x86 if the
3
remove the hack where we reset the STELLARIS_SYS at board creation
3
explicit integer bit is clear this is a "pseudo-infinity" and not a
4
time to force it to set system_clock_scale. Instead it will be reset
4
valid infinity; m68k does not care about the value of the integer
5
at the usual point in startup and will inform the watchdog of the
5
bit.)
6
clock frequency at that point.
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.
7
13
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Luc Michel <luc@lmichel.fr>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20250224111524.1101196-5-peter.maydell@linaro.org
12
Message-id: 20210128114145.20536-26-peter.maydell@linaro.org
13
Message-id: 20210121190622.22000-26-peter.maydell@linaro.org
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
---
18
---
16
hw/arm/stellaris.c | 10 ----------
19
include/fpu/softfloat.h | 2 +-
17
1 file changed, 10 deletions(-)
20
target/i386/tcg/fpu_helper.c | 20 +++++++++++---------
21
target/m68k/fpu_helper.c | 2 +-
22
3 files changed, 13 insertions(+), 11 deletions(-)
18
23
19
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
24
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
20
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/stellaris.c
26
--- a/include/fpu/softfloat.h
22
+++ b/hw/arm/stellaris.c
27
+++ b/include/fpu/softfloat.h
23
@@ -XXX,XX +XXX,XX @@ static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
28
@@ -XXX,XX +XXX,XX @@ static inline floatx80 floatx80_chs(floatx80 a)
24
sysbus_mmio_map(sbd, 0, base);
29
return a;
25
sysbus_connect_irq(sbd, 0, irq);
26
27
- /*
28
- * Normally we should not be resetting devices like this during
29
- * board creation. For the moment we need to do so, because
30
- * system_clock_scale will only get set when the STELLARIS_SYS
31
- * device is reset, and we need its initial value to pass to
32
- * the watchdog device. This hack can be removed once the
33
- * watchdog has been converted to use a Clock input instead.
34
- */
35
- device_cold_reset(dev);
36
-
37
return dev;
38
}
30
}
39
31
32
-static inline bool floatx80_is_infinity(floatx80 a)
33
+static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
34
{
35
#if defined(TARGET_M68K)
36
return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
37
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/i386/tcg/fpu_helper.c
40
+++ b/target/i386/tcg/fpu_helper.c
41
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
42
/* Pass this NaN through. */
43
} else if (floatx80_is_zero(ST1) && !arg0_sign) {
44
/* Pass this zero through. */
45
- } else if (((floatx80_is_infinity(ST0) && !floatx80_is_infinity(ST1)) ||
46
+ } else if (((floatx80_is_infinity(ST0, &env->fp_status) &&
47
+ !floatx80_is_infinity(ST1, &env->fp_status)) ||
48
arg0_exp - arg1_exp >= 80) &&
49
!arg0_sign) {
50
/*
51
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
52
rexp = pi_exp;
53
rsig0 = pi_sig_high;
54
rsig1 = pi_sig_low;
55
- } else if (floatx80_is_infinity(ST1)) {
56
- if (floatx80_is_infinity(ST0)) {
57
+ } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
58
+ if (floatx80_is_infinity(ST0, &env->fp_status)) {
59
if (arg0_sign) {
60
rexp = pi_34_exp;
61
rsig0 = pi_34_sig_high;
62
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
63
rexp = pi_2_exp;
64
rsig0 = pi_2_sig_high;
65
rsig1 = pi_2_sig_low;
66
- } else if (floatx80_is_infinity(ST0) || arg0_exp - arg1_exp >= 80) {
67
+ } else if (floatx80_is_infinity(ST0, &env->fp_status) ||
68
+ arg0_exp - arg1_exp >= 80) {
69
/* ST0 is negative. */
70
rexp = pi_exp;
71
rsig0 = pi_sig_high;
72
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
73
}
74
fpush(env);
75
ST0 = ST1;
76
- } else if (floatx80_is_infinity(ST0)) {
77
+ } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
78
fpush(env);
79
ST0 = ST1;
80
ST1 = floatx80_default_inf(0, &env->fp_status);
81
@@ -XXX,XX +XXX,XX @@ void helper_fyl2x(CPUX86State *env)
82
} else if (arg0_sign && !floatx80_is_zero(ST0)) {
83
float_raise(float_flag_invalid, &env->fp_status);
84
ST1 = floatx80_default_nan(&env->fp_status);
85
- } else if (floatx80_is_infinity(ST1)) {
86
+ } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
87
FloatRelation cmp = floatx80_compare(ST0, floatx80_one,
88
&env->fp_status);
89
switch (cmp) {
90
@@ -XXX,XX +XXX,XX @@ void helper_fyl2x(CPUX86State *env)
91
ST1 = floatx80_default_nan(&env->fp_status);
92
break;
93
}
94
- } else if (floatx80_is_infinity(ST0)) {
95
+ } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
96
if (floatx80_is_zero(ST1)) {
97
float_raise(float_flag_invalid, &env->fp_status);
98
ST1 = floatx80_default_nan(&env->fp_status);
99
@@ -XXX,XX +XXX,XX @@ void helper_fscale(CPUX86State *env)
100
float_raise(float_flag_invalid, &env->fp_status);
101
ST0 = floatx80_silence_nan(ST0, &env->fp_status);
102
}
103
- } else if (floatx80_is_infinity(ST1) &&
104
+ } else if (floatx80_is_infinity(ST1, &env->fp_status) &&
105
!floatx80_invalid_encoding(ST0) &&
106
!floatx80_is_any_nan(ST0)) {
107
if (floatx80_is_neg(ST1)) {
108
- if (floatx80_is_infinity(ST0)) {
109
+ if (floatx80_is_infinity(ST0, &env->fp_status)) {
110
float_raise(float_flag_invalid, &env->fp_status);
111
ST0 = floatx80_default_nan(&env->fp_status);
112
} else {
113
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/m68k/fpu_helper.c
116
+++ b/target/m68k/fpu_helper.c
117
@@ -XXX,XX +XXX,XX @@ void HELPER(ftst)(CPUM68KState *env, FPReg *val)
118
119
if (floatx80_is_any_nan(val->d)) {
120
cc |= FPSR_CC_A;
121
- } else if (floatx80_is_infinity(val->d)) {
122
+ } else if (floatx80_is_infinity(val->d, &env->fp_status)) {
123
cc |= FPSR_CC_I;
124
} else if (floatx80_is_zero(val->d)) {
125
cc |= FPSR_CC_Z;
40
--
126
--
41
2.20.1
127
2.43.0
42
128
43
129
diff view generated by jsdifflib
1
The ptimer API currently provides two methods for setting the period:
1
In Intel terminology, a floatx80 Infinity with the explicit integer
2
ptimer_set_period(), which takes a period in nanoseconds, and
2
bit clear is a "pseudo-infinity"; for x86 these are not valid
3
ptimer_set_freq(), which takes a frequency in Hz. Neither of these
3
infinity values. m68k is looser and does not care whether the
4
lines up nicely with the Clock API, because although both the Clock
4
Integer bit is set or clear in an infinity.
5
and the ptimer track the frequency using a representation of whole
6
and fractional nanoseconds, conversion via either period-in-ns or
7
frequency-in-Hz will introduce a rounding error.
8
5
9
Add a new function ptimer_set_period_from_clock() which takes the
6
Move this setting to runtime rather than using an ifdef in
10
Clock object directly to avoid the rounding issues. This includes a
7
floatx80_is_infinity().
11
facility for the user to specify that there is a frequency divider
12
between the Clock proper and the timer, as some timer devices like
13
the CMSDK APB dualtimer need this.
14
8
15
To avoid having to drag in clock.h from ptimer.h we add the Clock
9
Since this was the last use of the floatx80_infinity global constant,
16
type to typedefs.h.
10
we remove it and its definition here.
17
11
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Luc Michel <luc@lmichel.fr>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
21
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20250224111524.1101196-6-peter.maydell@linaro.org
22
Message-id: 20210128114145.20536-2-peter.maydell@linaro.org
16
Message-id: 20250217125055.160887-5-peter.maydell@linaro.org
23
Message-id: 20210121190622.22000-2-peter.maydell@linaro.org
24
---
17
---
25
include/hw/ptimer.h | 22 ++++++++++++++++++++++
18
include/fpu/softfloat-types.h | 5 +++++
26
include/qemu/typedefs.h | 1 +
19
include/fpu/softfloat.h | 18 +++++++++++-------
27
hw/core/ptimer.c | 34 ++++++++++++++++++++++++++++++++++
20
target/m68k/cpu.c | 4 +++-
28
3 files changed, 57 insertions(+)
21
fpu/softfloat-specialize.c.inc | 10 ----------
22
4 files changed, 19 insertions(+), 18 deletions(-)
29
23
30
diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
24
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
31
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/ptimer.h
26
--- a/include/fpu/softfloat-types.h
33
+++ b/include/hw/ptimer.h
27
+++ b/include/fpu/softfloat-types.h
34
@@ -XXX,XX +XXX,XX @@ void ptimer_transaction_commit(ptimer_state *s);
28
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
35
*/
29
typedef enum __attribute__((__packed__)) {
36
void ptimer_set_period(ptimer_state *s, int64_t period);
30
/* In the default Infinity value, is the Integer bit 0 ? */
37
31
floatx80_default_inf_int_bit_is_zero = 1,
38
+/**
32
+ /*
39
+ * ptimer_set_period_from_clock - Set counter increment from a Clock
33
+ * Are Pseudo-infinities (Inf with the Integer bit zero) valid?
40
+ * @s: ptimer to configure
34
+ * If so, floatx80_is_infinity() will return true for them.
41
+ * @clk: pointer to Clock object to take period from
35
+ */
42
+ * @divisor: value to scale the clock frequency down by
36
+ floatx80_pseudo_inf_valid = 2,
43
+ *
37
} FloatX80Behaviour;
44
+ * If the ptimer is being driven from a Clock, this is the preferred
38
45
+ * way to tell the ptimer about the period, because it avoids any
39
/*
46
+ * possible rounding errors that might happen if the internal
40
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
47
+ * representation of the Clock period was converted to either a period
41
index XXXXXXX..XXXXXXX 100644
48
+ * in ns or a frequency in Hz.
42
--- a/include/fpu/softfloat.h
49
+ *
43
+++ b/include/fpu/softfloat.h
50
+ * If the ptimer should run at the same frequency as the clock,
44
@@ -XXX,XX +XXX,XX @@ float128 floatx80_to_float128(floatx80, float_status *status);
51
+ * pass 1 as the @divisor; if the ptimer should run at half the
45
/*----------------------------------------------------------------------------
52
+ * frequency, pass 2, and so on.
46
| The pattern for an extended double-precision inf.
53
+ *
47
*----------------------------------------------------------------------------*/
54
+ * This function will assert if it is called outside a
48
-extern const floatx80 floatx80_infinity;
55
+ * ptimer_transaction_begin/commit block.
49
floatx80 floatx80_default_inf(bool zSign, float_status *status);
56
+ */
50
57
+void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clock,
51
/*----------------------------------------------------------------------------
58
+ unsigned int divisor);
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;
59
+
67
+
60
/**
68
+ if (!intbit &&
61
* ptimer_set_freq - Set counter frequency in Hz
69
+ !(status->floatx80_behaviour & floatx80_pseudo_inf_valid)) {
62
* @s: ptimer to configure
70
+ return false;
63
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
71
+ }
72
+ return (a.high & 0x7fff) == 0x7fff && !(a.low << 1);
73
}
74
75
static inline bool floatx80_is_neg(floatx80 a)
76
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
64
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
65
--- a/include/qemu/typedefs.h
78
--- a/target/m68k/cpu.c
66
+++ b/include/qemu/typedefs.h
79
+++ b/target/m68k/cpu.c
67
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDriverState BlockDriverState;
80
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
68
typedef struct BusClass BusClass;
81
/*
69
typedef struct BusState BusState;
82
* m68k-specific floatx80 behaviour:
70
typedef struct Chardev Chardev;
83
* * default Infinity values have a zero Integer bit
71
+typedef struct Clock Clock;
84
+ * * input Infinities may have the Integer bit either 0 or 1
72
typedef struct CompatProperty CompatProperty;
85
*/
73
typedef struct CoMutex CoMutex;
86
- set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
74
typedef struct CPUAddressSpace CPUAddressSpace;
87
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
75
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
88
+ floatx80_pseudo_inf_valid,
89
&env->fp_status);
90
91
nan = floatx80_default_nan(&env->fp_status);
92
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
76
index XXXXXXX..XXXXXXX 100644
93
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/core/ptimer.c
94
--- a/fpu/softfloat-specialize.c.inc
78
+++ b/hw/core/ptimer.c
95
+++ b/fpu/softfloat-specialize.c.inc
79
@@ -XXX,XX +XXX,XX @@
96
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_default_inf(bool zSign, float_status *status)
80
#include "sysemu/qtest.h"
97
return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
81
#include "block/aio.h"
82
#include "sysemu/cpus.h"
83
+#include "hw/clock.h"
84
85
#define DELTA_ADJUST 1
86
#define DELTA_NO_ADJUST -1
87
@@ -XXX,XX +XXX,XX @@ void ptimer_set_period(ptimer_state *s, int64_t period)
88
}
89
}
98
}
90
99
91
+/* Set counter increment interval from a Clock */
100
-#define floatx80_infinity_high 0x7FFF
92
+void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clk,
101
-#if defined(TARGET_M68K)
93
+ unsigned int divisor)
102
-#define floatx80_infinity_low UINT64_C(0x0000000000000000)
94
+{
103
-#else
95
+ /*
104
-#define floatx80_infinity_low UINT64_C(0x8000000000000000)
96
+ * The raw clock period is a 64-bit value in units of 2^-32 ns;
105
-#endif
97
+ * put another way it's a 32.32 fixed-point ns value. Our internal
106
-
98
+ * representation of the period is 64.32 fixed point ns, so
107
-const floatx80 floatx80_infinity
99
+ * the conversion is simple.
108
- = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low);
100
+ */
109
-
101
+ uint64_t raw_period = clock_get(clk);
110
/*----------------------------------------------------------------------------
102
+ uint64_t period_frac;
111
| Returns 1 if the half-precision floating-point value `a' is a quiet
103
+
112
| NaN; otherwise returns 0.
104
+ assert(s->in_transaction);
105
+ s->delta = ptimer_get_count(s);
106
+ s->period = extract64(raw_period, 32, 32);
107
+ period_frac = extract64(raw_period, 0, 32);
108
+ /*
109
+ * divisor specifies a possible frequency divisor between the
110
+ * clock and the timer, so it is a multiplier on the period.
111
+ * We do the multiply after splitting the raw period out into
112
+ * period and frac to avoid having to do a 32*64->96 multiply.
113
+ */
114
+ s->period *= divisor;
115
+ period_frac *= divisor;
116
+ s->period += extract64(period_frac, 32, 32);
117
+ s->period_frac = (uint32_t)period_frac;
118
+
119
+ if (s->enabled) {
120
+ s->need_reload = true;
121
+ }
122
+}
123
+
124
/* Set counter frequency in Hz. */
125
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
126
{
127
--
113
--
128
2.20.1
114
2.43.0
129
115
130
116
diff view generated by jsdifflib
1
Create and connect the two clocks needed by the ARMSSE.
1
The definition of which floatx80 encodings are invalid is
2
target-specific. Currently we handle this with an ifdef, but we
3
would like to defer this decision to runtime. In preparation, pass a
4
float_status argument to floatx80_invalid_encoding().
5
6
We will change the implementation from ifdef to looking at
7
the status argument in the following commit.
2
8
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20250224111524.1101196-7-peter.maydell@linaro.org
7
Message-id: 20210128114145.20536-15-peter.maydell@linaro.org
8
Message-id: 20210121190622.22000-15-peter.maydell@linaro.org
9
---
13
---
10
hw/arm/mps2-tz.c | 13 +++++++++++++
14
include/fpu/softfloat.h | 2 +-
11
1 file changed, 13 insertions(+)
15
fpu/softfloat.c | 2 +-
16
target/i386/tcg/fpu_helper.c | 24 +++++++++++++-----------
17
3 files changed, 15 insertions(+), 13 deletions(-)
12
18
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
19
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
21
--- a/include/fpu/softfloat.h
16
+++ b/hw/arm/mps2-tz.c
22
+++ b/include/fpu/softfloat.h
17
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
18
#include "hw/net/lan9118.h"
24
| pseudo-denormals, which must still be correctly handled as inputs even
19
#include "net/net.h"
25
| if they are never generated as outputs.
20
#include "hw/core/split-irq.h"
26
*----------------------------------------------------------------------------*/
21
+#include "hw/qdev-clock.h"
27
-static inline bool floatx80_invalid_encoding(floatx80 a)
22
#include "qom/object.h"
28
+static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
23
29
{
24
#define MPS2TZ_NUMIRQ 92
30
#if defined(TARGET_M68K)
25
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
31
/*-------------------------------------------------------------------------
26
qemu_or_irq uart_irq_orgate;
32
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
27
DeviceState *lan9118;
33
index XXXXXXX..XXXXXXX 100644
28
SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
34
--- a/fpu/softfloat.c
29
+ Clock *sysclk;
35
+++ b/fpu/softfloat.c
30
+ Clock *s32kclk;
36
@@ -XXX,XX +XXX,XX @@ static bool floatx80_unpack_canonical(FloatParts128 *p, floatx80 f,
31
};
37
g_assert_not_reached();
32
33
#define TYPE_MPS2TZ_MACHINE "mps2tz"
34
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
35
36
/* Main SYSCLK frequency in Hz */
37
#define SYSCLK_FRQ 20000000
38
+/* Slow 32Khz S32KCLK frequency in Hz */
39
+#define S32KCLK_FRQ (32 * 1000)
40
41
/* Create an alias of an entire original MemoryRegion @orig
42
* located at @base in the memory map.
43
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
44
exit(EXIT_FAILURE);
45
}
38
}
46
39
47
+ /* These clocks don't need migration because they are fixed-frequency */
40
- if (unlikely(floatx80_invalid_encoding(f))) {
48
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
41
+ if (unlikely(floatx80_invalid_encoding(f, s))) {
49
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
42
float_raise(float_flag_invalid, s);
50
+ mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
43
return false;
51
+ clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
44
}
52
+
45
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
53
object_initialize_child(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit,
46
index XXXXXXX..XXXXXXX 100644
54
mmc->armsse_type);
47
--- a/target/i386/tcg/fpu_helper.c
55
iotkitdev = DEVICE(&mms->iotkit);
48
+++ b/target/i386/tcg/fpu_helper.c
56
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
49
@@ -XXX,XX +XXX,XX @@ void helper_f2xm1(CPUX86State *env)
57
OBJECT(system_memory), &error_abort);
50
int32_t exp = extractFloatx80Exp(ST0);
58
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
51
bool sign = extractFloatx80Sign(ST0);
59
qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
52
60
+ qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
53
- if (floatx80_invalid_encoding(ST0)) {
61
+ qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
54
+ if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
62
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
55
float_raise(float_flag_invalid, &env->fp_status);
63
56
ST0 = floatx80_default_nan(&env->fp_status);
64
/*
57
} else if (floatx80_is_any_nan(ST0)) {
58
@@ -XXX,XX +XXX,XX @@ void helper_fpatan(CPUX86State *env)
59
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
60
float_raise(float_flag_invalid, &env->fp_status);
61
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
62
- } else if (floatx80_invalid_encoding(ST0) ||
63
- floatx80_invalid_encoding(ST1)) {
64
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
65
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
66
float_raise(float_flag_invalid, &env->fp_status);
67
ST1 = floatx80_default_nan(&env->fp_status);
68
} else if (floatx80_is_any_nan(ST0)) {
69
@@ -XXX,XX +XXX,XX @@ void helper_fxtract(CPUX86State *env)
70
&env->fp_status);
71
fpush(env);
72
ST0 = temp.d;
73
- } else if (floatx80_invalid_encoding(ST0)) {
74
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
75
float_raise(float_flag_invalid, &env->fp_status);
76
ST0 = floatx80_default_nan(&env->fp_status);
77
fpush(env);
78
@@ -XXX,XX +XXX,XX @@ static void helper_fprem_common(CPUX86State *env, bool mod)
79
env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
80
if (floatx80_is_zero(ST0) || floatx80_is_zero(ST1) ||
81
exp0 == 0x7fff || exp1 == 0x7fff ||
82
- floatx80_invalid_encoding(ST0) || floatx80_invalid_encoding(ST1)) {
83
+ floatx80_invalid_encoding(ST0, &env->fp_status) ||
84
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
85
ST0 = floatx80_modrem(ST0, ST1, mod, &quotient, &env->fp_status);
86
} else {
87
if (exp0 == 0) {
88
@@ -XXX,XX +XXX,XX @@ void helper_fyl2xp1(CPUX86State *env)
89
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
90
float_raise(float_flag_invalid, &env->fp_status);
91
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
92
- } else if (floatx80_invalid_encoding(ST0) ||
93
- floatx80_invalid_encoding(ST1)) {
94
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
95
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
96
float_raise(float_flag_invalid, &env->fp_status);
97
ST1 = floatx80_default_nan(&env->fp_status);
98
} else if (floatx80_is_any_nan(ST0)) {
99
@@ -XXX,XX +XXX,XX @@ void helper_fyl2x(CPUX86State *env)
100
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
101
float_raise(float_flag_invalid, &env->fp_status);
102
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
103
- } else if (floatx80_invalid_encoding(ST0) ||
104
- floatx80_invalid_encoding(ST1)) {
105
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
106
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
107
float_raise(float_flag_invalid, &env->fp_status);
108
ST1 = floatx80_default_nan(&env->fp_status);
109
} else if (floatx80_is_any_nan(ST0)) {
110
@@ -XXX,XX +XXX,XX @@ void helper_frndint(CPUX86State *env)
111
void helper_fscale(CPUX86State *env)
112
{
113
uint8_t old_flags = save_exception_flags(env);
114
- if (floatx80_invalid_encoding(ST1) || floatx80_invalid_encoding(ST0)) {
115
+ if (floatx80_invalid_encoding(ST1, &env->fp_status) ||
116
+ floatx80_invalid_encoding(ST0, &env->fp_status)) {
117
float_raise(float_flag_invalid, &env->fp_status);
118
ST0 = floatx80_default_nan(&env->fp_status);
119
} else if (floatx80_is_any_nan(ST1)) {
120
@@ -XXX,XX +XXX,XX @@ void helper_fscale(CPUX86State *env)
121
ST0 = floatx80_silence_nan(ST0, &env->fp_status);
122
}
123
} else if (floatx80_is_infinity(ST1, &env->fp_status) &&
124
- !floatx80_invalid_encoding(ST0) &&
125
+ !floatx80_invalid_encoding(ST0, &env->fp_status) &&
126
!floatx80_is_any_nan(ST0)) {
127
if (floatx80_is_neg(ST1)) {
128
if (floatx80_is_infinity(ST0, &env->fp_status)) {
65
--
129
--
66
2.20.1
130
2.43.0
67
131
68
132
diff view generated by jsdifflib
1
Now that the CMSDK APB watchdog uses its Clock input, it will
1
Because floatx80 has an explicit integer bit, this permits some
2
correctly respond when the system clock frequency is changed using
2
odd encodings where the integer bit is not set correctly for the
3
the RCC register on in the Stellaris board system registers. Test
3
floating point value type. In In Intel terminology the
4
that when the RCC register is written it causes the watchdog timer to
4
categories are:
5
change speed.
5
exp == 0, int = 0, mantissa == 0 : zeroes
6
exp == 0, int = 0, mantissa != 0 : denormals
7
exp == 0, int = 1 : pseudo-denormals
8
0 < exp < 0x7fff, int = 0 : unnormals
9
0 < exp < 0x7fff, int = 1 : normals
10
exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
11
exp == 0x7fff, int = 1, mantissa == 0 : infinities
12
exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
13
exp == 0x7fff, int = 1, mantissa == 0 : NaNs
14
15
The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
16
x87 permits as input also pseudo-denormals.
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.
6
27
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Luc Michel <luc@lmichel.fr>
30
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
31
Message-id: 20250224111524.1101196-8-peter.maydell@linaro.org
11
Message-id: 20210128114145.20536-22-peter.maydell@linaro.org
32
Message-id: 20250217125055.160887-6-peter.maydell@linaro.org
12
Message-id: 20210121190622.22000-22-peter.maydell@linaro.org
13
---
33
---
14
tests/qtest/cmsdk-apb-watchdog-test.c | 52 +++++++++++++++++++++++++++
34
include/fpu/softfloat-types.h | 14 ++++++++
15
1 file changed, 52 insertions(+)
35
include/fpu/softfloat.h | 68 ++++++++++++++++++-----------------
36
target/m68k/cpu.c | 28 ++++++++++++++-
37
3 files changed, 77 insertions(+), 33 deletions(-)
16
38
17
diff --git a/tests/qtest/cmsdk-apb-watchdog-test.c b/tests/qtest/cmsdk-apb-watchdog-test.c
39
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
18
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qtest/cmsdk-apb-watchdog-test.c
41
--- a/include/fpu/softfloat-types.h
20
+++ b/tests/qtest/cmsdk-apb-watchdog-test.c
42
+++ b/include/fpu/softfloat-types.h
21
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
22
*/
44
/*
23
45
* Are Pseudo-infinities (Inf with the Integer bit zero) valid?
24
#include "qemu/osdep.h"
46
* If so, floatx80_is_infinity() will return true for them.
25
+#include "qemu/bitops.h"
47
+ * If not, floatx80_invalid_encoding will return false for them,
26
#include "libqtest-single.h"
48
+ * and using them as inputs to a float op will raise Invalid.
49
*/
50
floatx80_pseudo_inf_valid = 2,
51
+ /*
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;
27
64
28
/*
65
/*
29
@@ -XXX,XX +XXX,XX @@
66
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
30
#define WDOGMIS 0x14
67
index XXXXXXX..XXXXXXX 100644
31
#define WDOGLOCK 0xc00
68
--- a/include/fpu/softfloat.h
32
69
+++ b/include/fpu/softfloat.h
33
+#define SSYS_BASE 0x400fe000
70
@@ -XXX,XX +XXX,XX @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
34
+#define RCC 0x60
71
35
+#define SYSDIV_SHIFT 23
72
/*----------------------------------------------------------------------------
36
+#define SYSDIV_LENGTH 4
73
| Return whether the given value is an invalid floatx80 encoding.
74
-| Invalid floatx80 encodings arise when the integer bit is not set, but
75
-| the exponent is not zero. The only times the integer bit is permitted to
76
-| be zero is in subnormal numbers and the value zero.
77
-| This includes what the Intel software developer's manual calls pseudo-NaNs,
78
-| pseudo-infinities and un-normal numbers. It does not include
79
-| pseudo-denormals, which must still be correctly handled as inputs even
80
-| if they are never generated as outputs.
81
+| Invalid floatx80 encodings may arise when the integer bit is not set
82
+| correctly; this is target-specific. In Intel terminology the
83
+| categories are:
84
+| exp == 0, int = 0, mantissa == 0 : zeroes
85
+| exp == 0, int = 0, mantissa != 0 : denormals
86
+| exp == 0, int = 1 : pseudo-denormals
87
+| 0 < exp < 0x7fff, int = 0 : unnormals
88
+| 0 < exp < 0x7fff, int = 1 : normals
89
+| exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
90
+| exp == 0x7fff, int = 1, mantissa == 0 : infinities
91
+| exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
92
+| exp == 0x7fff, int = 1, mantissa == 0 : NaNs
93
+|
94
+| The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
95
+| x87 permits as input also pseudo-denormals.
96
+| m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
97
+|
98
+| Since we don't have a target that handles floatx80 but prohibits
99
+| pseudo-denormals in input, we don't currently have a floatx80_behaviour
100
+| flag for that case, but instead always accept it. Conveniently this
101
+| means that all cases with either exponent 0 or the integer bit set are
102
+| valid for all targets.
103
*----------------------------------------------------------------------------*/
104
static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
105
{
106
-#if defined(TARGET_M68K)
107
- /*-------------------------------------------------------------------------
108
- | With m68k, the explicit integer bit can be zero in the case of:
109
- | - zeros (exp == 0, mantissa == 0)
110
- | - denormalized numbers (exp == 0, mantissa != 0)
111
- | - unnormalized numbers (exp != 0, exp < 0x7FFF)
112
- | - infinities (exp == 0x7FFF, mantissa == 0)
113
- | - not-a-numbers (exp == 0x7FFF, mantissa != 0)
114
- |
115
- | For infinities and NaNs, the explicit integer bit can be either one or
116
- | zero.
117
- |
118
- | The IEEE 754 standard does not define a zero integer bit. Such a number
119
- | is an unnormalized number. Hardware does not directly support
120
- | denormalized and unnormalized numbers, but implicitly supports them by
121
- | trapping them as unimplemented data types, allowing efficient conversion
122
- | in software.
123
- |
124
- | See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
125
- | "1.6 FLOATING-POINT DATA TYPES"
126
- *------------------------------------------------------------------------*/
127
- return false;
128
-#else
129
- return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0;
130
-#endif
131
+ if ((a.low >> 63) || (a.high & 0x7fff) == 0) {
132
+ /* Anything with the Integer bit set or the exponent 0 is valid */
133
+ return false;
134
+ }
37
+
135
+
38
static void test_watchdog(void)
136
+ if ((a.high & 0x7fff) == 0x7fff) {
39
{
137
+ if (a.low) {
40
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
138
+ return !(s->floatx80_behaviour & floatx80_pseudo_nan_valid);
41
@@ -XXX,XX +XXX,XX @@ static void test_watchdog(void)
139
+ } else {
42
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
140
+ return !(s->floatx80_behaviour & floatx80_pseudo_inf_valid);
141
+ }
142
+ } else {
143
+ return !(s->floatx80_behaviour & floatx80_unnormal_valid);
144
+ }
43
}
145
}
44
146
45
+static void test_clock_change(void)
147
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
46
+{
148
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
47
+ uint32_t rcc;
149
index XXXXXXX..XXXXXXX 100644
48
+
150
--- a/target/m68k/cpu.c
49
+ /*
151
+++ b/target/m68k/cpu.c
50
+ * Test that writing to the stellaris board's RCC register to
152
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
51
+ * change the system clock frequency causes the watchdog
153
* m68k-specific floatx80 behaviour:
52
+ * to change the speed it counts at.
154
* * default Infinity values have a zero Integer bit
53
+ */
155
* * input Infinities may have the Integer bit either 0 or 1
54
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
156
+ * * pseudo-denormals supported for input and output
55
+
157
+ * * don't raise Invalid for pseudo-NaN/pseudo-Inf/Unnormal
56
+ writel(WDOG_BASE + WDOGCONTROL, 1);
158
+ *
57
+ writel(WDOG_BASE + WDOGLOAD, 1000);
159
+ * With m68k, the explicit integer bit can be zero in the case of:
58
+
160
+ * - zeros (exp == 0, mantissa == 0)
59
+ /* Step to just past the 500th tick */
161
+ * - denormalized numbers (exp == 0, mantissa != 0)
60
+ clock_step(80 * 500 + 1);
162
+ * - unnormalized numbers (exp != 0, exp < 0x7FFF)
61
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
163
+ * - infinities (exp == 0x7FFF, mantissa == 0)
62
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
164
+ * - not-a-numbers (exp == 0x7FFF, mantissa != 0)
63
+
165
+ *
64
+ /* Rewrite RCC.SYSDIV from 16 to 8, so the clock is now 40ns per tick */
166
+ * For infinities and NaNs, the explicit integer bit can be either one or
65
+ rcc = readl(SSYS_BASE + RCC);
167
+ * zero.
66
+ g_assert_cmpuint(extract32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH), ==, 0xf);
168
+ *
67
+ rcc = deposit32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH, 7);
169
+ * The IEEE 754 standard does not define a zero integer bit. Such a number
68
+ writel(SSYS_BASE + RCC, rcc);
170
+ * is an unnormalized number. Hardware does not directly support
69
+
171
+ * denormalized and unnormalized numbers, but implicitly supports them by
70
+ /* Just past the 1000th tick: timer should have fired */
172
+ * trapping them as unimplemented data types, allowing efficient conversion
71
+ clock_step(40 * 500);
173
+ * in software.
72
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
174
+ *
73
+
175
+ * See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
74
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0);
176
+ * "1.6 FLOATING-POINT DATA TYPES"
75
+
177
+ *
76
+ /* VALUE reloads at following tick */
178
+ * Note though that QEMU's fp emulation does directly handle both
77
+ clock_step(41);
179
+ * denormal and unnormal values, and does not trap to guest software.
78
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
180
*/
79
+
181
set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
80
+ /* Writing any value to WDOGINTCLR clears the interrupt and reloads */
182
- floatx80_pseudo_inf_valid,
81
+ clock_step(40 * 500);
183
+ floatx80_pseudo_inf_valid |
82
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
184
+ floatx80_pseudo_nan_valid |
83
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
185
+ floatx80_unnormal_valid,
84
+ writel(WDOG_BASE + WDOGINTCLR, 0);
186
&env->fp_status);
85
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
187
86
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
188
nan = floatx80_default_nan(&env->fp_status);
87
+}
88
+
89
int main(int argc, char **argv)
90
{
91
int r;
92
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
93
qtest_start("-machine lm3s811evb");
94
95
qtest_add_func("/cmsdk-apb-watchdog/watchdog", test_watchdog);
96
+ qtest_add_func("/cmsdk-apb-watchdog/watchdog_clock_change",
97
+ test_clock_change);
98
99
r = g_test_run();
100
101
--
189
--
102
2.20.1
190
2.43.0
103
191
104
192
diff view generated by jsdifflib
1
Convert the SSYS code in the Stellaris boards (which encapsulates the
1
Currently we compile-time set an 'm68k_denormal' flag in the FloatFmt
2
system registers) to a proper QOM device. This will provide us with
2
for floatx80 for m68k. This controls our handling of what the Intel
3
somewhere to put the output Clock whose frequency depends on the
3
documentation calls a "pseudo-denormal": a value where the exponent
4
setting of the PLL configuration registers.
4
field is zero and the explicit integer bit is set.
5
5
6
This is a migration compatibility break for lm3s811evb, lm3s6965evb.
6
For x86, the x87 FPU is supposed to accept a pseudo-denormal as
7
input, but never generate one on output. For m68k, these values are
8
permitted on input and may be produced on output.
7
9
8
We use 3-phase reset here because the Clock will need to propagate
10
Replace the flag in the FloatFmt with a flag indicating whether the
9
its value in the hold phase.
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.
10
15
11
For the moment we reset the device during the board creation so that
16
As far as I can see from the code we don't actually handle the
12
the system_clock_scale global gets set; this will be removed in a
17
x86-mandated "accept on input but don't generate" behaviour, because
13
subsequent commit.
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.
14
22
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Luc Michel <luc@lmichel.fr>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
26
Message-id: 20250224111524.1101196-9-peter.maydell@linaro.org
19
Message-id: 20210128114145.20536-17-peter.maydell@linaro.org
27
Message-id: 20250217125055.160887-7-peter.maydell@linaro.org
20
Message-id: 20210121190622.22000-17-peter.maydell@linaro.org
21
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
---
28
---
23
hw/arm/stellaris.c | 132 ++++++++++++++++++++++++++++++++++++---------
29
include/fpu/softfloat-types.h | 19 +++++++++++++++++++
24
1 file changed, 107 insertions(+), 25 deletions(-)
30
fpu/softfloat.c | 9 ++++-----
31
target/m68k/cpu.c | 3 ++-
32
fpu/softfloat-parts.c.inc | 27 ++++++++++++++++++++++++---
33
4 files changed, 49 insertions(+), 9 deletions(-)
25
34
26
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
35
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
27
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/stellaris.c
37
--- a/include/fpu/softfloat-types.h
29
+++ b/hw/arm/stellaris.c
38
+++ b/include/fpu/softfloat-types.h
30
@@ -XXX,XX +XXX,XX @@ static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
39
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
31
40
* and using them as inputs to a float op will raise Invalid.
32
/* System controller. */
41
*/
33
42
floatx80_unnormal_valid = 8,
34
-typedef struct {
35
+#define TYPE_STELLARIS_SYS "stellaris-sys"
36
+OBJECT_DECLARE_SIMPLE_TYPE(ssys_state, STELLARIS_SYS)
37
+
38
+struct ssys_state {
39
+ SysBusDevice parent_obj;
40
+
41
MemoryRegion iomem;
42
uint32_t pborctl;
43
uint32_t ldopctl;
44
@@ -XXX,XX +XXX,XX @@ typedef struct {
45
uint32_t dcgc[3];
46
uint32_t clkvclr;
47
uint32_t ldoarst;
48
+ qemu_irq irq;
49
+ /* Properties (all read-only registers) */
50
uint32_t user0;
51
uint32_t user1;
52
- qemu_irq irq;
53
- stellaris_board_info *board;
54
-} ssys_state;
55
+ uint32_t did0;
56
+ uint32_t did1;
57
+ uint32_t dc0;
58
+ uint32_t dc1;
59
+ uint32_t dc2;
60
+ uint32_t dc3;
61
+ uint32_t dc4;
62
+};
63
64
static void ssys_update(ssys_state *s)
65
{
66
@@ -XXX,XX +XXX,XX @@ static uint32_t pllcfg_fury[16] = {
67
68
static int ssys_board_class(const ssys_state *s)
69
{
70
- uint32_t did0 = s->board->did0;
71
+ uint32_t did0 = s->did0;
72
switch (did0 & DID0_VER_MASK) {
73
case DID0_VER_0:
74
return DID0_CLASS_SANDSTORM;
75
@@ -XXX,XX +XXX,XX @@ static uint64_t ssys_read(void *opaque, hwaddr offset,
76
77
switch (offset) {
78
case 0x000: /* DID0 */
79
- return s->board->did0;
80
+ return s->did0;
81
case 0x004: /* DID1 */
82
- return s->board->did1;
83
+ return s->did1;
84
case 0x008: /* DC0 */
85
- return s->board->dc0;
86
+ return s->dc0;
87
case 0x010: /* DC1 */
88
- return s->board->dc1;
89
+ return s->dc1;
90
case 0x014: /* DC2 */
91
- return s->board->dc2;
92
+ return s->dc2;
93
case 0x018: /* DC3 */
94
- return s->board->dc3;
95
+ return s->dc3;
96
case 0x01c: /* DC4 */
97
- return s->board->dc4;
98
+ return s->dc4;
99
case 0x030: /* PBORCTL */
100
return s->pborctl;
101
case 0x034: /* LDOPCTL */
102
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps ssys_ops = {
103
.endianness = DEVICE_NATIVE_ENDIAN,
104
};
105
106
-static void ssys_reset(void *opaque)
107
+static void stellaris_sys_reset_enter(Object *obj, ResetType type)
108
{
109
- ssys_state *s = (ssys_state *)opaque;
110
+ ssys_state *s = STELLARIS_SYS(obj);
111
112
s->pborctl = 0x7ffd;
113
s->rcc = 0x078e3ac0;
114
@@ -XXX,XX +XXX,XX @@ static void ssys_reset(void *opaque)
115
s->rcgc[0] = 1;
116
s->scgc[0] = 1;
117
s->dcgc[0] = 1;
118
+}
119
+
120
+static void stellaris_sys_reset_hold(Object *obj)
121
+{
122
+ ssys_state *s = STELLARIS_SYS(obj);
123
+
124
ssys_calculate_system_clock(s);
125
}
126
127
+static void stellaris_sys_reset_exit(Object *obj)
128
+{
129
+}
130
+
131
static int stellaris_sys_post_load(void *opaque, int version_id)
132
{
133
ssys_state *s = opaque;
134
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_sys = {
135
}
136
};
137
138
+static Property stellaris_sys_properties[] = {
139
+ DEFINE_PROP_UINT32("user0", ssys_state, user0, 0),
140
+ DEFINE_PROP_UINT32("user1", ssys_state, user1, 0),
141
+ DEFINE_PROP_UINT32("did0", ssys_state, did0, 0),
142
+ DEFINE_PROP_UINT32("did1", ssys_state, did1, 0),
143
+ DEFINE_PROP_UINT32("dc0", ssys_state, dc0, 0),
144
+ DEFINE_PROP_UINT32("dc1", ssys_state, dc1, 0),
145
+ DEFINE_PROP_UINT32("dc2", ssys_state, dc2, 0),
146
+ DEFINE_PROP_UINT32("dc3", ssys_state, dc3, 0),
147
+ DEFINE_PROP_UINT32("dc4", ssys_state, dc4, 0),
148
+ DEFINE_PROP_END_OF_LIST()
149
+};
150
+
151
+static void stellaris_sys_instance_init(Object *obj)
152
+{
153
+ ssys_state *s = STELLARIS_SYS(obj);
154
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
155
+
156
+ memory_region_init_io(&s->iomem, obj, &ssys_ops, s, "ssys", 0x00001000);
157
+ sysbus_init_mmio(sbd, &s->iomem);
158
+ sysbus_init_irq(sbd, &s->irq);
159
+}
160
+
161
static int stellaris_sys_init(uint32_t base, qemu_irq irq,
162
stellaris_board_info * board,
163
uint8_t *macaddr)
164
{
165
- ssys_state *s;
166
+ DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
167
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
168
169
- s = g_new0(ssys_state, 1);
170
- s->irq = irq;
171
- s->board = board;
172
/* Most devices come preprogrammed with a MAC address in the user data. */
173
- s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
174
- s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
175
+ qdev_prop_set_uint32(dev, "user0",
176
+ macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16));
177
+ qdev_prop_set_uint32(dev, "user1",
178
+ macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16));
179
+ qdev_prop_set_uint32(dev, "did0", board->did0);
180
+ qdev_prop_set_uint32(dev, "did1", board->did1);
181
+ qdev_prop_set_uint32(dev, "dc0", board->dc0);
182
+ qdev_prop_set_uint32(dev, "dc1", board->dc1);
183
+ qdev_prop_set_uint32(dev, "dc2", board->dc2);
184
+ qdev_prop_set_uint32(dev, "dc3", board->dc3);
185
+ qdev_prop_set_uint32(dev, "dc4", board->dc4);
186
+
187
+ sysbus_realize_and_unref(sbd, &error_fatal);
188
+ sysbus_mmio_map(sbd, 0, base);
189
+ sysbus_connect_irq(sbd, 0, irq);
190
+
43
+
191
+ /*
44
+ /*
192
+ * Normally we should not be resetting devices like this during
45
+ * If the exponent is 0 and the Integer bit is set, Intel call
193
+ * board creation. For the moment we need to do so, because
46
+ * this a "pseudo-denormal"; x86 supports that only on input
194
+ * system_clock_scale will only get set when the STELLARIS_SYS
47
+ * (treating them as denormals by ignoring the Integer bit).
195
+ * device is reset, and we need its initial value to pass to
48
+ * For m68k, the integer bit is considered validly part of the
196
+ * the watchdog device. This hack can be removed once the
49
+ * input value when the exponent is 0, and may be 0 or 1,
197
+ * watchdog has been converted to use a Clock input instead.
50
+ * giving extra range. They may also be generated as outputs.
51
+ * (The m68k manual actually calls these values part of the
52
+ * normalized number range, not the denormalized number range.)
53
+ *
54
+ * By default you get the Intel behaviour where the Integer
55
+ * bit is ignored; if this is set then the Integer bit value
56
+ * is honoured, m68k-style.
57
+ *
58
+ * Either way, floatx80_invalid_encoding() will always accept
59
+ * pseudo-denormals.
198
+ */
60
+ */
199
+ device_cold_reset(dev);
61
+ floatx80_pseudo_denormal_valid = 16,
200
62
} FloatX80Behaviour;
201
- memory_region_init_io(&s->iomem, NULL, &ssys_ops, s, "ssys", 0x00001000);
63
202
- memory_region_add_subregion(get_system_memory(), base, &s->iomem);
64
/*
203
- ssys_reset(s);
65
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
204
- vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_stellaris_sys, s);
66
index XXXXXXX..XXXXXXX 100644
205
return 0;
67
--- a/fpu/softfloat.c
206
}
68
+++ b/fpu/softfloat.c
207
69
@@ -XXX,XX +XXX,XX @@ typedef struct {
208
-
70
* round_mask: bits below lsb which must be rounded
209
/* I2C controller. */
71
* The following optional modifiers are available:
210
72
* arm_althp: handle ARM Alternative Half Precision
211
#define TYPE_STELLARIS_I2C "stellaris-i2c"
73
- * m68k_denormal: explicit integer bit for extended precision may be 1
212
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stellaris_adc_info = {
74
+ * has_explicit_bit: has an explicit integer bit; this affects whether
213
.class_init = stellaris_adc_class_init,
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
},
214
};
97
};
215
98
216
+static void stellaris_sys_class_init(ObjectClass *klass, void *data)
99
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
217
+{
100
index XXXXXXX..XXXXXXX 100644
218
+ DeviceClass *dc = DEVICE_CLASS(klass);
101
--- a/target/m68k/cpu.c
219
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
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
{
121
+ /*
122
+ * It's target-dependent how to handle the case of exponent 0
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.
136
+ */
137
+ bool has_pseudo_denormals = fmt->has_explicit_bit &&
138
+ (status->floatx80_behaviour & floatx80_pseudo_denormal_valid);
220
+
139
+
221
+ dc->vmsd = &vmstate_stellaris_sys;
140
if (unlikely(p->exp == 0)) {
222
+ rc->phases.enter = stellaris_sys_reset_enter;
141
if (likely(frac_eqz(p))) {
223
+ rc->phases.hold = stellaris_sys_reset_hold;
142
p->cls = float_class_zero;
224
+ rc->phases.exit = stellaris_sys_reset_exit;
143
@@ -XXX,XX +XXX,XX @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
225
+ device_class_set_props(dc, stellaris_sys_properties);
144
int shift = frac_normalize(p);
226
+}
145
p->cls = float_class_denormal;
227
+
146
p->exp = fmt->frac_shift - fmt->exp_bias
228
+static const TypeInfo stellaris_sys_info = {
147
- - shift + !fmt->m68k_denormal;
229
+ .name = TYPE_STELLARIS_SYS,
148
+ - shift + !has_pseudo_denormals;
230
+ .parent = TYPE_SYS_BUS_DEVICE,
149
}
231
+ .instance_size = sizeof(ssys_state),
150
} else if (likely(p->exp < fmt->exp_max) || fmt->arm_althp) {
232
+ .instance_init = stellaris_sys_instance_init,
151
p->cls = float_class_normal;
233
+ .class_init = stellaris_sys_class_init,
152
@@ -XXX,XX +XXX,XX @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
234
+};
153
frac_clear(p);
235
+
154
} else {
236
static void stellaris_register_types(void)
155
bool is_tiny = s->tininess_before_rounding || exp < 0;
237
{
156
+ bool has_pseudo_denormals = fmt->has_explicit_bit &&
238
type_register_static(&stellaris_i2c_info);
157
+ (s->floatx80_behaviour & floatx80_pseudo_denormal_valid);
239
type_register_static(&stellaris_gptm_info);
158
240
type_register_static(&stellaris_adc_info);
159
if (!is_tiny) {
241
+ type_register_static(&stellaris_sys_info);
160
FloatPartsN discard;
242
}
161
is_tiny = !frac_addi(&discard, p, inc);
243
162
}
244
type_init(stellaris_register_types)
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) {
245
--
178
--
246
2.20.1
179
2.43.0
247
180
248
181
diff view generated by jsdifflib
1
As the first step in converting the CMSDK_APB_DUALTIMER device to the
1
Currently we have a compile-time shortcut where we
2
Clock framework, add a Clock input. For the moment we do nothing
2
return false from no_signaling_nans() on everything except
3
with this clock; we will change the behaviour from using the pclk-frq
3
Xtensa, because we know that's the only target that
4
property to using the Clock once all the users of this device have
4
might ever set status->no_signaling_nans.
5
been converted to wire up the Clock.
6
5
7
We take the opportunity to correct the name of the clock input to
6
Remove the ifdef, so we always look at the status flag;
8
match the hardware -- the dual timer names the clock which drives the
7
this has no behavioural change, but will be necessary
9
timers TIMCLK. (It does also have a 'pclk' input, which is used only
8
if we want to build softfloat once for all targets.
10
for the register and APB bus logic; on the SSE-200 these clocks are
11
both connected together.)
12
13
This is a migration compatibility break for machines mps2-an385,
14
mps2-an386, mps2-an500, mps2-an511, mps2-an505, mps2-an521, musca-a,
15
musca-b1.
16
9
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
19
Reviewed-by: Luc Michel <luc@lmichel.fr>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20250224111524.1101196-10-peter.maydell@linaro.org
21
Message-id: 20210128114145.20536-9-peter.maydell@linaro.org
14
Message-id: 20250217125055.160887-8-peter.maydell@linaro.org
22
Message-id: 20210121190622.22000-9-peter.maydell@linaro.org
23
---
15
---
24
include/hw/timer/cmsdk-apb-dualtimer.h | 3 +++
16
fpu/softfloat-specialize.c.inc | 4 ----
25
hw/timer/cmsdk-apb-dualtimer.c | 7 +++++--
17
1 file changed, 4 deletions(-)
26
2 files changed, 8 insertions(+), 2 deletions(-)
27
18
28
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
19
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
29
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/timer/cmsdk-apb-dualtimer.h
21
--- a/fpu/softfloat-specialize.c.inc
31
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
22
+++ b/fpu/softfloat-specialize.c.inc
32
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ this code that are retained.
33
*
24
*/
34
* QEMU interface:
25
static inline bool no_signaling_nans(float_status *status)
35
* + QOM property "pclk-frq": frequency at which the timer is clocked
26
{
36
+ * + Clock input "TIMCLK": clock (for both timers)
27
-#if defined(TARGET_XTENSA)
37
* + sysbus MMIO region 0: the register bank
28
return status->no_signaling_nans;
38
* + sysbus IRQ 0: combined timer interrupt TIMINTC
29
-#else
39
* + sysbus IRO 1: timer block 1 interrupt TIMINT1
30
- return false;
40
@@ -XXX,XX +XXX,XX @@
31
-#endif
41
42
#include "hw/sysbus.h"
43
#include "hw/ptimer.h"
44
+#include "hw/clock.h"
45
#include "qom/object.h"
46
47
#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
48
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBDualTimer {
49
MemoryRegion iomem;
50
qemu_irq timerintc;
51
uint32_t pclk_frq;
52
+ Clock *timclk;
53
54
CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
55
uint32_t timeritcr;
56
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/timer/cmsdk-apb-dualtimer.c
59
+++ b/hw/timer/cmsdk-apb-dualtimer.c
60
@@ -XXX,XX +XXX,XX @@
61
#include "hw/irq.h"
62
#include "hw/qdev-properties.h"
63
#include "hw/registerfields.h"
64
+#include "hw/qdev-clock.h"
65
#include "hw/timer/cmsdk-apb-dualtimer.h"
66
#include "migration/vmstate.h"
67
68
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_init(Object *obj)
69
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
70
sysbus_init_irq(sbd, &s->timermod[i].timerint);
71
}
72
+ s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", NULL, NULL);
73
}
32
}
74
33
75
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
34
/* Define how the architecture discriminates signaling NaNs.
76
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_dualtimermod_vmstate = {
77
78
static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
79
.name = "cmsdk-apb-dualtimer",
80
- .version_id = 1,
81
- .minimum_version_id = 1,
82
+ .version_id = 2,
83
+ .minimum_version_id = 2,
84
.fields = (VMStateField[]) {
85
+ VMSTATE_CLOCK(timclk, CMSDKAPBDualTimer),
86
VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
87
CMSDK_APB_DUALTIMER_NUM_MODULES,
88
1, cmsdk_dualtimermod_vmstate,
89
--
35
--
90
2.20.1
36
2.43.0
91
37
92
38
diff view generated by jsdifflib
1
The state struct for the CMSDK APB timer device doesn't follow our
1
Currently we have a compile-time shortcut where we return a hardcode
2
usual naming convention of camelcase -- "CMSDK" and "APB" are both
2
value from snan_bit_is_one() on everything except MIPS, because we
3
acronyms, but "TIMER" is not so should not be all-uppercase.
3
know that's the only target that needs to change
4
Globally rename the struct to "CMSDKAPBTimer" (bringing it into line
4
status->no_signaling_nans at runtime.
5
with CMSDKAPBWatchdog and CMSDKAPBDualTimer; CMSDKAPBUART remains
6
as-is because "UART" is an acronym).
7
5
8
Commit created with:
6
Remove the ifdef, so we always look at the status flag. This means
9
perl -p -i -e 's/CMSDKAPBTIMER/CMSDKAPBTimer/g' hw/timer/cmsdk-apb-timer.c include/hw/arm/armsse.h include/hw/timer/cmsdk-apb-timer.h
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.
10
12
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20250224111524.1101196-11-peter.maydell@linaro.org
15
Message-id: 20210128114145.20536-7-peter.maydell@linaro.org
17
Message-id: 20250217125055.160887-9-peter.maydell@linaro.org
16
Message-id: 20210121190622.22000-7-peter.maydell@linaro.org
17
---
18
---
18
include/hw/arm/armsse.h | 6 +++---
19
target/hppa/fpu_helper.c | 1 +
19
include/hw/timer/cmsdk-apb-timer.h | 4 ++--
20
target/sh4/cpu.c | 1 +
20
hw/timer/cmsdk-apb-timer.c | 28 ++++++++++++++--------------
21
fpu/softfloat-specialize.c.inc | 7 -------
21
3 files changed, 19 insertions(+), 19 deletions(-)
22
3 files changed, 2 insertions(+), 7 deletions(-)
22
23
23
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
24
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
24
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/armsse.h
26
--- a/target/hppa/fpu_helper.c
26
+++ b/include/hw/arm/armsse.h
27
+++ b/target/hppa/fpu_helper.c
27
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
28
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
28
TZPPC apb_ppc0;
29
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
29
TZPPC apb_ppc1;
30
/* Default NaN: sign bit clear, msb-1 frac bit set */
30
TZMPC mpc[IOTS_NUM_MPC];
31
set_float_default_nan_pattern(0b00100000, &env->fp_status);
31
- CMSDKAPBTIMER timer0;
32
+ set_snan_bit_is_one(true, &env->fp_status);
32
- CMSDKAPBTIMER timer1;
33
/*
33
- CMSDKAPBTIMER s32ktimer;
34
* "PA-RISC 2.0 Architecture" says it is IMPDEF whether the flushing
34
+ CMSDKAPBTimer timer0;
35
* enabled by FPSR.D happens before or after rounding. We pick "before"
35
+ CMSDKAPBTimer timer1;
36
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
36
+ CMSDKAPBTimer s32ktimer;
37
qemu_or_irq ppc_irq_orgate;
38
SplitIRQ sec_resp_splitter;
39
SplitIRQ ppc_irq_splitter[NUM_PPCS];
40
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
41
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/timer/cmsdk-apb-timer.h
38
--- a/target/sh4/cpu.c
43
+++ b/include/hw/timer/cmsdk-apb-timer.h
39
+++ b/target/sh4/cpu.c
44
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
45
#include "qom/object.h"
41
set_flush_to_zero(1, &env->fp_status);
46
42
#endif
47
#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
43
set_default_nan_mode(1, &env->fp_status);
48
-OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTIMER, CMSDK_APB_TIMER)
44
+ set_snan_bit_is_one(true, &env->fp_status);
49
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
45
/* sign bit clear, set all frac bits other than msb */
50
46
set_float_default_nan_pattern(0b00111111, &env->fp_status);
51
-struct CMSDKAPBTIMER {
47
/*
52
+struct CMSDKAPBTimer {
48
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
53
/*< private >*/
54
SysBusDevice parent_obj;
55
56
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
57
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/timer/cmsdk-apb-timer.c
50
--- a/fpu/softfloat-specialize.c.inc
59
+++ b/hw/timer/cmsdk-apb-timer.c
51
+++ b/fpu/softfloat-specialize.c.inc
60
@@ -XXX,XX +XXX,XX @@ static const int timer_id[] = {
52
@@ -XXX,XX +XXX,XX @@ static inline bool no_signaling_nans(float_status *status)
61
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
53
* In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008
62
};
54
* the msb must be zero. MIPS is (so far) unique in supporting both the
63
55
* 2008 revision and backward compatibility with their original choice.
64
-static void cmsdk_apb_timer_update(CMSDKAPBTIMER *s)
56
- * Thus for MIPS we must make the choice at runtime.
65
+static void cmsdk_apb_timer_update(CMSDKAPBTimer *s)
57
*/
58
static inline bool snan_bit_is_one(float_status *status)
66
{
59
{
67
qemu_set_irq(s->timerint, !!(s->intstatus & R_INTSTATUS_IRQ_MASK));
60
-#if defined(TARGET_MIPS)
61
return status->snan_bit_is_one;
62
-#elif defined(TARGET_HPPA) || defined(TARGET_SH4)
63
- return 1;
64
-#else
65
- return 0;
66
-#endif
68
}
67
}
69
68
70
static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
69
/*----------------------------------------------------------------------------
71
{
72
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
73
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
74
uint64_t r;
75
76
switch (offset) {
77
@@ -XXX,XX +XXX,XX @@ static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
78
static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
79
unsigned size)
80
{
81
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
82
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
83
84
trace_cmsdk_apb_timer_write(offset, value, size);
85
86
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps cmsdk_apb_timer_ops = {
87
88
static void cmsdk_apb_timer_tick(void *opaque)
89
{
90
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
91
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
92
93
if (s->ctrl & R_CTRL_IRQEN_MASK) {
94
s->intstatus |= R_INTSTATUS_IRQ_MASK;
95
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_tick(void *opaque)
96
97
static void cmsdk_apb_timer_reset(DeviceState *dev)
98
{
99
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
100
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
101
102
trace_cmsdk_apb_timer_reset();
103
s->ctrl = 0;
104
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
105
static void cmsdk_apb_timer_init(Object *obj)
106
{
107
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
108
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(obj);
109
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(obj);
110
111
memory_region_init_io(&s->iomem, obj, &cmsdk_apb_timer_ops,
112
s, "cmsdk-apb-timer", 0x1000);
113
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
114
115
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
116
{
117
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
118
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
119
120
if (s->pclk_frq == 0) {
121
error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
122
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_timer_vmstate = {
123
.version_id = 1,
124
.minimum_version_id = 1,
125
.fields = (VMStateField[]) {
126
- VMSTATE_PTIMER(timer, CMSDKAPBTIMER),
127
- VMSTATE_UINT32(ctrl, CMSDKAPBTIMER),
128
- VMSTATE_UINT32(value, CMSDKAPBTIMER),
129
- VMSTATE_UINT32(reload, CMSDKAPBTIMER),
130
- VMSTATE_UINT32(intstatus, CMSDKAPBTIMER),
131
+ VMSTATE_PTIMER(timer, CMSDKAPBTimer),
132
+ VMSTATE_UINT32(ctrl, CMSDKAPBTimer),
133
+ VMSTATE_UINT32(value, CMSDKAPBTimer),
134
+ VMSTATE_UINT32(reload, CMSDKAPBTimer),
135
+ VMSTATE_UINT32(intstatus, CMSDKAPBTimer),
136
VMSTATE_END_OF_LIST()
137
}
138
};
139
140
static Property cmsdk_apb_timer_properties[] = {
141
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTIMER, pclk_frq, 0),
142
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTimer, pclk_frq, 0),
143
DEFINE_PROP_END_OF_LIST(),
144
};
145
146
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
147
static const TypeInfo cmsdk_apb_timer_info = {
148
.name = TYPE_CMSDK_APB_TIMER,
149
.parent = TYPE_SYS_BUS_DEVICE,
150
- .instance_size = sizeof(CMSDKAPBTIMER),
151
+ .instance_size = sizeof(CMSDKAPBTimer),
152
.instance_init = cmsdk_apb_timer_init,
153
.class_init = cmsdk_apb_timer_class_init,
154
};
155
--
70
--
156
2.20.1
71
2.43.0
157
72
158
73
diff view generated by jsdifflib
1
Add a simple test of the CMSDK dual timer, since we're about to do
1
We happen to know that for the PPC target the FP status flags (and in
2
some refactoring of how it is clocked.
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.
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.
3
11
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20250224111524.1101196-12-peter.maydell@linaro.org
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
15
Message-id: 20250217125055.160887-10-peter.maydell@linaro.org
8
Message-id: 20210128114145.20536-6-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-6-peter.maydell@linaro.org
10
---
16
---
11
tests/qtest/cmsdk-apb-dualtimer-test.c | 130 +++++++++++++++++++++++++
17
fpu/softfloat.c | 2 --
12
MAINTAINERS | 1 +
18
1 file changed, 2 deletions(-)
13
tests/qtest/meson.build | 1 +
14
3 files changed, 132 insertions(+)
15
create mode 100644 tests/qtest/cmsdk-apb-dualtimer-test.c
16
19
17
diff --git a/tests/qtest/cmsdk-apb-dualtimer-test.c b/tests/qtest/cmsdk-apb-dualtimer-test.c
20
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/tests/qtest/cmsdk-apb-dualtimer-test.c
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * QTest testcase for the CMSDK APB dualtimer device
25
+ *
26
+ * Copyright (c) 2021 Linaro Limited
27
+ *
28
+ * This program is free software; you can redistribute it and/or modify it
29
+ * under the terms of the GNU General Public License as published by the
30
+ * Free Software Foundation; either version 2 of the License, or
31
+ * (at your option) any later version.
32
+ *
33
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * for more details.
37
+ */
38
+
39
+#include "qemu/osdep.h"
40
+#include "libqtest-single.h"
41
+
42
+/* IoTKit/ARMSSE dualtimer; driven at 25MHz in mps2-an385, so 40ns per tick */
43
+#define TIMER_BASE 0x40002000
44
+
45
+#define TIMER1LOAD 0
46
+#define TIMER1VALUE 4
47
+#define TIMER1CONTROL 8
48
+#define TIMER1INTCLR 0xc
49
+#define TIMER1RIS 0x10
50
+#define TIMER1MIS 0x14
51
+#define TIMER1BGLOAD 0x18
52
+
53
+#define TIMER2LOAD 0x20
54
+#define TIMER2VALUE 0x24
55
+#define TIMER2CONTROL 0x28
56
+#define TIMER2INTCLR 0x2c
57
+#define TIMER2RIS 0x30
58
+#define TIMER2MIS 0x34
59
+#define TIMER2BGLOAD 0x38
60
+
61
+#define CTRL_ENABLE (1 << 7)
62
+#define CTRL_PERIODIC (1 << 6)
63
+#define CTRL_INTEN (1 << 5)
64
+#define CTRL_PRESCALE_1 (0 << 2)
65
+#define CTRL_PRESCALE_16 (1 << 2)
66
+#define CTRL_PRESCALE_256 (2 << 2)
67
+#define CTRL_32BIT (1 << 1)
68
+#define CTRL_ONESHOT (1 << 0)
69
+
70
+static void test_dualtimer(void)
71
+{
72
+ g_assert_true(readl(TIMER_BASE + TIMER1RIS) == 0);
73
+
74
+ /* Start timer: will fire after 40000 ns */
75
+ writel(TIMER_BASE + TIMER1LOAD, 1000);
76
+ /* enable in free-running, wrapping, interrupt mode */
77
+ writel(TIMER_BASE + TIMER1CONTROL, CTRL_ENABLE | CTRL_INTEN);
78
+
79
+ /* Step to just past the 500th tick and check VALUE */
80
+ clock_step(500 * 40 + 1);
81
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 0);
82
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 500);
83
+
84
+ /* Just past the 1000th tick: timer should have fired */
85
+ clock_step(500 * 40);
86
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 1);
87
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0);
88
+
89
+ /*
90
+ * We are in free-running wrapping 16-bit mode, so on the following
91
+ * tick VALUE should have wrapped round to 0xffff.
92
+ */
93
+ clock_step(40);
94
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0xffff);
95
+
96
+ /* Check that any write to INTCLR clears interrupt */
97
+ writel(TIMER_BASE + TIMER1INTCLR, 1);
98
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 0);
99
+
100
+ /* Turn off the timer */
101
+ writel(TIMER_BASE + TIMER1CONTROL, 0);
102
+}
103
+
104
+static void test_prescale(void)
105
+{
106
+ g_assert_true(readl(TIMER_BASE + TIMER2RIS) == 0);
107
+
108
+ /* Start timer: will fire after 40 * 256 * 1000 == 1024000 ns */
109
+ writel(TIMER_BASE + TIMER2LOAD, 1000);
110
+ /* enable in periodic, wrapping, interrupt mode, prescale 256 */
111
+ writel(TIMER_BASE + TIMER2CONTROL,
112
+ CTRL_ENABLE | CTRL_INTEN | CTRL_PERIODIC | CTRL_PRESCALE_256);
113
+
114
+ /* Step to just past the 500th tick and check VALUE */
115
+ clock_step(40 * 256 * 501);
116
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 0);
117
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 500);
118
+
119
+ /* Just past the 1000th tick: timer should have fired */
120
+ clock_step(40 * 256 * 500);
121
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 1);
122
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 0);
123
+
124
+ /* In periodic mode the tick VALUE now reloads */
125
+ clock_step(40 * 256);
126
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 1000);
127
+
128
+ /* Check that any write to INTCLR clears interrupt */
129
+ writel(TIMER_BASE + TIMER2INTCLR, 1);
130
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 0);
131
+
132
+ /* Turn off the timer */
133
+ writel(TIMER_BASE + TIMER2CONTROL, 0);
134
+}
135
+
136
+int main(int argc, char **argv)
137
+{
138
+ int r;
139
+
140
+ g_test_init(&argc, &argv, NULL);
141
+
142
+ qtest_start("-machine mps2-an385");
143
+
144
+ qtest_add_func("/cmsdk-apb-dualtimer/dualtimer", test_dualtimer);
145
+ qtest_add_func("/cmsdk-apb-dualtimer/prescale", test_prescale);
146
+
147
+ r = g_test_run();
148
+
149
+ qtest_end();
150
+
151
+ return r;
152
+}
153
diff --git a/MAINTAINERS b/MAINTAINERS
154
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
155
--- a/MAINTAINERS
22
--- a/fpu/softfloat.c
156
+++ b/MAINTAINERS
23
+++ b/fpu/softfloat.c
157
@@ -XXX,XX +XXX,XX @@ F: include/hw/timer/cmsdk-apb-timer.h
24
@@ -XXX,XX +XXX,XX @@ GEN_INPUT_FLUSH3(float64_input_flush3, float64)
158
F: tests/qtest/cmsdk-apb-timer-test.c
25
* the use of hardfloat, since hardfloat relies on the inexact flag being
159
F: hw/timer/cmsdk-apb-dualtimer.c
26
* already set.
160
F: include/hw/timer/cmsdk-apb-dualtimer.h
27
*/
161
+F: tests/qtest/cmsdk-apb-dualtimer-test.c
28
-#if defined(TARGET_PPC) || defined(__FAST_MATH__)
162
F: hw/char/cmsdk-apb-uart.c
29
# if defined(__FAST_MATH__)
163
F: include/hw/char/cmsdk-apb-uart.h
30
# warning disabling hardfloat due to -ffast-math: hardfloat requires an exact \
164
F: hw/watchdog/cmsdk-apb-watchdog.c
31
IEEE implementation
165
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
32
-# endif
166
index XXXXXXX..XXXXXXX 100644
33
# define QEMU_NO_HARDFLOAT 1
167
--- a/tests/qtest/meson.build
34
# define QEMU_SOFTFLOAT_ATTR QEMU_FLATTEN
168
+++ b/tests/qtest/meson.build
35
#else
169
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
170
'npcm7xx_timer-test',
171
'npcm7xx_watchdog_timer-test']
172
qtests_arm = \
173
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
174
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
175
(config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
176
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
177
--
36
--
178
2.20.1
37
2.43.0
179
180
diff view generated by jsdifflib
1
Add a simple test of the CMSDK APB timer, since we're about to do
1
Now we have removed all the target-specifics from the softfloat code,
2
some refactoring of how it is clocked.
2
we can switch to building it once for the whole system rather than
3
once per target.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20250224111524.1101196-13-peter.maydell@linaro.org
8
Message-id: 20210128114145.20536-4-peter.maydell@linaro.org
9
Message-id: 20250217125055.160887-11-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-4-peter.maydell@linaro.org
10
---
10
---
11
tests/qtest/cmsdk-apb-timer-test.c | 75 ++++++++++++++++++++++++++++++
11
fpu/softfloat.c | 3 ---
12
MAINTAINERS | 1 +
12
fpu/meson.build | 2 +-
13
tests/qtest/meson.build | 1 +
13
2 files changed, 1 insertion(+), 4 deletions(-)
14
3 files changed, 77 insertions(+)
15
create mode 100644 tests/qtest/cmsdk-apb-timer-test.c
16
14
17
diff --git a/tests/qtest/cmsdk-apb-timer-test.c b/tests/qtest/cmsdk-apb-timer-test.c
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/tests/qtest/cmsdk-apb-timer-test.c
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * QTest testcase for the CMSDK APB timer device
25
+ *
26
+ * Copyright (c) 2021 Linaro Limited
27
+ *
28
+ * This program is free software; you can redistribute it and/or modify it
29
+ * under the terms of the GNU General Public License as published by the
30
+ * Free Software Foundation; either version 2 of the License, or
31
+ * (at your option) any later version.
32
+ *
33
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * for more details.
37
+ */
38
+
39
+#include "qemu/osdep.h"
40
+#include "libqtest-single.h"
41
+
42
+/* IoTKit/ARMSSE-200 timer0; driven at 25MHz in mps2-an385, so 40ns per tick */
43
+#define TIMER_BASE 0x40000000
44
+
45
+#define CTRL 0
46
+#define VALUE 4
47
+#define RELOAD 8
48
+#define INTSTATUS 0xc
49
+
50
+static void test_timer(void)
51
+{
52
+ g_assert_true(readl(TIMER_BASE + INTSTATUS) == 0);
53
+
54
+ /* Start timer: will fire after 40 * 1000 == 40000 ns */
55
+ writel(TIMER_BASE + RELOAD, 1000);
56
+ writel(TIMER_BASE + CTRL, 9);
57
+
58
+ /* Step to just past the 500th tick and check VALUE */
59
+ clock_step(40 * 500 + 1);
60
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 0);
61
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 500);
62
+
63
+ /* Just past the 1000th tick: timer should have fired */
64
+ clock_step(40 * 500);
65
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 1);
66
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 0);
67
+
68
+ /* VALUE reloads at the following tick */
69
+ clock_step(40);
70
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 1000);
71
+
72
+ /* Check write-1-to-clear behaviour of INTSTATUS */
73
+ writel(TIMER_BASE + INTSTATUS, 0);
74
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 1);
75
+ writel(TIMER_BASE + INTSTATUS, 1);
76
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 0);
77
+
78
+ /* Turn off the timer */
79
+ writel(TIMER_BASE + CTRL, 0);
80
+}
81
+
82
+int main(int argc, char **argv)
83
+{
84
+ int r;
85
+
86
+ g_test_init(&argc, &argv, NULL);
87
+
88
+ qtest_start("-machine mps2-an385");
89
+
90
+ qtest_add_func("/cmsdk-apb-timer/timer", test_timer);
91
+
92
+ r = g_test_run();
93
+
94
+ qtest_end();
95
+
96
+ return r;
97
+}
98
diff --git a/MAINTAINERS b/MAINTAINERS
99
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
100
--- a/MAINTAINERS
17
--- a/fpu/softfloat.c
101
+++ b/MAINTAINERS
18
+++ b/fpu/softfloat.c
102
@@ -XXX,XX +XXX,XX @@ F: include/hw/rtc/pl031.h
19
@@ -XXX,XX +XXX,XX @@ this code that are retained.
103
F: include/hw/arm/primecell.h
20
* version 2 or later. See the COPYING file in the top-level directory.
104
F: hw/timer/cmsdk-apb-timer.c
21
*/
105
F: include/hw/timer/cmsdk-apb-timer.h
22
106
+F: tests/qtest/cmsdk-apb-timer-test.c
23
-/* softfloat (and in particular the code in softfloat-specialize.h) is
107
F: hw/timer/cmsdk-apb-dualtimer.c
24
- * target-dependent and needs the TARGET_* macros.
108
F: include/hw/timer/cmsdk-apb-dualtimer.h
25
- */
109
F: hw/char/cmsdk-apb-uart.c
26
#include "qemu/osdep.h"
110
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
27
#include <math.h>
28
#include "qemu/bitops.h"
29
diff --git a/fpu/meson.build b/fpu/meson.build
111
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qtest/meson.build
31
--- a/fpu/meson.build
113
+++ b/tests/qtest/meson.build
32
+++ b/fpu/meson.build
114
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
33
@@ -1 +1 @@
115
'npcm7xx_timer-test',
34
-specific_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
116
'npcm7xx_watchdog_timer-test']
35
+common_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
117
qtests_arm = \
118
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
119
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
120
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
121
['arm-cpu-features',
122
--
36
--
123
2.20.1
37
2.43.0
124
38
125
39
diff view generated by jsdifflib
1
Add a function for checking whether a clock has a source. This is
1
Most of the target/arm/vfp_helper.c file is purely TCG helper code,
2
useful for devices which have input clocks that must be wired up by
2
guarded by #ifdef CONFIG_TCG. Move this into a new file in
3
the board as it allows them to fail in realize rather than ploughing
3
target/arm/tcg/.
4
on with a zero-period clock.
4
5
This leaves only the code relating to getting and setting the
6
FPCR/FPSR/FPSCR in the original file. (Some of this also is
7
TCG-only, but that needs more careful disentangling.)
8
9
Having two vfp_helper.c files might seem a bit confusing,
10
but once we've finished moving all the helper code out
11
of the old file we are going to rename it to vfp_fpscr.c.
5
12
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20250221190957.811948-2-peter.maydell@linaro.org
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210128114145.20536-3-peter.maydell@linaro.org
11
Message-id: 20210121190622.22000-3-peter.maydell@linaro.org
12
---
16
---
13
docs/devel/clocks.rst | 16 ++++++++++++++++
17
target/arm/{ => tcg}/vfp_helper.c | 399 +----------
14
include/hw/clock.h | 15 +++++++++++++++
18
target/arm/vfp_helper.c | 1109 -----------------------------
15
2 files changed, 31 insertions(+)
19
target/arm/tcg/meson.build | 1 +
20
3 files changed, 4 insertions(+), 1505 deletions(-)
21
copy target/arm/{ => tcg}/vfp_helper.c (71%)
16
22
17
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
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
18
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/devel/clocks.rst
28
--- a/target/arm/vfp_helper.c
20
+++ b/docs/devel/clocks.rst
29
+++ b/target/arm/tcg/vfp_helper.c
21
@@ -XXX,XX +XXX,XX @@ object during device instance init. For example:
30
@@ -XXX,XX +XXX,XX @@
22
/* set initial value to 10ns / 100MHz */
31
#include "internals.h"
23
clock_set_ns(clk, 10);
32
#include "cpu-features.h"
24
33
#include "fpu/softfloat.h"
25
+To enforce that the clock is wired up by the board code, you can
34
-#ifdef CONFIG_TCG
26
+call ``clock_has_source()`` in your device's realize method:
35
#include "qemu/log.h"
27
+
36
-#endif
28
+.. code-block:: c
37
-
29
+
38
-/* VFP support. We follow the convention used for VFP instructions:
30
+ if (!clock_has_source(s->clk)) {
39
- Single precision routines have a "s" suffix, double precision a
31
+ error_setg(errp, "MyDevice: clk input must be connected");
40
- "d" suffix. */
32
+ return;
41
33
+ }
42
/*
34
+
43
- * Set the float_status behaviour to match the Arm defaults:
35
+Note that this only checks that the clock has been wired up; it is
44
- * * tininess-before-rounding
36
+still possible that the output clock connected to it is disabled
45
- * * 2-input NaN propagation prefers SNaN over QNaN, and then
37
+or has not yet been configured, in which case the period will be
46
- * operand A over operand B (see FPProcessNaNs() pseudocode)
38
+zero. You should use the clock callback to find out when the clock
47
- * * 3-input NaN propagation prefers SNaN over QNaN, and then
39
+period changes.
48
- * operand C over A over B (see FPProcessNaNs3() pseudocode,
40
+
49
- * but note that for QEMU muladd is a * b + c, whereas for
41
Fetching clock frequency/period
50
- * the pseudocode function the arguments are in the order c, a, b.
42
-------------------------------
51
- * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
43
52
- * and the input NaN if it is signalling
44
diff --git a/include/hw/clock.h b/include/hw/clock.h
53
- * * Default NaN has sign bit clear, msb frac bit set
54
+ * VFP support. We follow the convention used for VFP instructions:
55
+ * Single precision routines have a "s" suffix, double precision a
56
+ * "d" suffix.
57
*/
58
-void arm_set_default_fp_behaviours(float_status *s)
59
-{
60
- set_float_detect_tininess(float_tininess_before_rounding, s);
61
- set_float_ftz_detection(float_ftz_before_rounding, s);
62
- set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
63
- set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
64
- set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
65
- set_float_default_nan_pattern(0b01000000, s);
66
-}
67
-
68
-/*
69
- * Set the float_status behaviour to match the FEAT_AFP
70
- * FPCR.AH=1 requirements:
71
- * * tininess-after-rounding
72
- * * 2-input NaN propagation prefers the first NaN
73
- * * 3-input NaN propagation prefers a over b over c
74
- * * 0 * Inf + NaN always returns the input NaN and doesn't
75
- * set Invalid for a QNaN
76
- * * default NaN has sign bit set, msb frac bit set
77
- */
78
-void arm_set_ah_fp_behaviours(float_status *s)
79
-{
80
- set_float_detect_tininess(float_tininess_after_rounding, s);
81
- set_float_ftz_detection(float_ftz_after_rounding, s);
82
- set_float_2nan_prop_rule(float_2nan_prop_ab, s);
83
- set_float_3nan_prop_rule(float_3nan_prop_abc, s);
84
- set_float_infzeronan_rule(float_infzeronan_dnan_never |
85
- float_infzeronan_suppress_invalid, s);
86
- set_float_default_nan_pattern(0b11000000, s);
87
-}
88
-
89
-#ifdef CONFIG_TCG
90
-
91
-/* Convert host exception flags to vfp form. */
92
-static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
93
-{
94
- uint32_t target_bits = 0;
95
-
96
- if (host_bits & float_flag_invalid) {
97
- target_bits |= FPSR_IOC;
98
- }
99
- if (host_bits & float_flag_divbyzero) {
100
- target_bits |= FPSR_DZC;
101
- }
102
- if (host_bits & float_flag_overflow) {
103
- target_bits |= FPSR_OFC;
104
- }
105
- if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
106
- target_bits |= FPSR_UFC;
107
- }
108
- if (host_bits & float_flag_inexact) {
109
- target_bits |= FPSR_IXC;
110
- }
111
- if (host_bits & float_flag_input_denormal_flushed) {
112
- target_bits |= FPSR_IDC;
113
- }
114
- /*
115
- * With FPCR.AH, IDC is set when an input denormal is used,
116
- * and flushing an output denormal to zero sets both IXC and UFC.
117
- */
118
- if (ah && (host_bits & float_flag_input_denormal_used)) {
119
- target_bits |= FPSR_IDC;
120
- }
121
- if (ah && (host_bits & float_flag_output_denormal_flushed)) {
122
- target_bits |= FPSR_IXC;
123
- }
124
- return target_bits;
125
-}
126
-
127
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
128
-{
129
- uint32_t a32_flags = 0, a64_flags = 0;
130
-
131
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
132
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
133
- /* FZ16 does not generate an input denormal exception. */
134
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
135
- & ~float_flag_input_denormal_flushed);
136
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
137
- & ~float_flag_input_denormal_flushed);
138
-
139
- a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
140
- a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
141
- & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
142
- /*
143
- * We do not merge in flags from FPST_AH or FPST_AH_F16, because
144
- * they are used for insns that must not set the cumulative exception bits.
145
- */
146
-
147
- /*
148
- * Flushing an input denormal *only* because FPCR.FIZ == 1 does
149
- * not set FPSR.IDC; if FPCR.FZ is also set then this takes
150
- * precedence and IDC is set (see the FPUnpackBase pseudocode).
151
- * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
152
- * We only do this for the a64 flags because FIZ has no effect
153
- * on AArch32 even if it is set.
154
- */
155
- if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
156
- a64_flags &= ~float_flag_input_denormal_flushed;
157
- }
158
- return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
159
- vfp_exceptbits_from_host(a32_flags, false);
160
-}
161
-
162
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
163
-{
164
- /*
165
- * Clear out all the exception-flag information in the float_status
166
- * values. The caller should have arranged for env->vfp.fpsr to
167
- * be the architecturally up-to-date exception flag information first.
168
- */
169
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
170
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
171
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
172
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
173
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
174
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
175
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
176
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
177
-}
178
-
179
-static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
180
-{
181
- /*
182
- * Synchronize any pending exception-flag information in the
183
- * float_status values into env->vfp.fpsr, and then clear out
184
- * the float_status data.
185
- */
186
- env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
187
- vfp_clear_float_status_exc_flags(env);
188
-}
189
-
190
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
191
-{
192
- uint64_t changed = env->vfp.fpcr;
193
-
194
- changed ^= val;
195
- changed &= mask;
196
- if (changed & (3 << 22)) {
197
- int i = (val >> 22) & 3;
198
- switch (i) {
199
- case FPROUNDING_TIEEVEN:
200
- i = float_round_nearest_even;
201
- break;
202
- case FPROUNDING_POSINF:
203
- i = float_round_up;
204
- break;
205
- case FPROUNDING_NEGINF:
206
- i = float_round_down;
207
- break;
208
- case FPROUNDING_ZERO:
209
- i = float_round_to_zero;
210
- break;
211
- }
212
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
213
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
214
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
215
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
216
- }
217
- if (changed & FPCR_FZ16) {
218
- bool ftz_enabled = val & FPCR_FZ16;
219
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
220
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
221
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
222
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
223
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
224
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
225
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
226
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
227
- }
228
- if (changed & FPCR_FZ) {
229
- bool ftz_enabled = val & FPCR_FZ;
230
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
231
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
232
- /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
233
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
234
- }
235
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
236
- /*
237
- * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
238
- * both FPCR.AH = 0 and FPCR.FZ = 1.
239
- */
240
- bool fitz_enabled = (val & FPCR_FIZ) ||
241
- (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
242
- set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
243
- }
244
- if (changed & FPCR_DN) {
245
- bool dnan_enabled = val & FPCR_DN;
246
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
247
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
248
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
249
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
250
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
251
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
252
- }
253
- if (changed & FPCR_AH) {
254
- bool ah_enabled = val & FPCR_AH;
255
-
256
- if (ah_enabled) {
257
- /* Change behaviours for A64 FP operations */
258
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
259
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
260
- } else {
261
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
262
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
263
- }
264
- }
265
- /*
266
- * If any bits changed that we look at in vfp_get_fpsr_from_host(),
267
- * we must sync the float_status flags into vfp.fpsr now (under the
268
- * old regime) before we update vfp.fpcr.
269
- */
270
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
271
- vfp_sync_and_clear_float_status_exc_flags(env);
272
- }
273
-}
274
-
275
-#else
276
-
277
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
278
-{
279
- return 0;
280
-}
281
-
282
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
283
-{
284
-}
285
-
286
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
287
-{
288
-}
289
-
290
-#endif
291
-
292
-uint32_t vfp_get_fpcr(CPUARMState *env)
293
-{
294
- uint32_t fpcr = env->vfp.fpcr
295
- | (env->vfp.vec_len << 16)
296
- | (env->vfp.vec_stride << 20);
297
-
298
- /*
299
- * M-profile LTPSIZE is the same bits [18:16] as A-profile Len; whichever
300
- * of the two is not applicable to this CPU will always be zero.
301
- */
302
- fpcr |= env->v7m.ltpsize << 16;
303
-
304
- return fpcr;
305
-}
306
-
307
-uint32_t vfp_get_fpsr(CPUARMState *env)
308
-{
309
- uint32_t fpsr = env->vfp.fpsr;
310
- uint32_t i;
311
-
312
- fpsr |= vfp_get_fpsr_from_host(env);
313
-
314
- i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
315
- fpsr |= i ? FPSR_QC : 0;
316
- return fpsr;
317
-}
318
-
319
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
320
-{
321
- return (vfp_get_fpcr(env) & FPSCR_FPCR_MASK) |
322
- (vfp_get_fpsr(env) & FPSCR_FPSR_MASK);
323
-}
324
-
325
-uint32_t vfp_get_fpscr(CPUARMState *env)
326
-{
327
- return HELPER(vfp_get_fpscr)(env);
328
-}
329
-
330
-void vfp_set_fpsr(CPUARMState *env, uint32_t val)
331
-{
332
- ARMCPU *cpu = env_archcpu(env);
333
-
334
- if (arm_feature(env, ARM_FEATURE_NEON) ||
335
- cpu_isar_feature(aa32_mve, cpu)) {
336
- /*
337
- * The bit we set within vfp.qc[] is arbitrary; the array as a
338
- * whole being zero/non-zero is what counts.
339
- */
340
- env->vfp.qc[0] = val & FPSR_QC;
341
- env->vfp.qc[1] = 0;
342
- env->vfp.qc[2] = 0;
343
- env->vfp.qc[3] = 0;
344
- }
345
-
346
- /*
347
- * NZCV lives only in env->vfp.fpsr. The cumulative exception flags
348
- * IOC|DZC|OFC|UFC|IXC|IDC also live in env->vfp.fpsr, with possible
349
- * extra pending exception information that hasn't yet been folded in
350
- * living in the float_status values (for TCG).
351
- * Since this FPSR write gives us the up to date values of the exception
352
- * flags, we want to store into vfp.fpsr the NZCV and CEXC bits, zeroing
353
- * anything else. We also need to clear out the float_status exception
354
- * information so that the next vfp_get_fpsr does not fold in stale data.
355
- */
356
- val &= FPSR_NZCV_MASK | FPSR_CEXC_MASK;
357
- env->vfp.fpsr = val;
358
- vfp_clear_float_status_exc_flags(env);
359
-}
360
-
361
-static void vfp_set_fpcr_masked(CPUARMState *env, uint32_t val, uint32_t mask)
362
-{
363
- /*
364
- * We only set FPCR bits defined by mask, and leave the others alone.
365
- * We assume the mask is sensible (e.g. doesn't try to set only
366
- * part of a field)
367
- */
368
- ARMCPU *cpu = env_archcpu(env);
369
-
370
- /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
371
- if (!cpu_isar_feature(any_fp16, cpu)) {
372
- val &= ~FPCR_FZ16;
373
- }
374
- if (!cpu_isar_feature(aa64_afp, cpu)) {
375
- val &= ~(FPCR_FIZ | FPCR_AH | FPCR_NEP);
376
- }
377
-
378
- if (!cpu_isar_feature(aa64_ebf16, cpu)) {
379
- val &= ~FPCR_EBF;
380
- }
381
-
382
- vfp_set_fpcr_to_host(env, val, mask);
383
-
384
- if (mask & (FPCR_LEN_MASK | FPCR_STRIDE_MASK)) {
385
- if (!arm_feature(env, ARM_FEATURE_M)) {
386
- /*
387
- * Short-vector length and stride; on M-profile these bits
388
- * are used for different purposes.
389
- * We can't make this conditional be "if MVFR0.FPShVec != 0",
390
- * because in v7A no-short-vector-support cores still had to
391
- * allow Stride/Len to be written with the only effect that
392
- * some insns are required to UNDEF if the guest sets them.
393
- */
394
- env->vfp.vec_len = extract32(val, 16, 3);
395
- env->vfp.vec_stride = extract32(val, 20, 2);
396
- } else if (cpu_isar_feature(aa32_mve, cpu)) {
397
- env->v7m.ltpsize = extract32(val, FPCR_LTPSIZE_SHIFT,
398
- FPCR_LTPSIZE_LENGTH);
399
- }
400
- }
401
-
402
- /*
403
- * We don't implement trapped exception handling, so the
404
- * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
405
- *
406
- * The FPCR bits we keep in vfp.fpcr are AHP, DN, FZ, RMode, EBF, FZ16,
407
- * FIZ, AH, and NEP.
408
- * Len, Stride and LTPSIZE we just handled. Store those bits
409
- * there, and zero any of the other FPCR bits and the RES0 and RAZ/WI
410
- * bits.
411
- */
412
- val &= FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK | FPCR_FZ16 |
413
- FPCR_EBF | FPCR_FIZ | FPCR_AH | FPCR_NEP;
414
- env->vfp.fpcr &= ~mask;
415
- env->vfp.fpcr |= val;
416
-}
417
-
418
-void vfp_set_fpcr(CPUARMState *env, uint32_t val)
419
-{
420
- vfp_set_fpcr_masked(env, val, MAKE_64BIT_MASK(0, 32));
421
-}
422
-
423
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
424
-{
425
- vfp_set_fpcr_masked(env, val, FPSCR_FPCR_MASK);
426
- vfp_set_fpsr(env, val & FPSCR_FPSR_MASK);
427
-}
428
-
429
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
430
-{
431
- HELPER(vfp_set_fpscr)(env, val);
432
-}
433
-
434
-#ifdef CONFIG_TCG
435
436
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
437
438
@@ -XXX,XX +XXX,XX @@ void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
439
440
raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
441
}
442
-
443
-#endif
444
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
45
index XXXXXXX..XXXXXXX 100644
445
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/clock.h
446
--- a/target/arm/vfp_helper.c
47
+++ b/include/hw/clock.h
447
+++ b/target/arm/vfp_helper.c
48
@@ -XXX,XX +XXX,XX @@ void clock_clear_callback(Clock *clk);
448
@@ -XXX,XX +XXX,XX @@
49
*/
449
#include "internals.h"
50
void clock_set_source(Clock *clk, Clock *src);
450
#include "cpu-features.h"
51
451
#include "fpu/softfloat.h"
52
+/**
452
-#ifdef CONFIG_TCG
53
+ * clock_has_source:
453
-#include "qemu/log.h"
54
+ * @clk: the clock
454
-#endif
55
+ *
455
-
56
+ * Returns true if the clock has a source clock connected to it.
456
-/* VFP support. We follow the convention used for VFP instructions:
57
+ * This is useful for devices which have input clocks which must
457
- Single precision routines have a "s" suffix, double precision a
58
+ * be connected by the board/SoC code which creates them. The
458
- "d" suffix. */
59
+ * device code can use this to check in its realize method that
459
60
+ * the clock has been connected.
460
/*
61
+ */
461
* Set the float_status behaviour to match the Arm defaults:
62
+static inline bool clock_has_source(const Clock *clk)
462
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val)
63
+{
463
{
64
+ return clk->source != NULL;
464
HELPER(vfp_set_fpscr)(env, val);
65
+}
465
}
66
+
466
-
67
/**
467
-#ifdef CONFIG_TCG
68
* clock_set:
468
-
69
* @clk: the clock to initialize.
469
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
470
-
471
-#define VFP_BINOP(name) \
472
-dh_ctype_f16 VFP_HELPER(name, h)(dh_ctype_f16 a, dh_ctype_f16 b, float_status *fpst) \
473
-{ \
474
- return float16_ ## name(a, b, fpst); \
475
-} \
476
-float32 VFP_HELPER(name, s)(float32 a, float32 b, float_status *fpst) \
477
-{ \
478
- return float32_ ## name(a, b, fpst); \
479
-} \
480
-float64 VFP_HELPER(name, d)(float64 a, float64 b, float_status *fpst) \
481
-{ \
482
- return float64_ ## name(a, b, fpst); \
483
-}
484
-VFP_BINOP(add)
485
-VFP_BINOP(sub)
486
-VFP_BINOP(mul)
487
-VFP_BINOP(div)
488
-VFP_BINOP(min)
489
-VFP_BINOP(max)
490
-VFP_BINOP(minnum)
491
-VFP_BINOP(maxnum)
492
-#undef VFP_BINOP
493
-
494
-dh_ctype_f16 VFP_HELPER(sqrt, h)(dh_ctype_f16 a, float_status *fpst)
495
-{
496
- return float16_sqrt(a, fpst);
497
-}
498
-
499
-float32 VFP_HELPER(sqrt, s)(float32 a, float_status *fpst)
500
-{
501
- return float32_sqrt(a, fpst);
502
-}
503
-
504
-float64 VFP_HELPER(sqrt, d)(float64 a, float_status *fpst)
505
-{
506
- return float64_sqrt(a, fpst);
507
-}
508
-
509
-static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp)
510
-{
511
- uint32_t flags;
512
- switch (cmp) {
513
- case float_relation_equal:
514
- flags = 0x6;
515
- break;
516
- case float_relation_less:
517
- flags = 0x8;
518
- break;
519
- case float_relation_greater:
520
- flags = 0x2;
521
- break;
522
- case float_relation_unordered:
523
- flags = 0x3;
524
- break;
525
- default:
526
- g_assert_not_reached();
527
- }
528
- env->vfp.fpsr = deposit64(env->vfp.fpsr, 28, 4, flags); /* NZCV */
529
-}
530
-
531
-/* XXX: check quiet/signaling case */
532
-#define DO_VFP_cmp(P, FLOATTYPE, ARGTYPE, FPST) \
533
-void VFP_HELPER(cmp, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
534
-{ \
535
- softfloat_to_vfp_compare(env, \
536
- FLOATTYPE ## _compare_quiet(a, b, &env->vfp.fp_status[FPST])); \
537
-} \
538
-void VFP_HELPER(cmpe, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
539
-{ \
540
- softfloat_to_vfp_compare(env, \
541
- FLOATTYPE ## _compare(a, b, &env->vfp.fp_status[FPST])); \
542
-}
543
-DO_VFP_cmp(h, float16, dh_ctype_f16, FPST_A32_F16)
544
-DO_VFP_cmp(s, float32, float32, FPST_A32)
545
-DO_VFP_cmp(d, float64, float64, FPST_A32)
546
-#undef DO_VFP_cmp
547
-
548
-/* Integer to float and float to integer conversions */
549
-
550
-#define CONV_ITOF(name, ftype, fsz, sign) \
551
-ftype HELPER(name)(uint32_t x, float_status *fpst) \
552
-{ \
553
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
554
-}
555
-
556
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
557
-sign##int32_t HELPER(name)(ftype x, float_status *fpst) \
558
-{ \
559
- if (float##fsz##_is_any_nan(x)) { \
560
- float_raise(float_flag_invalid, fpst); \
561
- return 0; \
562
- } \
563
- return float##fsz##_to_##sign##int32##round(x, fpst); \
564
-}
565
-
566
-#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
567
- CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
568
- CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
569
- CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
570
-
571
-FLOAT_CONVS(si, h, uint32_t, 16, )
572
-FLOAT_CONVS(si, s, float32, 32, )
573
-FLOAT_CONVS(si, d, float64, 64, )
574
-FLOAT_CONVS(ui, h, uint32_t, 16, u)
575
-FLOAT_CONVS(ui, s, float32, 32, u)
576
-FLOAT_CONVS(ui, d, float64, 64, u)
577
-
578
-#undef CONV_ITOF
579
-#undef CONV_FTOI
580
-#undef FLOAT_CONVS
581
-
582
-/* floating point conversion */
583
-float64 VFP_HELPER(fcvtd, s)(float32 x, float_status *status)
584
-{
585
- return float32_to_float64(x, status);
586
-}
587
-
588
-float32 VFP_HELPER(fcvts, d)(float64 x, float_status *status)
589
-{
590
- return float64_to_float32(x, status);
591
-}
592
-
593
-uint32_t HELPER(bfcvt)(float32 x, float_status *status)
594
-{
595
- return float32_to_bfloat16(x, status);
596
-}
597
-
598
-uint32_t HELPER(bfcvt_pair)(uint64_t pair, float_status *status)
599
-{
600
- bfloat16 lo = float32_to_bfloat16(extract64(pair, 0, 32), status);
601
- bfloat16 hi = float32_to_bfloat16(extract64(pair, 32, 32), status);
602
- return deposit32(lo, 16, 16, hi);
603
-}
604
-
605
-/*
606
- * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
607
- * must always round-to-nearest; the AArch64 ones honour the FPSCR
608
- * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
609
- * round-to-nearest so either helper will work.) AArch32 float-to-fix
610
- * must round-to-zero.
611
- */
612
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
613
-ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
614
- float_status *fpst) \
615
-{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpst); }
616
-
617
-#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
618
- ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
619
- uint32_t shift, \
620
- float_status *fpst) \
621
- { \
622
- ftype ret; \
623
- FloatRoundMode oldmode = fpst->float_rounding_mode; \
624
- fpst->float_rounding_mode = float_round_nearest_even; \
625
- ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpst); \
626
- fpst->float_rounding_mode = oldmode; \
627
- return ret; \
628
- }
629
-
630
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
631
-uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
632
- float_status *fpst) \
633
-{ \
634
- if (unlikely(float##fsz##_is_any_nan(x))) { \
635
- float_raise(float_flag_invalid, fpst); \
636
- return 0; \
637
- } \
638
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
639
-}
640
-
641
-#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
642
-VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
643
-VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
644
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
645
- float_round_to_zero, _round_to_zero) \
646
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
647
- get_float_rounding_mode(fpst), )
648
-
649
-#define VFP_CONV_FIX_A64(name, p, fsz, ftype, isz, itype) \
650
-VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
651
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
652
- get_float_rounding_mode(fpst), )
653
-
654
-VFP_CONV_FIX(sh, d, 64, float64, 64, int16)
655
-VFP_CONV_FIX(sl, d, 64, float64, 64, int32)
656
-VFP_CONV_FIX_A64(sq, d, 64, float64, 64, int64)
657
-VFP_CONV_FIX(uh, d, 64, float64, 64, uint16)
658
-VFP_CONV_FIX(ul, d, 64, float64, 64, uint32)
659
-VFP_CONV_FIX_A64(uq, d, 64, float64, 64, uint64)
660
-VFP_CONV_FIX(sh, s, 32, float32, 32, int16)
661
-VFP_CONV_FIX(sl, s, 32, float32, 32, int32)
662
-VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64)
663
-VFP_CONV_FIX(uh, s, 32, float32, 32, uint16)
664
-VFP_CONV_FIX(ul, s, 32, float32, 32, uint32)
665
-VFP_CONV_FIX_A64(uq, s, 32, float32, 64, uint64)
666
-VFP_CONV_FIX(sh, h, 16, dh_ctype_f16, 32, int16)
667
-VFP_CONV_FIX(sl, h, 16, dh_ctype_f16, 32, int32)
668
-VFP_CONV_FIX_A64(sq, h, 16, dh_ctype_f16, 64, int64)
669
-VFP_CONV_FIX(uh, h, 16, dh_ctype_f16, 32, uint16)
670
-VFP_CONV_FIX(ul, h, 16, dh_ctype_f16, 32, uint32)
671
-VFP_CONV_FIX_A64(uq, h, 16, dh_ctype_f16, 64, uint64)
672
-VFP_CONV_FLOAT_FIX_ROUND(sq, d, 64, float64, 64, int64,
673
- float_round_to_zero, _round_to_zero)
674
-VFP_CONV_FLOAT_FIX_ROUND(uq, d, 64, float64, 64, uint64,
675
- float_round_to_zero, _round_to_zero)
676
-
677
-#undef VFP_CONV_FIX
678
-#undef VFP_CONV_FIX_FLOAT
679
-#undef VFP_CONV_FLOAT_FIX_ROUND
680
-#undef VFP_CONV_FIX_A64
681
-
682
-/* Set the current fp rounding mode and return the old one.
683
- * The argument is a softfloat float_round_ value.
684
- */
685
-uint32_t HELPER(set_rmode)(uint32_t rmode, float_status *fp_status)
686
-{
687
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
688
- set_float_rounding_mode(rmode, fp_status);
689
-
690
- return prev_rmode;
691
-}
692
-
693
-/* Half precision conversions. */
694
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, float_status *fpst,
695
- uint32_t ahp_mode)
696
-{
697
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
698
- * it would affect flushing input denormals.
699
- */
700
- bool save = get_flush_inputs_to_zero(fpst);
701
- set_flush_inputs_to_zero(false, fpst);
702
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
703
- set_flush_inputs_to_zero(save, fpst);
704
- return r;
705
-}
706
-
707
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, float_status *fpst,
708
- uint32_t ahp_mode)
709
-{
710
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
711
- * it would affect flushing output denormals.
712
- */
713
- bool save = get_flush_to_zero(fpst);
714
- set_flush_to_zero(false, fpst);
715
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
716
- set_flush_to_zero(save, fpst);
717
- return r;
718
-}
719
-
720
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, float_status *fpst,
721
- uint32_t ahp_mode)
722
-{
723
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
724
- * it would affect flushing input denormals.
725
- */
726
- bool save = get_flush_inputs_to_zero(fpst);
727
- set_flush_inputs_to_zero(false, fpst);
728
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
729
- set_flush_inputs_to_zero(save, fpst);
730
- return r;
731
-}
732
-
733
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, float_status *fpst,
734
- uint32_t ahp_mode)
735
-{
736
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
737
- * it would affect flushing output denormals.
738
- */
739
- bool save = get_flush_to_zero(fpst);
740
- set_flush_to_zero(false, fpst);
741
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
742
- set_flush_to_zero(save, fpst);
743
- return r;
744
-}
745
-
746
-/* NEON helpers. */
747
-
748
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
749
- * int->float conversions at run-time. */
750
-#define float64_256 make_float64(0x4070000000000000LL)
751
-#define float64_512 make_float64(0x4080000000000000LL)
752
-#define float16_maxnorm make_float16(0x7bff)
753
-#define float32_maxnorm make_float32(0x7f7fffff)
754
-#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
755
-
756
-/* Reciprocal functions
757
- *
758
- * The algorithm that must be used to calculate the estimate
759
- * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
760
- */
761
-
762
-/* See RecipEstimate()
763
- *
764
- * input is a 9 bit fixed point number
765
- * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
766
- * result range 256 .. 511 for a number from 1.0 to 511/256.
767
- */
768
-
769
-static int recip_estimate(int input)
770
-{
771
- int a, b, r;
772
- assert(256 <= input && input < 512);
773
- a = (input * 2) + 1;
774
- b = (1 << 19) / a;
775
- r = (b + 1) >> 1;
776
- assert(256 <= r && r < 512);
777
- return r;
778
-}
779
-
780
-/*
781
- * Increased precision version:
782
- * input is a 13 bit fixed point number
783
- * input range 2048 .. 4095 for a number from 0.5 <= x < 1.0.
784
- * result range 4096 .. 8191 for a number from 1.0 to 2.0
785
- */
786
-static int recip_estimate_incprec(int input)
787
-{
788
- int a, b, r;
789
- assert(2048 <= input && input < 4096);
790
- a = (input * 2) + 1;
791
- /*
792
- * The pseudocode expresses this as an operation on infinite
793
- * precision reals where it calculates 2^25 / a and then looks
794
- * at the error between that and the rounded-down-to-integer
795
- * value to see if it should instead round up. We instead
796
- * follow the same approach as the pseudocode for the 8-bit
797
- * precision version, and calculate (2 * (2^25 / a)) as an
798
- * integer so we can do the "add one and halve" to round it.
799
- * So the 1 << 26 here is correct.
800
- */
801
- b = (1 << 26) / a;
802
- r = (b + 1) >> 1;
803
- assert(4096 <= r && r < 8192);
804
- return r;
805
-}
806
-
807
-/*
808
- * Common wrapper to call recip_estimate
809
- *
810
- * The parameters are exponent and 64 bit fraction (without implicit
811
- * bit) where the binary point is nominally at bit 52. Returns a
812
- * float64 which can then be rounded to the appropriate size by the
813
- * callee.
814
- */
815
-
816
-static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac,
817
- bool increasedprecision)
818
-{
819
- uint32_t scaled, estimate;
820
- uint64_t result_frac;
821
- int result_exp;
822
-
823
- /* Handle sub-normals */
824
- if (*exp == 0) {
825
- if (extract64(frac, 51, 1) == 0) {
826
- *exp = -1;
827
- frac <<= 2;
828
- } else {
829
- frac <<= 1;
830
- }
831
- }
832
-
833
- if (increasedprecision) {
834
- /* scaled = UInt('1':fraction<51:41>) */
835
- scaled = deposit32(1 << 11, 0, 11, extract64(frac, 41, 11));
836
- estimate = recip_estimate_incprec(scaled);
837
- } else {
838
- /* scaled = UInt('1':fraction<51:44>) */
839
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
840
- estimate = recip_estimate(scaled);
841
- }
842
-
843
- result_exp = exp_off - *exp;
844
- if (increasedprecision) {
845
- result_frac = deposit64(0, 40, 12, estimate);
846
- } else {
847
- result_frac = deposit64(0, 44, 8, estimate);
848
- }
849
- if (result_exp == 0) {
850
- result_frac = deposit64(result_frac >> 1, 51, 1, 1);
851
- } else if (result_exp == -1) {
852
- result_frac = deposit64(result_frac >> 2, 50, 2, 1);
853
- result_exp = 0;
854
- }
855
-
856
- *exp = result_exp;
857
-
858
- return result_frac;
859
-}
860
-
861
-static bool round_to_inf(float_status *fpst, bool sign_bit)
862
-{
863
- switch (fpst->float_rounding_mode) {
864
- case float_round_nearest_even: /* Round to Nearest */
865
- return true;
866
- case float_round_up: /* Round to +Inf */
867
- return !sign_bit;
868
- case float_round_down: /* Round to -Inf */
869
- return sign_bit;
870
- case float_round_to_zero: /* Round to Zero */
871
- return false;
872
- default:
873
- g_assert_not_reached();
874
- }
875
-}
876
-
877
-uint32_t HELPER(recpe_f16)(uint32_t input, float_status *fpst)
878
-{
879
- float16 f16 = float16_squash_input_denormal(input, fpst);
880
- uint32_t f16_val = float16_val(f16);
881
- uint32_t f16_sign = float16_is_neg(f16);
882
- int f16_exp = extract32(f16_val, 10, 5);
883
- uint32_t f16_frac = extract32(f16_val, 0, 10);
884
- uint64_t f64_frac;
885
-
886
- if (float16_is_any_nan(f16)) {
887
- float16 nan = f16;
888
- if (float16_is_signaling_nan(f16, fpst)) {
889
- float_raise(float_flag_invalid, fpst);
890
- if (!fpst->default_nan_mode) {
891
- nan = float16_silence_nan(f16, fpst);
892
- }
893
- }
894
- if (fpst->default_nan_mode) {
895
- nan = float16_default_nan(fpst);
896
- }
897
- return nan;
898
- } else if (float16_is_infinity(f16)) {
899
- return float16_set_sign(float16_zero, float16_is_neg(f16));
900
- } else if (float16_is_zero(f16)) {
901
- float_raise(float_flag_divbyzero, fpst);
902
- return float16_set_sign(float16_infinity, float16_is_neg(f16));
903
- } else if (float16_abs(f16) < (1 << 8)) {
904
- /* Abs(value) < 2.0^-16 */
905
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
906
- if (round_to_inf(fpst, f16_sign)) {
907
- return float16_set_sign(float16_infinity, f16_sign);
908
- } else {
909
- return float16_set_sign(float16_maxnorm, f16_sign);
910
- }
911
- } else if (f16_exp >= 29 && fpst->flush_to_zero) {
912
- float_raise(float_flag_underflow, fpst);
913
- return float16_set_sign(float16_zero, float16_is_neg(f16));
914
- }
915
-
916
- f64_frac = call_recip_estimate(&f16_exp, 29,
917
- ((uint64_t) f16_frac) << (52 - 10), false);
918
-
919
- /* result = sign : result_exp<4:0> : fraction<51:42> */
920
- f16_val = deposit32(0, 15, 1, f16_sign);
921
- f16_val = deposit32(f16_val, 10, 5, f16_exp);
922
- f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
923
- return make_float16(f16_val);
924
-}
925
-
926
-/*
927
- * FEAT_RPRES means the f32 FRECPE has an "increased precision" variant
928
- * which is used when FPCR.AH == 1.
929
- */
930
-static float32 do_recpe_f32(float32 input, float_status *fpst, bool rpres)
931
-{
932
- float32 f32 = float32_squash_input_denormal(input, fpst);
933
- uint32_t f32_val = float32_val(f32);
934
- bool f32_sign = float32_is_neg(f32);
935
- int f32_exp = extract32(f32_val, 23, 8);
936
- uint32_t f32_frac = extract32(f32_val, 0, 23);
937
- uint64_t f64_frac;
938
-
939
- if (float32_is_any_nan(f32)) {
940
- float32 nan = f32;
941
- if (float32_is_signaling_nan(f32, fpst)) {
942
- float_raise(float_flag_invalid, fpst);
943
- if (!fpst->default_nan_mode) {
944
- nan = float32_silence_nan(f32, fpst);
945
- }
946
- }
947
- if (fpst->default_nan_mode) {
948
- nan = float32_default_nan(fpst);
949
- }
950
- return nan;
951
- } else if (float32_is_infinity(f32)) {
952
- return float32_set_sign(float32_zero, float32_is_neg(f32));
953
- } else if (float32_is_zero(f32)) {
954
- float_raise(float_flag_divbyzero, fpst);
955
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
956
- } else if (float32_abs(f32) < (1ULL << 21)) {
957
- /* Abs(value) < 2.0^-128 */
958
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
959
- if (round_to_inf(fpst, f32_sign)) {
960
- return float32_set_sign(float32_infinity, f32_sign);
961
- } else {
962
- return float32_set_sign(float32_maxnorm, f32_sign);
963
- }
964
- } else if (f32_exp >= 253 && fpst->flush_to_zero) {
965
- float_raise(float_flag_underflow, fpst);
966
- return float32_set_sign(float32_zero, float32_is_neg(f32));
967
- }
968
-
969
- f64_frac = call_recip_estimate(&f32_exp, 253,
970
- ((uint64_t) f32_frac) << (52 - 23), rpres);
971
-
972
- /* result = sign : result_exp<7:0> : fraction<51:29> */
973
- f32_val = deposit32(0, 31, 1, f32_sign);
974
- f32_val = deposit32(f32_val, 23, 8, f32_exp);
975
- f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
976
- return make_float32(f32_val);
977
-}
978
-
979
-float32 HELPER(recpe_f32)(float32 input, float_status *fpst)
980
-{
981
- return do_recpe_f32(input, fpst, false);
982
-}
983
-
984
-float32 HELPER(recpe_rpres_f32)(float32 input, float_status *fpst)
985
-{
986
- return do_recpe_f32(input, fpst, true);
987
-}
988
-
989
-float64 HELPER(recpe_f64)(float64 input, float_status *fpst)
990
-{
991
- float64 f64 = float64_squash_input_denormal(input, fpst);
992
- uint64_t f64_val = float64_val(f64);
993
- bool f64_sign = float64_is_neg(f64);
994
- int f64_exp = extract64(f64_val, 52, 11);
995
- uint64_t f64_frac = extract64(f64_val, 0, 52);
996
-
997
- /* Deal with any special cases */
998
- if (float64_is_any_nan(f64)) {
999
- float64 nan = f64;
1000
- if (float64_is_signaling_nan(f64, fpst)) {
1001
- float_raise(float_flag_invalid, fpst);
1002
- if (!fpst->default_nan_mode) {
1003
- nan = float64_silence_nan(f64, fpst);
1004
- }
1005
- }
1006
- if (fpst->default_nan_mode) {
1007
- nan = float64_default_nan(fpst);
1008
- }
1009
- return nan;
1010
- } else if (float64_is_infinity(f64)) {
1011
- return float64_set_sign(float64_zero, float64_is_neg(f64));
1012
- } else if (float64_is_zero(f64)) {
1013
- float_raise(float_flag_divbyzero, fpst);
1014
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
1015
- } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
1016
- /* Abs(value) < 2.0^-1024 */
1017
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
1018
- if (round_to_inf(fpst, f64_sign)) {
1019
- return float64_set_sign(float64_infinity, f64_sign);
1020
- } else {
1021
- return float64_set_sign(float64_maxnorm, f64_sign);
1022
- }
1023
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
1024
- float_raise(float_flag_underflow, fpst);
1025
- return float64_set_sign(float64_zero, float64_is_neg(f64));
1026
- }
1027
-
1028
- f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac, false);
1029
-
1030
- /* result = sign : result_exp<10:0> : fraction<51:0>; */
1031
- f64_val = deposit64(0, 63, 1, f64_sign);
1032
- f64_val = deposit64(f64_val, 52, 11, f64_exp);
1033
- f64_val = deposit64(f64_val, 0, 52, f64_frac);
1034
- return make_float64(f64_val);
1035
-}
1036
-
1037
-/* The algorithm that must be used to calculate the estimate
1038
- * is specified by the ARM ARM.
1039
- */
1040
-
1041
-static int do_recip_sqrt_estimate(int a)
1042
-{
1043
- int b, estimate;
1044
-
1045
- assert(128 <= a && a < 512);
1046
- if (a < 256) {
1047
- a = a * 2 + 1;
1048
- } else {
1049
- a = (a >> 1) << 1;
1050
- a = (a + 1) * 2;
1051
- }
1052
- b = 512;
1053
- while (a * (b + 1) * (b + 1) < (1 << 28)) {
1054
- b += 1;
1055
- }
1056
- estimate = (b + 1) / 2;
1057
- assert(256 <= estimate && estimate < 512);
1058
-
1059
- return estimate;
1060
-}
1061
-
1062
-static int do_recip_sqrt_estimate_incprec(int a)
1063
-{
1064
- /*
1065
- * The Arm ARM describes the 12-bit precision version of RecipSqrtEstimate
1066
- * in terms of an infinite-precision floating point calculation of a
1067
- * square root. We implement this using the same kind of pure integer
1068
- * algorithm as the 8-bit mantissa, to get the same bit-for-bit result.
1069
- */
1070
- int64_t b, estimate;
1071
-
1072
- assert(1024 <= a && a < 4096);
1073
- if (a < 2048) {
1074
- a = a * 2 + 1;
1075
- } else {
1076
- a = (a >> 1) << 1;
1077
- a = (a + 1) * 2;
1078
- }
1079
- b = 8192;
1080
- while (a * (b + 1) * (b + 1) < (1ULL << 39)) {
1081
- b += 1;
1082
- }
1083
- estimate = (b + 1) / 2;
1084
-
1085
- assert(4096 <= estimate && estimate < 8192);
1086
-
1087
- return estimate;
1088
-}
1089
-
1090
-static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac,
1091
- bool increasedprecision)
1092
-{
1093
- int estimate;
1094
- uint32_t scaled;
1095
-
1096
- if (*exp == 0) {
1097
- while (extract64(frac, 51, 1) == 0) {
1098
- frac = frac << 1;
1099
- *exp -= 1;
1100
- }
1101
- frac = extract64(frac, 0, 51) << 1;
1102
- }
1103
-
1104
- if (increasedprecision) {
1105
- if (*exp & 1) {
1106
- /* scaled = UInt('01':fraction<51:42>) */
1107
- scaled = deposit32(1 << 10, 0, 10, extract64(frac, 42, 10));
1108
- } else {
1109
- /* scaled = UInt('1':fraction<51:41>) */
1110
- scaled = deposit32(1 << 11, 0, 11, extract64(frac, 41, 11));
1111
- }
1112
- estimate = do_recip_sqrt_estimate_incprec(scaled);
1113
- } else {
1114
- if (*exp & 1) {
1115
- /* scaled = UInt('01':fraction<51:45>) */
1116
- scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
1117
- } else {
1118
- /* scaled = UInt('1':fraction<51:44>) */
1119
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1120
- }
1121
- estimate = do_recip_sqrt_estimate(scaled);
1122
- }
1123
-
1124
- *exp = (exp_off - *exp) / 2;
1125
- if (increasedprecision) {
1126
- return extract64(estimate, 0, 12) << 40;
1127
- } else {
1128
- return extract64(estimate, 0, 8) << 44;
1129
- }
1130
-}
1131
-
1132
-uint32_t HELPER(rsqrte_f16)(uint32_t input, float_status *s)
1133
-{
1134
- float16 f16 = float16_squash_input_denormal(input, s);
1135
- uint16_t val = float16_val(f16);
1136
- bool f16_sign = float16_is_neg(f16);
1137
- int f16_exp = extract32(val, 10, 5);
1138
- uint16_t f16_frac = extract32(val, 0, 10);
1139
- uint64_t f64_frac;
1140
-
1141
- if (float16_is_any_nan(f16)) {
1142
- float16 nan = f16;
1143
- if (float16_is_signaling_nan(f16, s)) {
1144
- float_raise(float_flag_invalid, s);
1145
- if (!s->default_nan_mode) {
1146
- nan = float16_silence_nan(f16, s);
1147
- }
1148
- }
1149
- if (s->default_nan_mode) {
1150
- nan = float16_default_nan(s);
1151
- }
1152
- return nan;
1153
- } else if (float16_is_zero(f16)) {
1154
- float_raise(float_flag_divbyzero, s);
1155
- return float16_set_sign(float16_infinity, f16_sign);
1156
- } else if (f16_sign) {
1157
- float_raise(float_flag_invalid, s);
1158
- return float16_default_nan(s);
1159
- } else if (float16_is_infinity(f16)) {
1160
- return float16_zero;
1161
- }
1162
-
1163
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1164
- * preserving the parity of the exponent. */
1165
-
1166
- f64_frac = ((uint64_t) f16_frac) << (52 - 10);
1167
-
1168
- f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac, false);
1169
-
1170
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
1171
- val = deposit32(0, 15, 1, f16_sign);
1172
- val = deposit32(val, 10, 5, f16_exp);
1173
- val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
1174
- return make_float16(val);
1175
-}
1176
-
1177
-/*
1178
- * FEAT_RPRES means the f32 FRSQRTE has an "increased precision" variant
1179
- * which is used when FPCR.AH == 1.
1180
- */
1181
-static float32 do_rsqrte_f32(float32 input, float_status *s, bool rpres)
1182
-{
1183
- float32 f32 = float32_squash_input_denormal(input, s);
1184
- uint32_t val = float32_val(f32);
1185
- uint32_t f32_sign = float32_is_neg(f32);
1186
- int f32_exp = extract32(val, 23, 8);
1187
- uint32_t f32_frac = extract32(val, 0, 23);
1188
- uint64_t f64_frac;
1189
-
1190
- if (float32_is_any_nan(f32)) {
1191
- float32 nan = f32;
1192
- if (float32_is_signaling_nan(f32, s)) {
1193
- float_raise(float_flag_invalid, s);
1194
- if (!s->default_nan_mode) {
1195
- nan = float32_silence_nan(f32, s);
1196
- }
1197
- }
1198
- if (s->default_nan_mode) {
1199
- nan = float32_default_nan(s);
1200
- }
1201
- return nan;
1202
- } else if (float32_is_zero(f32)) {
1203
- float_raise(float_flag_divbyzero, s);
1204
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
1205
- } else if (float32_is_neg(f32)) {
1206
- float_raise(float_flag_invalid, s);
1207
- return float32_default_nan(s);
1208
- } else if (float32_is_infinity(f32)) {
1209
- return float32_zero;
1210
- }
1211
-
1212
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1213
- * preserving the parity of the exponent. */
1214
-
1215
- f64_frac = ((uint64_t) f32_frac) << 29;
1216
-
1217
- f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac, rpres);
1218
-
1219
- /*
1220
- * result = sign : result_exp<7:0> : estimate<7:0> : Zeros(15)
1221
- * or for increased precision
1222
- * result = sign : result_exp<7:0> : estimate<11:0> : Zeros(11)
1223
- */
1224
- val = deposit32(0, 31, 1, f32_sign);
1225
- val = deposit32(val, 23, 8, f32_exp);
1226
- if (rpres) {
1227
- val = deposit32(val, 11, 12, extract64(f64_frac, 52 - 12, 12));
1228
- } else {
1229
- val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
1230
- }
1231
- return make_float32(val);
1232
-}
1233
-
1234
-float32 HELPER(rsqrte_f32)(float32 input, float_status *s)
1235
-{
1236
- return do_rsqrte_f32(input, s, false);
1237
-}
1238
-
1239
-float32 HELPER(rsqrte_rpres_f32)(float32 input, float_status *s)
1240
-{
1241
- return do_rsqrte_f32(input, s, true);
1242
-}
1243
-
1244
-float64 HELPER(rsqrte_f64)(float64 input, float_status *s)
1245
-{
1246
- float64 f64 = float64_squash_input_denormal(input, s);
1247
- uint64_t val = float64_val(f64);
1248
- bool f64_sign = float64_is_neg(f64);
1249
- int f64_exp = extract64(val, 52, 11);
1250
- uint64_t f64_frac = extract64(val, 0, 52);
1251
-
1252
- if (float64_is_any_nan(f64)) {
1253
- float64 nan = f64;
1254
- if (float64_is_signaling_nan(f64, s)) {
1255
- float_raise(float_flag_invalid, s);
1256
- if (!s->default_nan_mode) {
1257
- nan = float64_silence_nan(f64, s);
1258
- }
1259
- }
1260
- if (s->default_nan_mode) {
1261
- nan = float64_default_nan(s);
1262
- }
1263
- return nan;
1264
- } else if (float64_is_zero(f64)) {
1265
- float_raise(float_flag_divbyzero, s);
1266
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
1267
- } else if (float64_is_neg(f64)) {
1268
- float_raise(float_flag_invalid, s);
1269
- return float64_default_nan(s);
1270
- } else if (float64_is_infinity(f64)) {
1271
- return float64_zero;
1272
- }
1273
-
1274
- f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac, false);
1275
-
1276
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
1277
- val = deposit64(0, 61, 1, f64_sign);
1278
- val = deposit64(val, 52, 11, f64_exp);
1279
- val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
1280
- return make_float64(val);
1281
-}
1282
-
1283
-uint32_t HELPER(recpe_u32)(uint32_t a)
1284
-{
1285
- int input, estimate;
1286
-
1287
- if ((a & 0x80000000) == 0) {
1288
- return 0xffffffff;
1289
- }
1290
-
1291
- input = extract32(a, 23, 9);
1292
- estimate = recip_estimate(input);
1293
-
1294
- return deposit32(0, (32 - 9), 9, estimate);
1295
-}
1296
-
1297
-uint32_t HELPER(rsqrte_u32)(uint32_t a)
1298
-{
1299
- int estimate;
1300
-
1301
- if ((a & 0xc0000000) == 0) {
1302
- return 0xffffffff;
1303
- }
1304
-
1305
- estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
1306
-
1307
- return deposit32(0, 23, 9, estimate);
1308
-}
1309
-
1310
-/* VFPv4 fused multiply-accumulate */
1311
-dh_ctype_f16 VFP_HELPER(muladd, h)(dh_ctype_f16 a, dh_ctype_f16 b,
1312
- dh_ctype_f16 c, float_status *fpst)
1313
-{
1314
- return float16_muladd(a, b, c, 0, fpst);
1315
-}
1316
-
1317
-float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c,
1318
- float_status *fpst)
1319
-{
1320
- return float32_muladd(a, b, c, 0, fpst);
1321
-}
1322
-
1323
-float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c,
1324
- float_status *fpst)
1325
-{
1326
- return float64_muladd(a, b, c, 0, fpst);
1327
-}
1328
-
1329
-/* ARMv8 round to integral */
1330
-dh_ctype_f16 HELPER(rinth_exact)(dh_ctype_f16 x, float_status *fp_status)
1331
-{
1332
- return float16_round_to_int(x, fp_status);
1333
-}
1334
-
1335
-float32 HELPER(rints_exact)(float32 x, float_status *fp_status)
1336
-{
1337
- return float32_round_to_int(x, fp_status);
1338
-}
1339
-
1340
-float64 HELPER(rintd_exact)(float64 x, float_status *fp_status)
1341
-{
1342
- return float64_round_to_int(x, fp_status);
1343
-}
1344
-
1345
-dh_ctype_f16 HELPER(rinth)(dh_ctype_f16 x, float_status *fp_status)
1346
-{
1347
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1348
- float16 ret;
1349
-
1350
- ret = float16_round_to_int(x, fp_status);
1351
-
1352
- /* Suppress any inexact exceptions the conversion produced */
1353
- if (!(old_flags & float_flag_inexact)) {
1354
- new_flags = get_float_exception_flags(fp_status);
1355
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1356
- }
1357
-
1358
- return ret;
1359
-}
1360
-
1361
-float32 HELPER(rints)(float32 x, float_status *fp_status)
1362
-{
1363
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1364
- float32 ret;
1365
-
1366
- ret = float32_round_to_int(x, fp_status);
1367
-
1368
- /* Suppress any inexact exceptions the conversion produced */
1369
- if (!(old_flags & float_flag_inexact)) {
1370
- new_flags = get_float_exception_flags(fp_status);
1371
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1372
- }
1373
-
1374
- return ret;
1375
-}
1376
-
1377
-float64 HELPER(rintd)(float64 x, float_status *fp_status)
1378
-{
1379
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1380
- float64 ret;
1381
-
1382
- ret = float64_round_to_int(x, fp_status);
1383
-
1384
- /* Suppress any inexact exceptions the conversion produced */
1385
- if (!(old_flags & float_flag_inexact)) {
1386
- new_flags = get_float_exception_flags(fp_status);
1387
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1388
- }
1389
-
1390
- return ret;
1391
-}
1392
-
1393
-/* Convert ARM rounding mode to softfloat */
1394
-const FloatRoundMode arm_rmode_to_sf_map[] = {
1395
- [FPROUNDING_TIEEVEN] = float_round_nearest_even,
1396
- [FPROUNDING_POSINF] = float_round_up,
1397
- [FPROUNDING_NEGINF] = float_round_down,
1398
- [FPROUNDING_ZERO] = float_round_to_zero,
1399
- [FPROUNDING_TIEAWAY] = float_round_ties_away,
1400
- [FPROUNDING_ODD] = float_round_to_odd,
1401
-};
1402
-
1403
-/*
1404
- * Implement float64 to int32_t conversion without saturation;
1405
- * the result is supplied modulo 2^32.
1406
- */
1407
-uint64_t HELPER(fjcvtzs)(float64 value, float_status *status)
1408
-{
1409
- uint32_t frac, e_old, e_new;
1410
- bool inexact;
1411
-
1412
- e_old = get_float_exception_flags(status);
1413
- set_float_exception_flags(0, status);
1414
- frac = float64_to_int32_modulo(value, float_round_to_zero, status);
1415
- e_new = get_float_exception_flags(status);
1416
- set_float_exception_flags(e_old | e_new, status);
1417
-
1418
- /* Normal inexact, denormal with flush-to-zero, or overflow or NaN */
1419
- inexact = e_new & (float_flag_inexact |
1420
- float_flag_input_denormal_flushed |
1421
- float_flag_invalid);
1422
-
1423
- /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
1424
- inexact |= value == float64_chs(float64_zero);
1425
-
1426
- /* Pack the result and the env->ZF representation of Z together. */
1427
- return deposit64(frac, 32, 32, inexact);
1428
-}
1429
-
1430
-uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
1431
-{
1432
- uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status[FPST_A32]);
1433
- uint32_t result = pair;
1434
- uint32_t z = (pair >> 32) == 0;
1435
-
1436
- /* Store Z, clear NCV, in FPSCR.NZCV. */
1437
- env->vfp.fpsr = (env->vfp.fpsr & ~FPSR_NZCV_MASK) | (z * FPSR_Z);
1438
-
1439
- return result;
1440
-}
1441
-
1442
-/* Round a float32 to an integer that fits in int32_t or int64_t. */
1443
-static float32 frint_s(float32 f, float_status *fpst, int intsize)
1444
-{
1445
- int old_flags = get_float_exception_flags(fpst);
1446
- uint32_t exp = extract32(f, 23, 8);
1447
-
1448
- if (unlikely(exp == 0xff)) {
1449
- /* NaN or Inf. */
1450
- goto overflow;
1451
- }
1452
-
1453
- /* Round and re-extract the exponent. */
1454
- f = float32_round_to_int(f, fpst);
1455
- exp = extract32(f, 23, 8);
1456
-
1457
- /* Validate the range of the result. */
1458
- if (exp < 126 + intsize) {
1459
- /* abs(F) <= INT{N}_MAX */
1460
- return f;
1461
- }
1462
- if (exp == 126 + intsize) {
1463
- uint32_t sign = extract32(f, 31, 1);
1464
- uint32_t frac = extract32(f, 0, 23);
1465
- if (sign && frac == 0) {
1466
- /* F == INT{N}_MIN */
1467
- return f;
1468
- }
1469
- }
1470
-
1471
- overflow:
1472
- /*
1473
- * Raise Invalid and return INT{N}_MIN as a float. Revert any
1474
- * inexact exception float32_round_to_int may have raised.
1475
- */
1476
- set_float_exception_flags(old_flags | float_flag_invalid, fpst);
1477
- return (0x100u + 126u + intsize) << 23;
1478
-}
1479
-
1480
-float32 HELPER(frint32_s)(float32 f, float_status *fpst)
1481
-{
1482
- return frint_s(f, fpst, 32);
1483
-}
1484
-
1485
-float32 HELPER(frint64_s)(float32 f, float_status *fpst)
1486
-{
1487
- return frint_s(f, fpst, 64);
1488
-}
1489
-
1490
-/* Round a float64 to an integer that fits in int32_t or int64_t. */
1491
-static float64 frint_d(float64 f, float_status *fpst, int intsize)
1492
-{
1493
- int old_flags = get_float_exception_flags(fpst);
1494
- uint32_t exp = extract64(f, 52, 11);
1495
-
1496
- if (unlikely(exp == 0x7ff)) {
1497
- /* NaN or Inf. */
1498
- goto overflow;
1499
- }
1500
-
1501
- /* Round and re-extract the exponent. */
1502
- f = float64_round_to_int(f, fpst);
1503
- exp = extract64(f, 52, 11);
1504
-
1505
- /* Validate the range of the result. */
1506
- if (exp < 1022 + intsize) {
1507
- /* abs(F) <= INT{N}_MAX */
1508
- return f;
1509
- }
1510
- if (exp == 1022 + intsize) {
1511
- uint64_t sign = extract64(f, 63, 1);
1512
- uint64_t frac = extract64(f, 0, 52);
1513
- if (sign && frac == 0) {
1514
- /* F == INT{N}_MIN */
1515
- return f;
1516
- }
1517
- }
1518
-
1519
- overflow:
1520
- /*
1521
- * Raise Invalid and return INT{N}_MIN as a float. Revert any
1522
- * inexact exception float64_round_to_int may have raised.
1523
- */
1524
- set_float_exception_flags(old_flags | float_flag_invalid, fpst);
1525
- return (uint64_t)(0x800 + 1022 + intsize) << 52;
1526
-}
1527
-
1528
-float64 HELPER(frint32_d)(float64 f, float_status *fpst)
1529
-{
1530
- return frint_d(f, fpst, 32);
1531
-}
1532
-
1533
-float64 HELPER(frint64_d)(float64 f, float_status *fpst)
1534
-{
1535
- return frint_d(f, fpst, 64);
1536
-}
1537
-
1538
-void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
1539
-{
1540
- uint32_t syndrome;
1541
-
1542
- switch (reg) {
1543
- case ARM_VFP_MVFR0:
1544
- case ARM_VFP_MVFR1:
1545
- case ARM_VFP_MVFR2:
1546
- if (!(arm_hcr_el2_eff(env) & HCR_TID3)) {
1547
- return;
1548
- }
1549
- break;
1550
- case ARM_VFP_FPSID:
1551
- if (!(arm_hcr_el2_eff(env) & HCR_TID0)) {
1552
- return;
1553
- }
1554
- break;
1555
- default:
1556
- g_assert_not_reached();
1557
- }
1558
-
1559
- syndrome = ((EC_FPIDTRAP << ARM_EL_EC_SHIFT)
1560
- | ARM_EL_IL
1561
- | (1 << 24) | (0xe << 20) | (7 << 14)
1562
- | (reg << 10) | (rt << 5) | 1);
1563
-
1564
- raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
1565
-}
1566
-
1567
-#endif
1568
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
1569
index XXXXXXX..XXXXXXX 100644
1570
--- a/target/arm/tcg/meson.build
1571
+++ b/target/arm/tcg/meson.build
1572
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
1573
'vec_helper.c',
1574
'tlb-insns.c',
1575
'arith_helper.c',
1576
+ 'vfp_helper.c',
1577
))
1578
1579
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
70
--
1580
--
71
2.20.1
1581
2.43.0
72
73
diff view generated by jsdifflib
1
Switch the CMSDK APB timer device over to using its Clock input; the
1
Currently the helper_vfp_get_fpscr() and helper_vfp_set_fpscr()
2
pclk-frq property is now ignored.
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.
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.
3
13
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
16
Message-id: 20250221190957.811948-3-peter.maydell@linaro.org
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-19-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-19-peter.maydell@linaro.org
10
---
17
---
11
hw/timer/cmsdk-apb-timer.c | 18 ++++++++++++++----
18
target/arm/tcg/vfp_helper.c | 10 ++++++++++
12
1 file changed, 14 insertions(+), 4 deletions(-)
19
target/arm/vfp_helper.c | 15 ++-------------
20
2 files changed, 12 insertions(+), 13 deletions(-)
13
21
14
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
22
diff --git a/target/arm/tcg/vfp_helper.c b/target/arm/tcg/vfp_helper.c
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/timer/cmsdk-apb-timer.c
24
--- a/target/arm/tcg/vfp_helper.c
17
+++ b/hw/timer/cmsdk-apb-timer.c
25
+++ b/target/arm/tcg/vfp_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
26
@@ -XXX,XX +XXX,XX @@ void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
19
ptimer_transaction_commit(s->timer);
27
28
raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
20
}
29
}
21
30
+
22
+static void cmsdk_apb_timer_clk_update(void *opaque)
31
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
23
+{
32
+{
24
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
33
+ return vfp_get_fpscr(env);
25
+
26
+ ptimer_transaction_begin(s->timer);
27
+ ptimer_set_period_from_clock(s->timer, s->pclk, 1);
28
+ ptimer_transaction_commit(s->timer);
29
+}
34
+}
30
+
35
+
31
static void cmsdk_apb_timer_init(Object *obj)
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)
32
{
58
{
33
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
59
return (vfp_get_fpcr(env) & FPSCR_FPCR_MASK) |
34
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
60
(vfp_get_fpsr(env) & FPSCR_FPSR_MASK);
35
s, "cmsdk-apb-timer", 0x1000);
36
sysbus_init_mmio(sbd, &s->iomem);
37
sysbus_init_irq(sbd, &s->timerint);
38
- s->pclk = qdev_init_clock_in(DEVICE(s), "pclk", NULL, NULL);
39
+ s->pclk = qdev_init_clock_in(DEVICE(s), "pclk",
40
+ cmsdk_apb_timer_clk_update, s);
41
}
61
}
42
62
43
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
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)
44
{
69
{
45
CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
70
ARMCPU *cpu = env_archcpu(env);
46
71
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpcr(CPUARMState *env, uint32_t val)
47
- if (s->pclk_frq == 0) {
72
vfp_set_fpcr_masked(env, val, MAKE_64BIT_MASK(0, 32));
48
- error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
49
+ if (!clock_has_source(s->pclk)) {
50
+ error_setg(errp, "CMSDK APB timer: pclk clock must be connected");
51
return;
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
55
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
56
57
ptimer_transaction_begin(s->timer);
58
- ptimer_set_freq(s->timer, s->pclk_frq);
59
+ ptimer_set_period_from_clock(s->timer, s->pclk, 1);
60
ptimer_transaction_commit(s->timer);
61
}
73
}
62
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
-}
63
--
86
--
64
2.20.1
87
2.43.0
65
66
diff view generated by jsdifflib
1
Add a simple test of the CMSDK watchdog, since we're about to do some
1
The softfloat (i.e. TCG) specific handling for the FPCR
2
refactoring of how it is clocked.
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
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.
3
20
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Message-id: 20250221190957.811948-4-peter.maydell@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-5-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-5-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
---
24
---
12
tests/qtest/cmsdk-apb-watchdog-test.c | 79 +++++++++++++++++++++++++++
25
target/arm/internals.h | 9 ++
13
MAINTAINERS | 1 +
26
target/arm/tcg-stubs.c | 22 ++++
14
tests/qtest/meson.build | 1 +
27
target/arm/tcg/vfp_helper.c | 228 +++++++++++++++++++++++++++++++++
15
3 files changed, 81 insertions(+)
28
target/arm/vfp_helper.c | 248 ------------------------------------
16
create mode 100644 tests/qtest/cmsdk-apb-watchdog-test.c
29
4 files changed, 259 insertions(+), 248 deletions(-)
17
30
18
diff --git a/tests/qtest/cmsdk-apb-watchdog-test.c b/tests/qtest/cmsdk-apb-watchdog-test.c
31
diff --git a/target/arm/internals.h b/target/arm/internals.h
19
new file mode 100644
32
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX
33
--- a/target/arm/internals.h
21
--- /dev/null
34
+++ b/target/arm/internals.h
22
+++ b/tests/qtest/cmsdk-apb-watchdog-test.c
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
23
@@ -XXX,XX +XXX,XX @@
84
@@ -XXX,XX +XXX,XX @@
85
#include "fpu/softfloat.h"
86
#include "qemu/log.h"
87
24
+/*
88
+/*
25
+ * QTest testcase for the CMSDK APB watchdog device
89
+ * Set the float_status behaviour to match the Arm defaults:
26
+ *
90
+ * * tininess-before-rounding
27
+ * Copyright (c) 2021 Linaro Limited
91
+ * * 2-input NaN propagation prefers SNaN over QNaN, and then
28
+ *
92
+ * operand A over operand B (see FPProcessNaNs() pseudocode)
29
+ * This program is free software; you can redistribute it and/or modify it
93
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
30
+ * under the terms of the GNU General Public License as published by the
94
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
31
+ * Free Software Foundation; either version 2 of the License, or
95
+ * but note that for QEMU muladd is a * b + c, whereas for
32
+ * (at your option) any later version.
96
+ * the pseudocode function the arguments are in the order c, a, b.
33
+ *
97
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
98
+ * and the input NaN if it is signalling
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
99
+ * * Default NaN has sign bit clear, msb frac bit set
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
100
+ */
39
+
101
+void arm_set_default_fp_behaviours(float_status *s)
40
+#include "qemu/osdep.h"
102
+{
41
+#include "libqtest-single.h"
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
+}
42
+
110
+
43
+/*
111
+/*
44
+ * lm3s811evb watchdog; at board startup this runs at 200MHz / 16 == 12.5MHz,
112
+ * Set the float_status behaviour to match the FEAT_AFP
45
+ * which is 80ns per tick.
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
46
+ */
120
+ */
47
+#define WDOG_BASE 0x40000000
121
+void arm_set_ah_fp_behaviours(float_status *s)
48
+
122
+{
49
+#define WDOGLOAD 0
123
+ set_float_detect_tininess(float_tininess_after_rounding, s);
50
+#define WDOGVALUE 4
124
+ set_float_ftz_detection(float_ftz_after_rounding, s);
51
+#define WDOGCONTROL 8
125
+ set_float_2nan_prop_rule(float_2nan_prop_ab, s);
52
+#define WDOGINTCLR 0xc
126
+ set_float_3nan_prop_rule(float_3nan_prop_abc, s);
53
+#define WDOGRIS 0x10
127
+ set_float_infzeronan_rule(float_infzeronan_dnan_never |
54
+#define WDOGMIS 0x14
128
+ float_infzeronan_suppress_invalid, s);
55
+#define WDOGLOCK 0xc00
129
+ set_float_default_nan_pattern(0b11000000, s);
56
+
130
+}
57
+static void test_watchdog(void)
131
+
58
+{
132
+/* Convert host exception flags to vfp form. */
59
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
133
+static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
60
+
134
+{
61
+ writel(WDOG_BASE + WDOGCONTROL, 1);
135
+ uint32_t target_bits = 0;
62
+ writel(WDOG_BASE + WDOGLOAD, 1000);
136
+
63
+
137
+ if (host_bits & float_flag_invalid) {
64
+ /* Step to just past the 500th tick */
138
+ target_bits |= FPSR_IOC;
65
+ clock_step(500 * 80 + 1);
139
+ }
66
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
140
+ if (host_bits & float_flag_divbyzero) {
67
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
141
+ target_bits |= FPSR_DZC;
68
+
142
+ }
69
+ /* Just past the 1000th tick: timer should have fired */
143
+ if (host_bits & float_flag_overflow) {
70
+ clock_step(500 * 80);
144
+ target_bits |= FPSR_OFC;
71
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
145
+ }
72
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0);
146
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
73
+
147
+ target_bits |= FPSR_UFC;
74
+ /* VALUE reloads at following tick */
148
+ }
75
+ clock_step(80);
149
+ if (host_bits & float_flag_inexact) {
76
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
150
+ target_bits |= FPSR_IXC;
77
+
151
+ }
78
+ /* Writing any value to WDOGINTCLR clears the interrupt and reloads */
152
+ if (host_bits & float_flag_input_denormal_flushed) {
79
+ clock_step(500 * 80);
153
+ target_bits |= FPSR_IDC;
80
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
154
+ }
81
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
155
+ /*
82
+ writel(WDOG_BASE + WDOGINTCLR, 0);
156
+ * With FPCR.AH, IDC is set when an input denormal is used,
83
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
157
+ * and flushing an output denormal to zero sets both IXC and UFC.
84
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
158
+ */
85
+}
159
+ if (ah && (host_bits & float_flag_input_denormal_used)) {
86
+
160
+ target_bits |= FPSR_IDC;
87
+int main(int argc, char **argv)
161
+ }
88
+{
162
+ if (ah && (host_bits & float_flag_output_denormal_flushed)) {
89
+ int r;
163
+ target_bits |= FPSR_IXC;
90
+
164
+ }
91
+ g_test_init(&argc, &argv, NULL);
165
+ return target_bits;
92
+
166
+}
93
+ qtest_start("-machine lm3s811evb");
167
+
94
+
168
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
95
+ qtest_add_func("/cmsdk-apb-watchdog/watchdog", test_watchdog);
169
+{
96
+
170
+ uint32_t a32_flags = 0, a64_flags = 0;
97
+ r = g_test_run();
171
+
98
+
172
+ a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
99
+ qtest_end();
173
+ a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
100
+
174
+ /* FZ16 does not generate an input denormal exception. */
101
+ return r;
175
+ a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
102
+}
176
+ & ~float_flag_input_denormal_flushed);
103
diff --git a/MAINTAINERS b/MAINTAINERS
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
104
index XXXXXXX..XXXXXXX 100644
320
index XXXXXXX..XXXXXXX 100644
105
--- a/MAINTAINERS
321
--- a/target/arm/vfp_helper.c
106
+++ b/MAINTAINERS
322
+++ b/target/arm/vfp_helper.c
107
@@ -XXX,XX +XXX,XX @@ F: hw/char/cmsdk-apb-uart.c
323
@@ -XXX,XX +XXX,XX @@
108
F: include/hw/char/cmsdk-apb-uart.h
324
#include "cpu.h"
109
F: hw/watchdog/cmsdk-apb-watchdog.c
325
#include "internals.h"
110
F: include/hw/watchdog/cmsdk-apb-watchdog.h
326
#include "cpu-features.h"
111
+F: tests/qtest/cmsdk-apb-watchdog-test.c
327
-#include "fpu/softfloat.h"
112
F: hw/misc/tz-ppc.c
328
-
113
F: include/hw/misc/tz-ppc.h
329
-/*
114
F: hw/misc/tz-mpc.c
330
- * Set the float_status behaviour to match the Arm defaults:
115
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
331
- * * tininess-before-rounding
116
index XXXXXXX..XXXXXXX 100644
332
- * * 2-input NaN propagation prefers SNaN over QNaN, and then
117
--- a/tests/qtest/meson.build
333
- * operand A over operand B (see FPProcessNaNs() pseudocode)
118
+++ b/tests/qtest/meson.build
334
- * * 3-input NaN propagation prefers SNaN over QNaN, and then
119
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
335
- * operand C over A over B (see FPProcessNaNs3() pseudocode,
120
'npcm7xx_watchdog_timer-test']
336
- * but note that for QEMU muladd is a * b + c, whereas for
121
qtests_arm = \
337
- * the pseudocode function the arguments are in the order c, a, b.
122
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
338
- * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
123
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
339
- * and the input NaN if it is signalling
124
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
340
- * * Default NaN has sign bit clear, msb frac bit set
125
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
341
- */
126
['arm-cpu-features',
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
{
127
--
578
--
128
2.20.1
579
2.43.0
129
130
diff view generated by jsdifflib
1
Remove all the code that sets frequency properties on the CMSDK
1
The vfp_helper.c in the target/arm directory now only has
2
timer, dualtimer and watchdog devices and on the ARMSSE SoC device:
2
code for handling FPSCR/FPCR/FPSR in it, and no helper
3
these properties are unused now that the devices rely on their Clock
3
functions. Rename it to vfp_fpscr.c; this helps keep it
4
inputs instead.
4
distinct from tcg/vfp_helper.c.
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Message-id: 20250221190957.811948-5-peter.maydell@linaro.org
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210128114145.20536-24-peter.maydell@linaro.org
11
Message-id: 20210121190622.22000-24-peter.maydell@linaro.org
12
---
9
---
13
hw/arm/armsse.c | 7 -------
10
target/arm/{vfp_helper.c => vfp_fpscr.c} | 2 +-
14
hw/arm/mps2-tz.c | 1 -
11
target/arm/meson.build | 2 +-
15
hw/arm/mps2.c | 3 ---
12
2 files changed, 2 insertions(+), 2 deletions(-)
16
hw/arm/musca.c | 1 -
13
rename target/arm/{vfp_helper.c => vfp_fpscr.c} (98%)
17
hw/arm/stellaris.c | 3 ---
18
5 files changed, 15 deletions(-)
19
14
20
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
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
21
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/armsse.c
20
--- a/target/arm/vfp_helper.c
23
+++ b/hw/arm/armsse.c
21
+++ b/target/arm/vfp_fpscr.c
24
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
22
@@ -XXX,XX +XXX,XX @@
25
* it to the appropriate PPC port; then we can realize the PPC and
23
/*
26
* map its upstream ends to the right place in the container.
24
- * ARM VFP floating-point operations
27
*/
25
+ * ARM VFP floating-point: handling of FPSCR/FPCR/FPSR
28
- qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
26
*
29
qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
27
* Copyright (c) 2003 Fabrice Bellard
30
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
28
*
31
return;
29
diff --git a/target/arm/meson.build b/target/arm/meson.build
32
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
33
object_property_set_link(OBJECT(&s->apb_ppc0), "port[0]", OBJECT(mr),
34
&error_abort);
35
36
- qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
37
qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
38
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
39
return;
40
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
41
object_property_set_link(OBJECT(&s->apb_ppc0), "port[1]", OBJECT(mr),
42
&error_abort);
43
44
- qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
45
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
46
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
47
return;
48
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
49
/* Devices behind APB PPC1:
50
* 0x4002f000: S32K timer
51
*/
52
- qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
53
qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
54
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
55
return;
56
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
57
qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
58
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
59
60
- qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
61
qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
62
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
63
return;
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
66
/* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
67
68
- qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
69
qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
70
if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
71
return;
72
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
73
armsse_get_common_irq_in(s, 1));
74
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
75
76
- qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
77
qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
78
if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
79
return;
80
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
81
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/arm/mps2-tz.c
31
--- a/target/arm/meson.build
83
+++ b/hw/arm/mps2-tz.c
32
+++ b/target/arm/meson.build
84
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
33
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
85
object_property_set_link(OBJECT(&mms->iotkit), "memory",
34
'debug_helper.c',
86
OBJECT(system_memory), &error_abort);
35
'gdbstub.c',
87
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
36
'helper.c',
88
- qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
37
- 'vfp_helper.c',
89
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
38
+ 'vfp_fpscr.c',
90
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
39
))
91
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
40
arm_ss.add(zlib)
92
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/arm/mps2.c
95
+++ b/hw/arm/mps2.c
96
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
97
object_initialize_child(OBJECT(mms), name, &mms->timer[i],
98
TYPE_CMSDK_APB_TIMER);
99
sbd = SYS_BUS_DEVICE(&mms->timer[i]);
100
- qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
101
qdev_connect_clock_in(DEVICE(&mms->timer[i]), "pclk", mms->sysclk);
102
sysbus_realize_and_unref(sbd, &error_fatal);
103
sysbus_mmio_map(sbd, 0, base);
104
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
105
106
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
107
TYPE_CMSDK_APB_DUALTIMER);
108
- qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
109
qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->sysclk);
110
sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
111
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
112
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
113
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
114
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
115
TYPE_CMSDK_APB_WATCHDOG);
116
- qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
117
qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->sysclk);
118
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
119
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
120
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/arm/musca.c
123
+++ b/hw/arm/musca.c
124
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
125
qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
126
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
127
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
128
- qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
129
qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
130
qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
131
/*
132
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/arm/stellaris.c
135
+++ b/hw/arm/stellaris.c
136
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
137
if (board->dc1 & (1 << 3)) { /* watchdog present */
138
dev = qdev_new(TYPE_LUMINARY_WATCHDOG);
139
140
- /* system_clock_scale is valid now */
141
- uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
142
- qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
143
qdev_connect_clock_in(dev, "WDOGCLK",
144
qdev_get_clock_out(ssys_dev, "SYSCLK"));
145
41
146
--
42
--
147
2.20.1
43
2.43.0
148
149
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Joelle van Dyne <j@getutm.app>
2
2
3
On iOS there is no CoreAudio, so we should not assume Darwin always
3
macOS 15.2's Hypervisor.framework exposes SME feature on M4 Macs.
4
has it.
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:
5
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
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
18
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Message-id: 20250224165735.36792-1-j@getutm.app
8
Message-id: 20210126012457.39046-11-j@getutm.app
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
[PMM: expanded commit message, comment]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
23
---
11
configure | 35 +++++++++++++++++++++++++++++++++--
24
target/arm/hvf/hvf.c | 12 ++++++++++++
12
1 file changed, 33 insertions(+), 2 deletions(-)
25
1 file changed, 12 insertions(+)
13
26
14
diff --git a/configure b/configure
27
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
15
index XXXXXXX..XXXXXXX 100755
28
index XXXXXXX..XXXXXXX 100644
16
--- a/configure
29
--- a/target/arm/hvf/hvf.c
17
+++ b/configure
30
+++ b/target/arm/hvf/hvf.c
18
@@ -XXX,XX +XXX,XX @@ fdt="auto"
31
@@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
19
netmap="no"
32
20
sdl="auto"
33
clamp_id_aa64mmfr0_parange_to_ipa_size(&host_isar.id_aa64mmfr0);
21
sdl_image="auto"
34
22
+coreaudio="auto"
35
+ /*
23
virtiofsd="auto"
36
+ * Disable SME, which is not properly handled by QEMU hvf yet.
24
virtfs="auto"
37
+ * To allow this through we would need to:
25
libudev="auto"
38
+ * - make sure that the SME state is correctly handled in the
26
@@ -XXX,XX +XXX,XX @@ Darwin)
39
+ * get_registers/put_registers functions
27
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
40
+ * - get the SME-specific CPU properties to work with accelerators
28
QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS"
41
+ * other than TCG
29
fi
42
+ * - fix any assumptions we made that SME implies SVE (since
30
- audio_drv_list="coreaudio try-sdl"
43
+ * on the M4 there is SME but not SVE)
31
+ audio_drv_list="try-coreaudio try-sdl"
44
+ */
32
audio_possible_drivers="coreaudio sdl"
45
+ host_isar.id_aa64pfr1 &= ~R_ID_AA64PFR1_SME_MASK;
33
# Disable attempts to use ObjectiveC features in os/object.h since they
34
# won't work when we're compiling with gcc as a C compiler.
35
@@ -XXX,XX +XXX,XX @@ EOF
36
fi
37
fi
38
39
+##########################################
40
+# detect CoreAudio
41
+if test "$coreaudio" != "no" ; then
42
+ coreaudio_libs="-framework CoreAudio"
43
+ cat > $TMPC << EOF
44
+#include <CoreAudio/CoreAudio.h>
45
+int main(void)
46
+{
47
+ return (int)AudioGetCurrentHostTime();
48
+}
49
+EOF
50
+ if compile_prog "" "$coreaudio_libs" ; then
51
+ coreaudio=yes
52
+ else
53
+ coreaudio=no
54
+ fi
55
+fi
56
+
46
+
57
##########################################
47
ahcf->isar = host_isar;
58
# Sound support libraries probe
48
59
49
/*
60
@@ -XXX,XX +XXX,XX @@ for drv in $audio_drv_list; do
61
fi
62
;;
63
64
- coreaudio)
65
+ coreaudio | try-coreaudio)
66
+ if test "$coreaudio" = "no"; then
67
+ if test "$drv" = "try-coreaudio"; then
68
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio//')
69
+ else
70
+ error_exit "$drv check failed" \
71
+ "Make sure to have the $drv is available."
72
+ fi
73
+ else
74
coreaudio_libs="-framework CoreAudio"
75
+ if test "$drv" = "try-coreaudio"; then
76
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio/coreaudio/')
77
+ fi
78
+ fi
79
;;
80
81
dsound)
82
--
50
--
83
2.20.1
51
2.43.0
84
85
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Joelle van Dyne <j@getutm.app>
2
2
3
Build without error on hosts without a working system(). If system()
3
In the syndrome value for a data abort, bit 21 is SSE, which is
4
is called, return -1 with ENOSYS.
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.
5
9
10
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
11
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Message-id: 20210126012457.39046-6-j@getutm.app
12
Message-id: 20250224184123.50780-1-j@getutm.app
13
[PMM: Drop an unnecessary check on 'len'; expand commit message]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
16
---
11
meson.build | 1 +
17
target/arm/hvf/hvf.c | 4 ++++
12
include/qemu/osdep.h | 12 ++++++++++++
18
1 file changed, 4 insertions(+)
13
2 files changed, 13 insertions(+)
14
19
15
diff --git a/meson.build b/meson.build
20
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/meson.build
22
--- a/target/arm/hvf/hvf.c
18
+++ b/meson.build
23
+++ b/target/arm/hvf/hvf.c
19
@@ -XXX,XX +XXX,XX @@ config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
24
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
20
config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
25
bool isv = syndrome & ARM_EL_ISV;
21
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
26
bool iswrite = (syndrome >> 6) & 1;
22
config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
27
bool s1ptw = (syndrome >> 7) & 1;
23
+config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
28
+ bool sse = (syndrome >> 21) & 1;
24
29
uint32_t sas = (syndrome >> 22) & 3;
25
config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
30
uint32_t len = 1 << sas;
26
31
uint32_t srt = (syndrome >> 16) & 0x1f;
27
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
32
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
28
index XXXXXXX..XXXXXXX 100644
33
address_space_read(&address_space_memory,
29
--- a/include/qemu/osdep.h
34
hvf_exit->exception.physical_address,
30
+++ b/include/qemu/osdep.h
35
MEMTXATTRS_UNSPECIFIED, &val, len);
31
@@ -XXX,XX +XXX,XX @@ static inline void qemu_thread_jit_write(void) {}
36
+ if (sse) {
32
static inline void qemu_thread_jit_execute(void) {}
37
+ val = sextract64(val, 0, len * 8);
33
#endif
38
+ }
34
39
hvf_set_reg(cpu, srt, val);
35
+/**
40
}
36
+ * Platforms which do not support system() return ENOSYS
41
37
+ */
38
+#ifndef HAVE_SYSTEM_FUNCTION
39
+#define system platform_does_not_support_system
40
+static inline int platform_does_not_support_system(const char *command)
41
+{
42
+ errno = ENOSYS;
43
+ return -1;
44
+}
45
+#endif /* !HAVE_SYSTEM_FUNCTION */
46
+
47
#endif
48
--
42
--
49
2.20.1
43
2.43.0
50
51
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
2
2
3
The properties to attach a CANBUS object to the xlnx-zcu102 machine have
3
Regression introduced by cf76c4
4
a period in them. We want to use periods in properties for compound QAPI types,
4
(hw/misc: Add nr_regs and cold_reset_values to NPCM CLK)
5
and besides the "xlnx-zcu102." prefix is both unnecessary and different
6
from any other machine property name. Remove it.
7
5
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
cold_reset_values has a different size, depending on device used
9
Message-id: 20210118162537.779542-1-pbonzini@redhat.com
7
(NPCM7xx vs NPCM8xx). However, s->regs has a fixed size, which matches
10
Reviewed-by: Vikram Garhwal <fnu.vikram@xilinx.com>
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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
67
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
68
---
13
hw/arm/xlnx-zcu102.c | 4 ++--
69
hw/misc/npcm_clk.c | 5 +++--
14
tests/qtest/xlnx-can-test.c | 30 +++++++++++++++---------------
70
1 file changed, 3 insertions(+), 2 deletions(-)
15
2 files changed, 17 insertions(+), 17 deletions(-)
16
71
17
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
72
diff --git a/hw/misc/npcm_clk.c b/hw/misc/npcm_clk.c
18
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/xlnx-zcu102.c
74
--- a/hw/misc/npcm_clk.c
20
+++ b/hw/arm/xlnx-zcu102.c
75
+++ b/hw/misc/npcm_clk.c
21
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
76
@@ -XXX,XX +XXX,XX @@ static void npcm_clk_enter_reset(Object *obj, ResetType type)
22
s->secure = false;
77
NPCMCLKState *s = NPCM_CLK(obj);
23
/* Default to virt (EL2) being disabled */
78
NPCMCLKClass *c = NPCM_CLK_GET_CLASS(s);
24
s->virt = false;
79
25
- object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
80
- g_assert(sizeof(s->regs) >= c->nr_regs * sizeof(uint32_t));
26
+ object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
81
- memcpy(s->regs, c->cold_reset_values, sizeof(s->regs));
27
(Object **)&s->canbus[0],
82
+ size_t sizeof_regs = c->nr_regs * sizeof(uint32_t);
28
object_property_allow_set_link,
83
+ g_assert(sizeof(s->regs) >= sizeof_regs);
29
0);
84
+ memcpy(s->regs, c->cold_reset_values, sizeof_regs);
30
85
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
31
- object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
86
npcm7xx_clk_update_all_clocks(s);
32
+ object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
87
/*
33
(Object **)&s->canbus[1],
34
object_property_allow_set_link,
35
0);
36
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qtest/xlnx-can-test.c
39
+++ b/tests/qtest/xlnx-can-test.c
40
@@ -XXX,XX +XXX,XX @@ static void test_can_bus(void)
41
uint8_t can_timestamp = 1;
42
43
QTestState *qts = qtest_init("-machine xlnx-zcu102"
44
- " -object can-bus,id=canbus0"
45
- " -machine xlnx-zcu102.canbus0=canbus0"
46
- " -machine xlnx-zcu102.canbus1=canbus0"
47
+ " -object can-bus,id=canbus"
48
+ " -machine canbus0=canbus"
49
+ " -machine canbus1=canbus"
50
);
51
52
/* Configure the CAN0 and CAN1. */
53
@@ -XXX,XX +XXX,XX @@ static void test_can_loopback(void)
54
uint32_t status = 0;
55
56
QTestState *qts = qtest_init("-machine xlnx-zcu102"
57
- " -object can-bus,id=canbus0"
58
- " -machine xlnx-zcu102.canbus0=canbus0"
59
- " -machine xlnx-zcu102.canbus1=canbus0"
60
+ " -object can-bus,id=canbus"
61
+ " -machine canbus0=canbus"
62
+ " -machine canbus1=canbus"
63
);
64
65
/* Configure the CAN0 in loopback mode. */
66
@@ -XXX,XX +XXX,XX @@ static void test_can_filter(void)
67
uint8_t can_timestamp = 1;
68
69
QTestState *qts = qtest_init("-machine xlnx-zcu102"
70
- " -object can-bus,id=canbus0"
71
- " -machine xlnx-zcu102.canbus0=canbus0"
72
- " -machine xlnx-zcu102.canbus1=canbus0"
73
+ " -object can-bus,id=canbus"
74
+ " -machine canbus0=canbus"
75
+ " -machine canbus1=canbus"
76
);
77
78
/* Configure the CAN0 and CAN1. */
79
@@ -XXX,XX +XXX,XX @@ static void test_can_sleepmode(void)
80
uint8_t can_timestamp = 1;
81
82
QTestState *qts = qtest_init("-machine xlnx-zcu102"
83
- " -object can-bus,id=canbus0"
84
- " -machine xlnx-zcu102.canbus0=canbus0"
85
- " -machine xlnx-zcu102.canbus1=canbus0"
86
+ " -object can-bus,id=canbus"
87
+ " -machine canbus0=canbus"
88
+ " -machine canbus1=canbus"
89
);
90
91
/* Configure the CAN0. */
92
@@ -XXX,XX +XXX,XX @@ static void test_can_snoopmode(void)
93
uint8_t can_timestamp = 1;
94
95
QTestState *qts = qtest_init("-machine xlnx-zcu102"
96
- " -object can-bus,id=canbus0"
97
- " -machine xlnx-zcu102.canbus0=canbus0"
98
- " -machine xlnx-zcu102.canbus1=canbus0"
99
+ " -object can-bus,id=canbus"
100
+ " -machine canbus0=canbus"
101
+ " -machine canbus1=canbus"
102
);
103
104
/* Configure the CAN0. */
105
--
88
--
106
2.20.1
89
2.43.0
107
108
diff view generated by jsdifflib
1
From: Mihai Carabas <mihai.carabas@oracle.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add pvpanic PCI device support details in docs/specs/pvpanic.txt.
3
While at it add missing GUSB2RHBCTL register as found in i.MX 8M Plus reference
4
manual.
4
5
5
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
docs/specs/pvpanic.txt | 13 ++++++++++++-
11
include/hw/usb/hcd-dwc3.h | 2 +-
10
1 file changed, 12 insertions(+), 1 deletion(-)
12
hw/usb/hcd-dwc3.c | 5 +++++
13
2 files changed, 6 insertions(+), 1 deletion(-)
11
14
12
diff --git a/docs/specs/pvpanic.txt b/docs/specs/pvpanic.txt
15
diff --git a/include/hw/usb/hcd-dwc3.h b/include/hw/usb/hcd-dwc3.h
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/specs/pvpanic.txt
17
--- a/include/hw/usb/hcd-dwc3.h
15
+++ b/docs/specs/pvpanic.txt
18
+++ b/include/hw/usb/hcd-dwc3.h
16
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
17
PVPANIC DEVICE
20
#define USB_DWC3(obj) \
18
==============
21
OBJECT_CHECK(USBDWC3, (obj), TYPE_USB_DWC3)
19
22
20
-pvpanic device is a simulated ISA device, through which a guest panic
23
-#define USB_DWC3_R_MAX ((0x530 / 4) + 1)
21
+pvpanic device is a simulated device, through which a guest panic
24
+#define USB_DWC3_R_MAX (0x600 / 4)
22
event is sent to qemu, and a QMP event is generated. This allows
25
#define DWC3_SIZE 0x10000
23
management apps (e.g. libvirt) to be notified and respond to the event.
26
24
27
typedef struct USBDWC3 {
25
@@ -XXX,XX +XXX,XX @@ The management app has the option of waiting for GUEST_PANICKED events,
28
diff --git a/hw/usb/hcd-dwc3.c b/hw/usb/hcd-dwc3.c
26
and/or polling for guest-panicked RunState, to learn when the pvpanic
29
index XXXXXXX..XXXXXXX 100644
27
device has fired a panic event.
30
--- a/hw/usb/hcd-dwc3.c
28
31
+++ b/hw/usb/hcd-dwc3.c
29
+The pvpanic device can be implemented as an ISA device (using IOPORT) or as a
32
@@ -XXX,XX +XXX,XX @@ REG32(GFLADJ, 0x530)
30
+PCI device.
33
FIELD(GFLADJ, GFLADJ_REFCLK_FLADJ, 8, 14)
31
+
34
FIELD(GFLADJ, GFLADJ_30MHZ_SDBND_SEL, 7, 1)
32
ISA Interface
35
FIELD(GFLADJ, GFLADJ_30MHZ, 0, 6)
33
-------------
36
+REG32(GUSB2RHBCTL, 0x540)
34
37
+ FIELD(GUSB2RHBCTL, OVRD_L1TIMEOUT, 0, 4)
35
@@ -XXX,XX +XXX,XX @@ bit 1: a guest panic has happened and will be handled by the guest;
38
36
the host should record it or report it, but should not affect
39
#define DWC3_GLOBAL_OFFSET 0xC100
37
the execution of the guest.
40
static void reset_csr(USBDWC3 * s)
38
41
@@ -XXX,XX +XXX,XX @@ static const RegisterAccessInfo usb_dwc3_regs_info[] = {
39
+PCI Interface
42
.rsvd = 0x40,
40
+-------------
43
.ro = 0x400040,
41
+
44
.unimp = 0xffffffff,
42
+The PCI interface is similar to the ISA interface except that it uses an MMIO
45
+ },{ .name = "GUSB2RHBCTL", .addr = A_GUSB2RHBCTL,
43
+address space provided by its BAR0, 1 byte long. Any machine with a PCI bus
46
+ .rsvd = 0xfffffff0,
44
+can enable a pvpanic device by adding '-device pvpanic-pci' to the command
47
+ .unimp = 0xffffffff,
45
+line.
48
}
46
+
49
};
47
ACPI Interface
48
--------------
49
50
50
--
51
--
51
2.20.1
52
2.43.0
52
53
diff view generated by jsdifflib
1
From: Mihai Carabas <mihai.carabas@oracle.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add a test case for pvpanic-pci device. The scenario is the same as pvpanic
3
On the real device, the PCIe root bus is only connected to a PCIe bridge and
4
ISA device, but is using the PCI bus.
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.
5
7
6
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
8
Unfortunately, QEMU defaults to plugging devices into the PCIe root bus. To work
7
Acked-by: Thomas Huth <thuth@redhat.com>
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
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Message-id: 20250223114708.1780-3-shentey@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
17
---
12
tests/qtest/pvpanic-pci-test.c | 94 ++++++++++++++++++++++++++++++++++
18
include/hw/pci-host/designware.h | 7 +++++++
13
tests/qtest/meson.build | 1 +
19
hw/pci-host/designware.c | 18 +++++++++++++++++-
14
2 files changed, 95 insertions(+)
20
2 files changed, 24 insertions(+), 1 deletion(-)
15
create mode 100644 tests/qtest/pvpanic-pci-test.c
16
21
17
diff --git a/tests/qtest/pvpanic-pci-test.c b/tests/qtest/pvpanic-pci-test.c
22
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
18
new file mode 100644
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX
24
--- a/include/hw/pci-host/designware.h
20
--- /dev/null
25
+++ b/include/hw/pci-host/designware.h
21
+++ b/tests/qtest/pvpanic-pci-test.c
22
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
23
+/*
27
#include "hw/pci/pci_bridge.h"
24
+ * QTest testcase for PV Panic PCI device
28
#include "qom/object.h"
25
+ *
29
26
+ * Copyright (C) 2020 Oracle
30
+#define TYPE_DESIGNWARE_PCIE_ROOT_BUS "designware-pcie-root-BUS"
27
+ *
31
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERootBus, DESIGNWARE_PCIE_ROOT_BUS)
28
+ * Authors:
29
+ * Mihai Carabas <mihai.carabas@oracle.com>
30
+ *
31
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
32
+ * See the COPYING file in the top-level directory.
33
+ *
34
+ */
35
+
32
+
36
+#include "qemu/osdep.h"
33
#define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
37
+#include "libqos/libqtest.h"
34
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
38
+#include "qapi/qmp/qdict.h"
35
39
+#include "libqos/pci.h"
36
#define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
40
+#include "libqos/pci-pc.h"
37
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
41
+#include "hw/pci/pci_regs.h"
38
39
+struct DesignwarePCIERootBus {
40
+ PCIBus parent;
41
+};
42
+
42
+
43
+static void test_panic_nopause(void)
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)
44
+{
55
+{
45
+ uint8_t val;
56
+ BusClass *k = BUS_CLASS(klass);
46
+ QDict *response, *data;
47
+ QTestState *qts;
48
+ QPCIBus *pcibus;
49
+ QPCIDevice *dev;
50
+ QPCIBar bar;
51
+
57
+
52
+ qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=none");
58
+ /*
53
+ pcibus = qpci_new_pc(qts, NULL);
59
+ * Designware has only a single root complex. Enforce the limit on the
54
+ dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
60
+ * parent bus
55
+ qpci_device_enable(dev);
61
+ */
56
+ bar = qpci_iomap(dev, 0, NULL);
62
+ k->max_dev = 1;
57
+
58
+ qpci_memread(dev, bar, 0, &val, sizeof(val));
59
+ g_assert_cmpuint(val, ==, 3);
60
+
61
+ val = 1;
62
+ qpci_memwrite(dev, bar, 0, &val, sizeof(val));
63
+
64
+ response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
65
+ g_assert(qdict_haskey(response, "data"));
66
+ data = qdict_get_qdict(response, "data");
67
+ g_assert(qdict_haskey(data, "action"));
68
+ g_assert_cmpstr(qdict_get_str(data, "action"), ==, "run");
69
+ qobject_unref(response);
70
+
71
+ qtest_quit(qts);
72
+}
63
+}
73
+
64
+
74
+static void test_panic(void)
65
static DesignwarePCIEHost *
75
+{
66
designware_pcie_root_to_host(DesignwarePCIERoot *root)
76
+ uint8_t val;
67
{
77
+ QDict *response, *data;
68
@@ -XXX,XX +XXX,XX @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
78
+ QTestState *qts;
69
&s->pci.memory,
79
+ QPCIBus *pcibus;
70
&s->pci.io,
80
+ QPCIDevice *dev;
71
0, 4,
81
+ QPCIBar bar;
72
- TYPE_PCIE_BUS);
82
+
73
+ TYPE_DESIGNWARE_PCIE_ROOT_BUS);
83
+ qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=pause");
74
pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
84
+ pcibus = qpci_new_pc(qts, NULL);
75
85
+ dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
76
memory_region_init(&s->pci.address_space_root,
86
+ qpci_device_enable(dev);
77
@@ -XXX,XX +XXX,XX @@ static void designware_pcie_host_init(Object *obj)
87
+ bar = qpci_iomap(dev, 0, NULL);
78
88
+
79
static const TypeInfo designware_pcie_types[] = {
89
+ qpci_memread(dev, bar, 0, &val, sizeof(val));
80
{
90
+ g_assert_cmpuint(val, ==, 3);
81
+ .name = TYPE_DESIGNWARE_PCIE_ROOT_BUS,
91
+
82
+ .parent = TYPE_PCIE_BUS,
92
+ val = 1;
83
+ .instance_size = sizeof(DesignwarePCIERootBus),
93
+ qpci_memwrite(dev, bar, 0, &val, sizeof(val));
84
+ .class_init = designware_pcie_root_bus_class_init,
94
+
85
+ }, {
95
+ response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
86
.name = TYPE_DESIGNWARE_PCIE_HOST,
96
+ g_assert(qdict_haskey(response, "data"));
87
.parent = TYPE_PCI_HOST_BRIDGE,
97
+ data = qdict_get_qdict(response, "data");
88
.instance_size = sizeof(DesignwarePCIEHost),
98
+ g_assert(qdict_haskey(data, "action"));
99
+ g_assert_cmpstr(qdict_get_str(data, "action"), ==, "pause");
100
+ qobject_unref(response);
101
+
102
+ qtest_quit(qts);
103
+}
104
+
105
+int main(int argc, char **argv)
106
+{
107
+ int ret;
108
+
109
+ g_test_init(&argc, &argv, NULL);
110
+ qtest_add_func("/pvpanic-pci/panic", test_panic);
111
+ qtest_add_func("/pvpanic-pci/panic-nopause", test_panic_nopause);
112
+
113
+ ret = g_test_run();
114
+
115
+ return ret;
116
+}
117
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
118
index XXXXXXX..XXXXXXX 100644
119
--- a/tests/qtest/meson.build
120
+++ b/tests/qtest/meson.build
121
@@ -XXX,XX +XXX,XX @@ qtests_i386 = \
122
config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \
123
(config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + \
124
(config_all_devices.has_key('CONFIG_PVPANIC_ISA') ? ['pvpanic-test'] : []) + \
125
+ (config_all_devices.has_key('CONFIG_PVPANIC_PCI') ? ['pvpanic-pci-test'] : []) + \
126
(config_all_devices.has_key('CONFIG_HDA') ? ['intel-hda-test'] : []) + \
127
(config_all_devices.has_key('CONFIG_I82801B11') ? ['i82801b11-test'] : []) + \
128
(config_all_devices.has_key('CONFIG_IOH3420') ? ['ioh3420-test'] : []) + \
129
--
89
--
130
2.20.1
90
2.43.0
131
132
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Only define the register if it exists for the cpu.
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.
4
6
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Fixes: 6328d8ffa6cb9d "misc/pca955*: Move models under hw/gpio"
6
Message-id: 20210120031656.737646-1-richard.henderson@linaro.org
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20250223114708.1780-4-shentey@gmail.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
target/arm/helper.c | 21 +++++++++++++++------
13
hw/gpio/Kconfig | 8 ++++++++
11
1 file changed, 15 insertions(+), 6 deletions(-)
14
hw/misc/Kconfig | 8 --------
15
2 files changed, 8 insertions(+), 8 deletions(-)
12
16
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
19
--- a/hw/gpio/Kconfig
16
+++ b/target/arm/helper.c
20
+++ b/hw/gpio/Kconfig
17
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
21
@@ -XXX,XX +XXX,XX @@ config SIFIVE_GPIO
18
*/
22
config STM32L4X5_GPIO
19
int i;
23
bool
20
int wrps, brps, ctx_cmps;
24
21
- ARMCPRegInfo dbgdidr = {
25
+config PCA9552
22
- .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
26
+ bool
23
- .access = PL0_R, .accessfn = access_tda,
27
+ depends on I2C
24
- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
25
- };
26
+
28
+
27
+ /*
29
+config PCA9554
28
+ * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot
30
+ bool
29
+ * use AArch32. Given that bit 15 is RES1, if the value is 0 then
31
+ depends on I2C
30
+ * the register must not exist for this cpu.
32
+
31
+ */
33
config PCF8574
32
+ if (cpu->isar.dbgdidr != 0) {
34
bool
33
+ ARMCPRegInfo dbgdidr = {
35
depends on I2C
34
+ .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0,
36
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
35
+ .opc1 = 0, .opc2 = 0,
37
index XXXXXXX..XXXXXXX 100644
36
+ .access = PL0_R, .accessfn = access_tda,
38
--- a/hw/misc/Kconfig
37
+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
39
+++ b/hw/misc/Kconfig
38
+ };
40
@@ -XXX,XX +XXX,XX @@ config EDU
39
+ define_one_arm_cp_reg(cpu, &dbgdidr);
41
default y if TEST_DEVICES
40
+ }
42
depends on PCI && MSI_NONBROKEN
41
43
42
/* Note that all these register fields hold "number of Xs minus 1". */
44
-config PCA9552
43
brps = arm_num_brps(cpu);
45
- bool
44
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
46
- depends on I2C
45
47
-
46
assert(ctx_cmps <= brps);
48
-config PCA9554
47
49
- bool
48
- define_one_arm_cp_reg(cpu, &dbgdidr);
50
- depends on I2C
49
define_arm_cp_regs(cpu, debug_cp_reginfo);
51
-
50
52
config I2C_ECHO
51
if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
53
bool
54
default y if TEST_DEVICES
52
--
55
--
53
2.20.1
56
2.43.0
54
55
diff view generated by jsdifflib
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Implement gpio-pwr driver to allow reboot and poweroff machine.
3
As a first step, implement the bare minimum: CPUs, RAM, interrupt controller,
4
This is simple driver with just 2 gpios lines. Current use case
4
serial. All other devices of the A53 memory map are represented as
5
is to reboot and poweroff virt machine in secure mode. Secure
5
TYPE_UNIMPLEMENTED_DEVICE, i.e. the whole memory map is provided. This allows
6
pl066 gpio chip is needed for that.
6
for running Linux without it crashing due to invalid memory accesses.
7
7
8
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Reviewed-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20250223114708.1780-5-shentey@gmail.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
14
---
13
hw/gpio/gpio_pwr.c | 70 +++++++++++++++++++++++++++++++++++++++++++++
15
MAINTAINERS | 9 +
14
hw/gpio/Kconfig | 3 ++
16
docs/system/arm/imx8mp-evk.rst | 54 +++++
15
hw/gpio/meson.build | 1 +
17
docs/system/target-arm.rst | 1 +
16
3 files changed, 74 insertions(+)
18
include/hw/arm/fsl-imx8mp.h | 189 +++++++++++++++++
17
create mode 100644 hw/gpio/gpio_pwr.c
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
18
28
19
diff --git a/hw/gpio/gpio_pwr.c b/hw/gpio/gpio_pwr.c
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
20
new file mode 100644
50
new file mode 100644
21
index XXXXXXX..XXXXXXX
51
index XXXXXXX..XXXXXXX
22
--- /dev/null
52
--- /dev/null
23
+++ b/hw/gpio/gpio_pwr.c
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
24
@@ -XXX,XX +XXX,XX @@
126
@@ -XXX,XX +XXX,XX @@
25
+/*
127
+/*
26
+ * GPIO qemu power controller
128
+ * i.MX 8M Plus SoC Definitions
27
+ *
129
+ *
28
+ * Copyright (c) 2020 Linaro Limited
130
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
29
+ *
131
+ *
30
+ * Author: Maxim Uvarov <maxim.uvarov@linaro.org>
31
+ *
32
+ * Virtual gpio driver which can be used on top of pl061
33
+ * to reboot and shutdown qemu virtual machine. One of use
34
+ * case is gpio driver for secure world application (ARM
35
+ * Trusted Firmware.).
36
+ *
37
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
38
+ * See the COPYING file in the top-level directory.
39
+ * SPDX-License-Identifier: GPL-2.0-or-later
132
+ * SPDX-License-Identifier: GPL-2.0-or-later
40
+ */
133
+ */
41
+
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 @@
42
+/*
322
+/*
43
+ * QEMU interface:
323
+ * i.MX 8M Plus SoC Implementation
44
+ * two named input GPIO lines:
324
+ *
45
+ * 'reset' : when asserted, trigger system reset
325
+ * Based on hw/arm/fsl-imx6.c
46
+ * 'shutdown' : when asserted, trigger system shutdown
326
+ *
327
+ * Copyright (c) 2024, Bernhard Beschow <shentey@gmail.com>
328
+ *
329
+ * SPDX-License-Identifier: GPL-2.0-or-later
47
+ */
330
+ */
48
+
331
+
49
+#include "qemu/osdep.h"
332
+#include "qemu/osdep.h"
50
+#include "hw/sysbus.h"
333
+#include "exec/address-spaces.h"
51
+#include "sysemu/runstate.h"
334
+#include "hw/arm/bsa.h"
52
+
335
+#include "hw/arm/fsl-imx8mp.h"
53
+#define TYPE_GPIOPWR "gpio-pwr"
336
+#include "hw/intc/arm_gicv3.h"
54
+OBJECT_DECLARE_SIMPLE_TYPE(GPIO_PWR_State, GPIOPWR)
337
+#include "hw/misc/unimp.h"
55
+
338
+#include "hw/boards.h"
56
+struct GPIO_PWR_State {
339
+#include "system/system.h"
57
+ SysBusDevice parent_obj;
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" },
58
+};
505
+};
59
+
506
+
60
+static void gpio_pwr_reset(void *opaque, int n, int level)
507
+static void fsl_imx8mp_init(Object *obj)
61
+{
508
+{
62
+ if (level) {
509
+ MachineState *ms = MACHINE(qdev_get_machine());
63
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
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);
64
+ }
524
+ }
65
+}
525
+}
66
+
526
+
67
+static void gpio_pwr_shutdown(void *opaque, int n, int level)
527
+static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
68
+{
528
+{
69
+ if (level) {
529
+ MachineState *ms = MACHINE(qdev_get_machine());
70
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
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
+ }
71
+ }
666
+ }
72
+}
667
+}
73
+
668
+
74
+static void gpio_pwr_init(Object *obj)
669
+static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
75
+{
670
+{
76
+ DeviceState *dev = DEVICE(obj);
671
+ DeviceClass *dc = DEVICE_CLASS(oc);
77
+
672
+
78
+ qdev_init_gpio_in_named(dev, gpio_pwr_reset, "reset", 1);
673
+ dc->realize = fsl_imx8mp_realize;
79
+ qdev_init_gpio_in_named(dev, gpio_pwr_shutdown, "shutdown", 1);
674
+
675
+ dc->desc = "i.MX 8M Plus SoC";
80
+}
676
+}
81
+
677
+
82
+static const TypeInfo gpio_pwr_info = {
678
+static const TypeInfo fsl_imx8mp_types[] = {
83
+ .name = TYPE_GPIOPWR,
679
+ {
84
+ .parent = TYPE_SYS_BUS_DEVICE,
680
+ .name = TYPE_FSL_IMX8MP,
85
+ .instance_size = sizeof(GPIO_PWR_State),
681
+ .parent = TYPE_DEVICE,
86
+ .instance_init = gpio_pwr_init,
682
+ .instance_size = sizeof(FslImx8mpState),
683
+ .instance_init = fsl_imx8mp_init,
684
+ .class_init = fsl_imx8mp_class_init,
685
+ },
87
+};
686
+};
88
+
687
+
89
+static void gpio_pwr_register_types(void)
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)
90
+{
713
+{
91
+ type_register_static(&gpio_pwr_info);
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
+ }
92
+}
740
+}
93
+
741
+
94
+type_init(gpio_pwr_register_types)
742
+static void imx8mp_evk_machine_init(MachineClass *mc)
95
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
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
96
index XXXXXXX..XXXXXXX 100644
751
index XXXXXXX..XXXXXXX 100644
97
--- a/hw/gpio/Kconfig
752
--- a/hw/arm/Kconfig
98
+++ b/hw/gpio/Kconfig
753
+++ b/hw/arm/Kconfig
99
@@ -XXX,XX +XXX,XX @@ config PL061
754
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
100
config GPIO_KEY
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
101
bool
771
bool
102
772
103
+config GPIO_PWR
773
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
104
+ bool
105
+
106
config SIFIVE_GPIO
107
bool
108
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
109
index XXXXXXX..XXXXXXX 100644
774
index XXXXXXX..XXXXXXX 100644
110
--- a/hw/gpio/meson.build
775
--- a/hw/arm/meson.build
111
+++ b/hw/gpio/meson.build
776
+++ b/hw/arm/meson.build
112
@@ -XXX,XX +XXX,XX @@
777
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))
113
softmmu_ss.add(when: 'CONFIG_E500', if_true: files('mpc8xxx.c'))
778
arm_ss.add(when: 'CONFIG_MUSCA', if_true: files('musca.c'))
114
softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
779
arm_ss.add(when: 'CONFIG_ARMSSE', if_true: files('armsse.c'))
115
+softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
780
arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.c'))
116
softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
781
+arm_ss.add(when: 'CONFIG_FSL_IMX8MP', if_true: files('fsl-imx8mp.c'))
117
softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))
782
+arm_ss.add(when: 'CONFIG_FSL_IMX8MP_EVK', if_true: files('imx8mp-evk.c'))
118
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.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'))
119
--
786
--
120
2.20.1
787
2.43.0
121
122
diff view generated by jsdifflib
1
From: Mihai Carabas <mihai.carabas@oracle.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add PCI interface support for PVPANIC device. Create a new file pvpanic-pci.c
3
Fixes quite a few stack traces during the Linux boot process. Also provides the
4
where the PCI specific routines reside and update the build system with the new
4
clocks for devices added later, e.g. enet1.
5
files and config structure.
6
5
7
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
7
Message-id: 20250223114708.1780-6-shentey@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
docs/specs/pci-ids.txt | 1 +
11
MAINTAINERS | 2 +
14
include/hw/misc/pvpanic.h | 1 +
12
docs/system/arm/imx8mp-evk.rst | 1 +
15
include/hw/pci/pci.h | 1 +
13
include/hw/arm/fsl-imx8mp.h | 4 +
16
hw/misc/pvpanic-pci.c | 94 +++++++++++++++++++++++++++++++++++++++
14
include/hw/misc/imx8mp_analog.h | 81 +++++++++++++++
17
hw/misc/Kconfig | 6 +++
15
include/hw/misc/imx8mp_ccm.h | 30 ++++++
18
hw/misc/meson.build | 1 +
16
hw/arm/fsl-imx8mp.c | 20 ++++
19
6 files changed, 104 insertions(+)
17
hw/misc/imx8mp_analog.c | 160 +++++++++++++++++++++++++++++
20
create mode 100644 hw/misc/pvpanic-pci.c
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/docs/specs/pci-ids.txt b/docs/specs/pci-ids.txt
28
diff --git a/MAINTAINERS b/MAINTAINERS
23
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
24
--- a/docs/specs/pci-ids.txt
30
--- a/MAINTAINERS
25
+++ b/docs/specs/pci-ids.txt
31
+++ b/MAINTAINERS
26
@@ -XXX,XX +XXX,XX @@ PCI devices (other than virtio):
32
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
27
1b36:000d PCI xhci usb host adapter
33
S: Maintained
28
1b36:000f mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c
34
F: hw/arm/imx8mp-evk.c
29
1b36:0010 PCIe NVMe device (-device nvme)
35
F: hw/arm/fsl-imx8mp.c
30
+1b36:0011 PCI PVPanic device (-device pvpanic-pci)
36
+F: hw/misc/imx8mp_*.c
31
37
F: include/hw/arm/fsl-imx8mp.h
32
All these devices are documented in docs/specs.
38
+F: include/hw/misc/imx8mp_*.h
33
39
F: docs/system/arm/imx8mp-evk.rst
34
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
40
41
MPS2 / MPS3
42
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
35
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/misc/pvpanic.h
44
--- a/docs/system/arm/imx8mp-evk.rst
37
+++ b/include/hw/misc/pvpanic.h
45
+++ b/docs/system/arm/imx8mp-evk.rst
46
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
47
* Up to 4 Cortex-A53 cores
48
* Generic Interrupt Controller (GICv3)
49
* 4 UARTs
50
+ * Clock Tree
51
52
Boot options
53
------------
54
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/arm/fsl-imx8mp.h
57
+++ b/include/hw/arm/fsl-imx8mp.h
38
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@
59
#include "cpu.h"
60
#include "hw/char/imx_serial.h"
61
#include "hw/intc/arm_gicv3_common.h"
62
+#include "hw/misc/imx8mp_analog.h"
63
+#include "hw/misc/imx8mp_ccm.h"
39
#include "qom/object.h"
64
#include "qom/object.h"
40
65
#include "qemu/units.h"
41
#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
66
42
+#define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci"
67
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
43
68
44
#define PVPANIC_IOPORT_PROP "ioport"
69
ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
45
70
GICv3State gic;
46
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
71
+ IMX8MPCCMState ccm;
47
index XXXXXXX..XXXXXXX 100644
72
+ IMX8MPAnalogState analog;
48
--- a/include/hw/pci/pci.h
73
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
49
+++ b/include/hw/pci/pci.h
74
};
50
@@ -XXX,XX +XXX,XX @@ extern bool pci_available;
75
51
#define PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE 0x000e
76
diff --git a/include/hw/misc/imx8mp_analog.h b/include/hw/misc/imx8mp_analog.h
52
#define PCI_DEVICE_ID_REDHAT_MDPY 0x000f
53
#define PCI_DEVICE_ID_REDHAT_NVME 0x0010
54
+#define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
55
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
56
57
#define FMT_PCIBUS PRIx64
58
diff --git a/hw/misc/pvpanic-pci.c b/hw/misc/pvpanic-pci.c
59
new file mode 100644
77
new file mode 100644
60
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
61
--- /dev/null
79
--- /dev/null
62
+++ b/hw/misc/pvpanic-pci.c
80
+++ b/include/hw/misc/imx8mp_analog.h
63
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
64
+/*
82
+/*
65
+ * QEMU simulated PCI pvpanic device.
83
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
66
+ *
84
+ *
67
+ * Copyright (C) 2020 Oracle
85
+ * i.MX8MP ANALOG IP block emulation code
68
+ *
86
+ *
69
+ * Authors:
87
+ * SPDX-License-Identifier: GPL-2.0-or-later
70
+ * Mihai Carabas <mihai.carabas@oracle.com>
88
+ */
71
+ *
89
+
72
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
90
+#ifndef IMX8MP_ANALOG_H
73
+ * See the COPYING file in the top-level directory.
91
+#define IMX8MP_ANALOG_H
74
+ *
92
+
93
+#include "qom/object.h"
94
+#include "hw/sysbus.h"
95
+
96
+enum IMX8MPAnalogRegisters {
97
+ ANALOG_AUDIO_PLL1_GEN_CTRL = 0x000 / 4,
98
+ ANALOG_AUDIO_PLL1_FDIV_CTL0 = 0x004 / 4,
99
+ ANALOG_AUDIO_PLL1_FDIV_CTL1 = 0x008 / 4,
100
+ ANALOG_AUDIO_PLL1_SSCG_CTRL = 0x00c / 4,
101
+ ANALOG_AUDIO_PLL1_MNIT_CTRL = 0x010 / 4,
102
+ ANALOG_AUDIO_PLL2_GEN_CTRL = 0x014 / 4,
103
+ ANALOG_AUDIO_PLL2_FDIV_CTL0 = 0x018 / 4,
104
+ ANALOG_AUDIO_PLL2_FDIV_CTL1 = 0x01c / 4,
105
+ ANALOG_AUDIO_PLL2_SSCG_CTRL = 0x020 / 4,
106
+ ANALOG_AUDIO_PLL2_MNIT_CTRL = 0x024 / 4,
107
+ ANALOG_VIDEO_PLL1_GEN_CTRL = 0x028 / 4,
108
+ ANALOG_VIDEO_PLL1_FDIV_CTL0 = 0x02c / 4,
109
+ ANALOG_VIDEO_PLL1_FDIV_CTL1 = 0x030 / 4,
110
+ ANALOG_VIDEO_PLL1_SSCG_CTRL = 0x034 / 4,
111
+ ANALOG_VIDEO_PLL1_MNIT_CTRL = 0x038 / 4,
112
+ ANALOG_DRAM_PLL_GEN_CTRL = 0x050 / 4,
113
+ ANALOG_DRAM_PLL_FDIV_CTL0 = 0x054 / 4,
114
+ ANALOG_DRAM_PLL_FDIV_CTL1 = 0x058 / 4,
115
+ ANALOG_DRAM_PLL_SSCG_CTRL = 0x05c / 4,
116
+ ANALOG_DRAM_PLL_MNIT_CTRL = 0x060 / 4,
117
+ ANALOG_GPU_PLL_GEN_CTRL = 0x064 / 4,
118
+ ANALOG_GPU_PLL_FDIV_CTL0 = 0x068 / 4,
119
+ ANALOG_GPU_PLL_LOCKD_CTRL = 0x06c / 4,
120
+ ANALOG_GPU_PLL_MNIT_CTRL = 0x070 / 4,
121
+ ANALOG_VPU_PLL_GEN_CTRL = 0x074 / 4,
122
+ ANALOG_VPU_PLL_FDIV_CTL0 = 0x078 / 4,
123
+ ANALOG_VPU_PLL_LOCKD_CTRL = 0x07c / 4,
124
+ ANALOG_VPU_PLL_MNIT_CTRL = 0x080 / 4,
125
+ ANALOG_ARM_PLL_GEN_CTRL = 0x084 / 4,
126
+ ANALOG_ARM_PLL_FDIV_CTL0 = 0x088 / 4,
127
+ ANALOG_ARM_PLL_LOCKD_CTRL = 0x08c / 4,
128
+ ANALOG_ARM_PLL_MNIT_CTRL = 0x090 / 4,
129
+ ANALOG_SYS_PLL1_GEN_CTRL = 0x094 / 4,
130
+ ANALOG_SYS_PLL1_FDIV_CTL0 = 0x098 / 4,
131
+ ANALOG_SYS_PLL1_LOCKD_CTRL = 0x09c / 4,
132
+ ANALOG_SYS_PLL1_MNIT_CTRL = 0x100 / 4,
133
+ ANALOG_SYS_PLL2_GEN_CTRL = 0x104 / 4,
134
+ ANALOG_SYS_PLL2_FDIV_CTL0 = 0x108 / 4,
135
+ ANALOG_SYS_PLL2_LOCKD_CTRL = 0x10c / 4,
136
+ ANALOG_SYS_PLL2_MNIT_CTRL = 0x110 / 4,
137
+ ANALOG_SYS_PLL3_GEN_CTRL = 0x114 / 4,
138
+ ANALOG_SYS_PLL3_FDIV_CTL0 = 0x118 / 4,
139
+ ANALOG_SYS_PLL3_LOCKD_CTRL = 0x11c / 4,
140
+ ANALOG_SYS_PLL3_MNIT_CTRL = 0x120 / 4,
141
+ ANALOG_OSC_MISC_CFG = 0x124 / 4,
142
+ ANALOG_ANAMIX_PLL_MNIT_CTL = 0x128 / 4,
143
+
144
+ ANALOG_DIGPROG = 0x800 / 4,
145
+ ANALOG_MAX,
146
+};
147
+
148
+#define TYPE_IMX8MP_ANALOG "imx8mp.analog"
149
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPAnalogState, IMX8MP_ANALOG)
150
+
151
+struct IMX8MPAnalogState {
152
+ SysBusDevice parent_obj;
153
+
154
+ struct {
155
+ MemoryRegion container;
156
+ MemoryRegion analog;
157
+ } mmio;
158
+
159
+ uint32_t analog[ANALOG_MAX];
160
+};
161
+
162
+#endif /* IMX8MP_ANALOG_H */
163
diff --git a/include/hw/misc/imx8mp_ccm.h b/include/hw/misc/imx8mp_ccm.h
164
new file mode 100644
165
index XXXXXXX..XXXXXXX
166
--- /dev/null
167
+++ b/include/hw/misc/imx8mp_ccm.h
168
@@ -XXX,XX +XXX,XX @@
169
+/*
170
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
171
+ *
172
+ * i.MX 8M Plus CCM IP block emulation code
173
+ *
174
+ * SPDX-License-Identifier: GPL-2.0-or-later
175
+ */
176
+
177
+#ifndef IMX8MP_CCM_H
178
+#define IMX8MP_CCM_H
179
+
180
+#include "hw/misc/imx_ccm.h"
181
+#include "qom/object.h"
182
+
183
+enum IMX8MPCCMRegisters {
184
+ CCM_MAX = 0xc6fc / sizeof(uint32_t) + 1,
185
+};
186
+
187
+#define TYPE_IMX8MP_CCM "imx8mp.ccm"
188
+OBJECT_DECLARE_SIMPLE_TYPE(IMX8MPCCMState, IMX8MP_CCM)
189
+
190
+struct IMX8MPCCMState {
191
+ IMXCCMState parent_obj;
192
+
193
+ MemoryRegion iomem;
194
+
195
+ uint32_t ccm[CCM_MAX];
196
+};
197
+
198
+#endif /* IMX8MP_CCM_H */
199
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/arm/fsl-imx8mp.c
202
+++ b/hw/arm/fsl-imx8mp.c
203
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
204
205
object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
206
207
+ object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
208
+
209
+ object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
210
+
211
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
212
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
213
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
214
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
215
}
216
}
217
218
+ /* CCM */
219
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
220
+ return;
221
+ }
222
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
223
+ fsl_imx8mp_memmap[FSL_IMX8MP_CCM].addr);
224
+
225
+ /* Analog */
226
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
227
+ return;
228
+ }
229
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
230
+ fsl_imx8mp_memmap[FSL_IMX8MP_ANA_PLL].addr);
231
+
232
/* UARTs */
233
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
234
struct {
235
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
236
/* Unimplemented devices */
237
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
238
switch (i) {
239
+ case FSL_IMX8MP_ANA_PLL:
240
+ case FSL_IMX8MP_CCM:
241
case FSL_IMX8MP_GIC_DIST:
242
case FSL_IMX8MP_GIC_REDIST:
243
case FSL_IMX8MP_RAM:
244
diff --git a/hw/misc/imx8mp_analog.c b/hw/misc/imx8mp_analog.c
245
new file mode 100644
246
index XXXXXXX..XXXXXXX
247
--- /dev/null
248
+++ b/hw/misc/imx8mp_analog.c
249
@@ -XXX,XX +XXX,XX @@
250
+/*
251
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
252
+ *
253
+ * i.MX 8M Plus ANALOG IP block emulation code
254
+ *
255
+ * Based on hw/misc/imx7_ccm.c
256
+ *
257
+ * SPDX-License-Identifier: GPL-2.0-or-later
75
+ */
258
+ */
76
+
259
+
77
+#include "qemu/osdep.h"
260
+#include "qemu/osdep.h"
78
+#include "qemu/log.h"
261
+#include "qemu/log.h"
79
+#include "qemu/module.h"
262
+
80
+#include "sysemu/runstate.h"
263
+#include "hw/misc/imx8mp_analog.h"
81
+
82
+#include "hw/nvram/fw_cfg.h"
83
+#include "hw/qdev-properties.h"
84
+#include "migration/vmstate.h"
264
+#include "migration/vmstate.h"
85
+#include "hw/misc/pvpanic.h"
265
+
86
+#include "qom/object.h"
266
+#define ANALOG_PLL_LOCK BIT(31)
87
+#include "hw/pci/pci.h"
267
+
88
+
268
+static void imx8mp_analog_reset(DeviceState *dev)
89
+OBJECT_DECLARE_SIMPLE_TYPE(PVPanicPCIState, PVPANIC_PCI_DEVICE)
269
+{
90
+
270
+ IMX8MPAnalogState *s = IMX8MP_ANALOG(dev);
91
+/*
271
+
92
+ * PVPanicPCIState for PCI device
272
+ memset(s->analog, 0, sizeof(s->analog));
93
+ */
273
+
94
+typedef struct PVPanicPCIState {
274
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] = 0x00002010;
95
+ PCIDevice dev;
275
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL0] = 0x00145032;
96
+ PVPanicState pvpanic;
276
+ s->analog[ANALOG_AUDIO_PLL1_FDIV_CTL1] = 0x00000000;
97
+} PVPanicPCIState;
277
+ s->analog[ANALOG_AUDIO_PLL1_SSCG_CTRL] = 0x00000000;
98
+
278
+ s->analog[ANALOG_AUDIO_PLL1_MNIT_CTRL] = 0x00100103;
99
+static const VMStateDescription vmstate_pvpanic_pci = {
279
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] = 0x00002010;
100
+ .name = "pvpanic-pci",
280
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL0] = 0x00145032;
281
+ s->analog[ANALOG_AUDIO_PLL2_FDIV_CTL1] = 0x00000000;
282
+ s->analog[ANALOG_AUDIO_PLL2_SSCG_CTRL] = 0x00000000;
283
+ s->analog[ANALOG_AUDIO_PLL2_MNIT_CTRL] = 0x00100103;
284
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] = 0x00002010;
285
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL0] = 0x00145032;
286
+ s->analog[ANALOG_VIDEO_PLL1_FDIV_CTL1] = 0x00000000;
287
+ s->analog[ANALOG_VIDEO_PLL1_SSCG_CTRL] = 0x00000000;
288
+ s->analog[ANALOG_VIDEO_PLL1_MNIT_CTRL] = 0x00100103;
289
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] = 0x00002010;
290
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL0] = 0x0012c032;
291
+ s->analog[ANALOG_DRAM_PLL_FDIV_CTL1] = 0x00000000;
292
+ s->analog[ANALOG_DRAM_PLL_SSCG_CTRL] = 0x00000000;
293
+ s->analog[ANALOG_DRAM_PLL_MNIT_CTRL] = 0x00100103;
294
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] = 0x00000810;
295
+ s->analog[ANALOG_GPU_PLL_FDIV_CTL0] = 0x000c8031;
296
+ s->analog[ANALOG_GPU_PLL_LOCKD_CTRL] = 0x0010003f;
297
+ s->analog[ANALOG_GPU_PLL_MNIT_CTRL] = 0x00280081;
298
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] = 0x00000810;
299
+ s->analog[ANALOG_VPU_PLL_FDIV_CTL0] = 0x0012c032;
300
+ s->analog[ANALOG_VPU_PLL_LOCKD_CTRL] = 0x0010003f;
301
+ s->analog[ANALOG_VPU_PLL_MNIT_CTRL] = 0x00280081;
302
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] = 0x00000810;
303
+ s->analog[ANALOG_ARM_PLL_FDIV_CTL0] = 0x000fa031;
304
+ s->analog[ANALOG_ARM_PLL_LOCKD_CTRL] = 0x0010003f;
305
+ s->analog[ANALOG_ARM_PLL_MNIT_CTRL] = 0x00280081;
306
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] = 0x0aaaa810;
307
+ s->analog[ANALOG_SYS_PLL1_FDIV_CTL0] = 0x00190032;
308
+ s->analog[ANALOG_SYS_PLL1_LOCKD_CTRL] = 0x0010003f;
309
+ s->analog[ANALOG_SYS_PLL1_MNIT_CTRL] = 0x00280081;
310
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] = 0x0aaaa810;
311
+ s->analog[ANALOG_SYS_PLL2_FDIV_CTL0] = 0x000fa031;
312
+ s->analog[ANALOG_SYS_PLL2_LOCKD_CTRL] = 0x0010003f;
313
+ s->analog[ANALOG_SYS_PLL2_MNIT_CTRL] = 0x00280081;
314
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] = 0x00000810;
315
+ s->analog[ANALOG_SYS_PLL3_FDIV_CTL0] = 0x000fa031;
316
+ s->analog[ANALOG_SYS_PLL3_LOCKD_CTRL] = 0x0010003f;
317
+ s->analog[ANALOG_SYS_PLL3_MNIT_CTRL] = 0x00280081;
318
+ s->analog[ANALOG_OSC_MISC_CFG] = 0x00000000;
319
+ s->analog[ANALOG_ANAMIX_PLL_MNIT_CTL] = 0x00000000;
320
+ s->analog[ANALOG_DIGPROG] = 0x00824010;
321
+
322
+ /* all PLLs need to be locked */
323
+ s->analog[ANALOG_AUDIO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
324
+ s->analog[ANALOG_AUDIO_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
325
+ s->analog[ANALOG_VIDEO_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
326
+ s->analog[ANALOG_DRAM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
327
+ s->analog[ANALOG_GPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
328
+ s->analog[ANALOG_VPU_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
329
+ s->analog[ANALOG_ARM_PLL_GEN_CTRL] |= ANALOG_PLL_LOCK;
330
+ s->analog[ANALOG_SYS_PLL1_GEN_CTRL] |= ANALOG_PLL_LOCK;
331
+ s->analog[ANALOG_SYS_PLL2_GEN_CTRL] |= ANALOG_PLL_LOCK;
332
+ s->analog[ANALOG_SYS_PLL3_GEN_CTRL] |= ANALOG_PLL_LOCK;
333
+}
334
+
335
+static uint64_t imx8mp_analog_read(void *opaque, hwaddr offset, unsigned size)
336
+{
337
+ IMX8MPAnalogState *s = opaque;
338
+
339
+ return s->analog[offset >> 2];
340
+}
341
+
342
+static void imx8mp_analog_write(void *opaque, hwaddr offset,
343
+ uint64_t value, unsigned size)
344
+{
345
+ IMX8MPAnalogState *s = opaque;
346
+
347
+ if (offset >> 2 == ANALOG_DIGPROG) {
348
+ qemu_log_mask(LOG_GUEST_ERROR,
349
+ "Guest write to read-only ANALOG_DIGPROG register\n");
350
+ } else {
351
+ s->analog[offset >> 2] = value;
352
+ }
353
+}
354
+
355
+static const struct MemoryRegionOps imx8mp_analog_ops = {
356
+ .read = imx8mp_analog_read,
357
+ .write = imx8mp_analog_write,
358
+ .endianness = DEVICE_NATIVE_ENDIAN,
359
+ .impl = {
360
+ .min_access_size = 4,
361
+ .max_access_size = 4,
362
+ .unaligned = false,
363
+ },
364
+};
365
+
366
+static void imx8mp_analog_init(Object *obj)
367
+{
368
+ IMX8MPAnalogState *s = IMX8MP_ANALOG(obj);
369
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
370
+
371
+ memory_region_init(&s->mmio.container, obj, TYPE_IMX8MP_ANALOG, 0x10000);
372
+
373
+ memory_region_init_io(&s->mmio.analog, obj, &imx8mp_analog_ops, s,
374
+ TYPE_IMX8MP_ANALOG, sizeof(s->analog));
375
+ memory_region_add_subregion(&s->mmio.container, 0, &s->mmio.analog);
376
+
377
+ sysbus_init_mmio(sd, &s->mmio.container);
378
+}
379
+
380
+static const VMStateDescription imx8mp_analog_vmstate = {
381
+ .name = TYPE_IMX8MP_ANALOG,
101
+ .version_id = 1,
382
+ .version_id = 1,
102
+ .minimum_version_id = 1,
383
+ .minimum_version_id = 1,
103
+ .fields = (VMStateField[]) {
384
+ .fields = (const VMStateField[]) {
104
+ VMSTATE_PCI_DEVICE(dev, PVPanicPCIState),
385
+ VMSTATE_UINT32_ARRAY(analog, IMX8MPAnalogState, ANALOG_MAX),
105
+ VMSTATE_END_OF_LIST()
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,
106
+ }
406
+ }
107
+};
407
+};
108
+
408
+
109
+static void pvpanic_pci_realizefn(PCIDevice *dev, Error **errp)
409
+DEFINE_TYPES(imx8mp_analog_types);
110
+{
410
diff --git a/hw/misc/imx8mp_ccm.c b/hw/misc/imx8mp_ccm.c
111
+ PVPanicPCIState *s = PVPANIC_PCI_DEVICE(dev);
411
new file mode 100644
112
+ PVPanicState *ps = &s->pvpanic;
412
index XXXXXXX..XXXXXXX
113
+
413
--- /dev/null
114
+ pvpanic_setup_io(&s->pvpanic, DEVICE(s), 2);
414
+++ b/hw/misc/imx8mp_ccm.c
115
+
415
@@ -XXX,XX +XXX,XX @@
116
+ pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &ps->mr);
416
+/*
117
+}
417
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
118
+
418
+ *
119
+static Property pvpanic_pci_properties[] = {
419
+ * i.MX 8M Plus CCM IP block emulation code
120
+ DEFINE_PROP_UINT8("events", PVPanicPCIState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
420
+ *
121
+ DEFINE_PROP_END_OF_LIST(),
421
+ * Based on hw/misc/imx7_ccm.c
122
+};
422
+ *
123
+
423
+ * SPDX-License-Identifier: GPL-2.0-or-later
124
+static void pvpanic_pci_class_init(ObjectClass *klass, void *data)
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)
125
+{
569
+{
126
+ DeviceClass *dc = DEVICE_CLASS(klass);
570
+ DeviceClass *dc = DEVICE_CLASS(klass);
127
+ PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
571
+ IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
128
+
572
+
129
+ device_class_set_props(dc, pvpanic_pci_properties);
573
+ device_class_set_legacy_reset(dc, imx8mp_ccm_reset);
130
+
574
+ dc->vmsd = &imx8mp_ccm_vmstate;
131
+ pc->realize = pvpanic_pci_realizefn;
575
+ dc->desc = "i.MX 8M Plus Clock Control Module";
132
+ pc->vendor_id = PCI_VENDOR_ID_REDHAT;
576
+
133
+ pc->device_id = PCI_DEVICE_ID_REDHAT_PVPANIC;
577
+ ccm->get_clock_frequency = imx8mp_ccm_get_clock_frequency;
134
+ pc->revision = 1;
578
+}
135
+ pc->class_id = PCI_CLASS_SYSTEM_OTHER;
579
+
136
+ dc->vmsd = &vmstate_pvpanic_pci;
580
+static const TypeInfo imx8mp_ccm_types[] = {
137
+
581
+ {
138
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
582
+ .name = TYPE_IMX8MP_CCM,
139
+}
583
+ .parent = TYPE_IMX_CCM,
140
+
584
+ .instance_size = sizeof(IMX8MPCCMState),
141
+static TypeInfo pvpanic_pci_info = {
585
+ .instance_init = imx8mp_ccm_init,
142
+ .name = TYPE_PVPANIC_PCI_DEVICE,
586
+ .class_init = imx8mp_ccm_class_init,
143
+ .parent = TYPE_PCI_DEVICE,
587
+ },
144
+ .instance_size = sizeof(PVPanicPCIState),
588
+};
145
+ .class_init = pvpanic_pci_class_init,
589
+
146
+ .interfaces = (InterfaceInfo[]) {
590
+DEFINE_TYPES(imx8mp_ccm_types);
147
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
591
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
148
+ { }
592
index XXXXXXX..XXXXXXX 100644
149
+ }
593
--- a/hw/arm/Kconfig
150
+};
594
+++ b/hw/arm/Kconfig
151
+
595
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
152
+static void pvpanic_register_types(void)
596
config FSL_IMX8MP
153
+{
597
bool
154
+ type_register_static(&pvpanic_pci_info);
598
select ARM_GIC
155
+}
599
+ select FSL_IMX8MP_ANALOG
156
+
600
+ select FSL_IMX8MP_CCM
157
+type_init(pvpanic_register_types);
601
select IMX
602
select UNIMP
603
158
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
604
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
159
index XXXXXXX..XXXXXXX 100644
605
index XXXXXXX..XXXXXXX 100644
160
--- a/hw/misc/Kconfig
606
--- a/hw/misc/Kconfig
161
+++ b/hw/misc/Kconfig
607
+++ b/hw/misc/Kconfig
162
@@ -XXX,XX +XXX,XX @@ config IOTKIT_SYSINFO
608
@@ -XXX,XX +XXX,XX @@ config IMX
163
config PVPANIC_COMMON
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
164
bool
619
bool
165
620
166
+config PVPANIC_PCI
167
+ bool
168
+ default y if PCI_DEVICES
169
+ depends on PCI
170
+ select PVPANIC_COMMON
171
+
172
config PVPANIC_ISA
173
bool
174
depends on ISA_BUS
175
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
621
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
176
index XXXXXXX..XXXXXXX 100644
622
index XXXXXXX..XXXXXXX 100644
177
--- a/hw/misc/meson.build
623
--- a/hw/misc/meson.build
178
+++ b/hw/misc/meson.build
624
+++ b/hw/misc/meson.build
179
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
625
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_AXP2XX_PMU', if_true: files('axp2xx.c'))
180
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
626
system_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
181
627
system_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
182
softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
628
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pmu.c', 'exynos4210_clk.c', 'exynos4210_rng.c'))
183
+softmmu_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c'))
629
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_ANALOG', if_true: files('imx8mp_analog.c'))
184
softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
630
+system_ss.add(when: 'CONFIG_FSL_IMX8MP_CCM', if_true: files('imx8mp_ccm.c'))
185
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_scu.c', 'aspeed_sdmc.c', 'aspeed_xdma.c'))
631
system_ss.add(when: 'CONFIG_IMX', if_true: files(
186
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
632
'imx25_ccm.c',
633
'imx31_ccm.c',
187
--
634
--
188
2.20.1
635
2.43.0
189
190
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Fix potential overflow problem when calculating pwm_duty.
3
SNVS contains an RTC which allows Linux to deal correctly with time. This is
4
1. Ensure p->cmr and p->cnr to be from [0,65535], according to the
4
particularly useful when handling persistent storage which will be done in the
5
hardware specification.
5
next patch.
6
2. Changed duty to uint32_t. However, since MAX_DUTY * (p->cmr+1)
7
can excceed UINT32_MAX, we convert them to uint64_t in computation
8
and converted them back to uint32_t.
9
(duty is guaranteed to be <= MAX_DUTY so it won't overflow.)
10
6
11
Fixes: CID 1442342
12
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Doug Evans <dje@google.com>
14
Signed-off-by: Hao Wu <wuhaotsh@google.com>
15
Message-id: 20210127011142.2122790-1-wuhaotsh@google.com
16
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-7-shentey@gmail.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
11
---
19
hw/misc/npcm7xx_pwm.c | 23 +++++++++++++++++++----
12
docs/system/arm/imx8mp-evk.rst | 1 +
20
tests/qtest/npcm7xx_pwm-test.c | 4 ++--
13
include/hw/arm/fsl-imx8mp.h | 2 ++
21
2 files changed, 21 insertions(+), 6 deletions(-)
14
hw/arm/fsl-imx8mp.c | 10 ++++++++++
15
3 files changed, 13 insertions(+)
22
16
23
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
17
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/misc/npcm7xx_pwm.c
19
--- a/docs/system/arm/imx8mp-evk.rst
26
+++ b/hw/misc/npcm7xx_pwm.c
20
+++ b/docs/system/arm/imx8mp-evk.rst
27
@@ -XXX,XX +XXX,XX @@ REG32(NPCM7XX_PWM_PWDR3, 0x50);
21
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
28
#define NPCM7XX_CH_INV BIT(2)
22
* Up to 4 Cortex-A53 cores
29
#define NPCM7XX_CH_MOD BIT(3)
23
* Generic Interrupt Controller (GICv3)
30
24
* 4 UARTs
31
+#define NPCM7XX_MAX_CMR 65535
25
+ * Secure Non-Volatile Storage (SNVS) including an RTC
32
+#define NPCM7XX_MAX_CNR 65535
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);
33
+
58
+
34
/* Offset of each PWM channel's prescaler in the PPR register. */
59
for (i = 0; i < FSL_IMX8MP_NUM_UARTS; i++) {
35
static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
60
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
36
/* Offset of each PWM channel's clock selector in the CSR register. */
61
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
37
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
62
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
38
63
qdev_get_gpio_in(gicdev, serial_table[i].irq));
39
static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
40
{
41
- uint64_t duty;
42
+ uint32_t duty;
43
44
if (p->running) {
45
if (p->cnr == 0) {
46
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
47
} else if (p->cmr >= p->cnr) {
48
duty = NPCM7XX_PWM_MAX_DUTY;
49
} else {
50
- duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
51
+ duty = (uint64_t)NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
52
}
53
} else {
54
duty = 0;
55
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
56
case A_NPCM7XX_PWM_CNR2:
57
case A_NPCM7XX_PWM_CNR3:
58
p = &s->pwm[npcm7xx_cnr_index(offset)];
59
- p->cnr = value;
60
+ if (value > NPCM7XX_MAX_CNR) {
61
+ qemu_log_mask(LOG_GUEST_ERROR,
62
+ "%s: invalid cnr value: %u", __func__, value);
63
+ p->cnr = NPCM7XX_MAX_CNR;
64
+ } else {
65
+ p->cnr = value;
66
+ }
67
npcm7xx_pwm_update_output(p);
68
break;
69
70
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
71
case A_NPCM7XX_PWM_CMR2:
72
case A_NPCM7XX_PWM_CMR3:
73
p = &s->pwm[npcm7xx_cmr_index(offset)];
74
- p->cmr = value;
75
+ if (value > NPCM7XX_MAX_CMR) {
76
+ qemu_log_mask(LOG_GUEST_ERROR,
77
+ "%s: invalid cmr value: %u", __func__, value);
78
+ p->cmr = NPCM7XX_MAX_CMR;
79
+ } else {
80
+ p->cmr = value;
81
+ }
82
npcm7xx_pwm_update_output(p);
83
break;
84
85
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/tests/qtest/npcm7xx_pwm-test.c
88
+++ b/tests/qtest/npcm7xx_pwm-test.c
89
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
90
91
static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
92
{
93
- uint64_t duty;
94
+ uint32_t duty;
95
96
if (cnr == 0) {
97
/* PWM is stopped. */
98
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
99
} else if (cmr >= cnr) {
100
duty = MAX_DUTY;
101
} else {
102
- duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
103
+ duty = (uint64_t)MAX_DUTY * (cmr + 1) / (cnr + 1);
104
}
64
}
105
65
106
if (inverted) {
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;
107
--
84
--
108
2.20.1
85
2.43.0
109
110
diff view generated by jsdifflib
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add secure pl061 for reset/power down machine from
3
The USDHC emulation allows for running real-world images such as those generated
4
the secure world (Arm Trusted Firmware). Connect it
4
by Buildroot. Convert the board documentation accordingly instead of running a
5
with gpio-pwr driver.
5
Linux kernel with ephemeral storage.
6
6
7
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
[PMM: Added mention of the new device to the documentation]
9
Message-id: 20250223114708.1780-8-shentey@gmail.com
10
[PMM: drop 'static const' from usdhc_table[] for GCC 7.5]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
docs/system/arm/virt.rst | 2 ++
13
docs/system/arm/imx8mp-evk.rst | 18 ++++++++++++------
13
include/hw/arm/virt.h | 2 ++
14
include/hw/arm/fsl-imx8mp.h | 7 +++++++
14
hw/arm/virt.c | 56 +++++++++++++++++++++++++++++++++++++++-
15
hw/arm/fsl-imx8mp.c | 28 ++++++++++++++++++++++++++++
15
hw/arm/Kconfig | 1 +
16
hw/arm/imx8mp-evk.c | 18 ++++++++++++++++++
16
4 files changed, 60 insertions(+), 1 deletion(-)
17
hw/arm/Kconfig | 1 +
18
5 files changed, 66 insertions(+), 6 deletions(-)
17
19
18
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
20
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
19
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/virt.rst
22
--- a/docs/system/arm/imx8mp-evk.rst
21
+++ b/docs/system/arm/virt.rst
23
+++ b/docs/system/arm/imx8mp-evk.rst
22
@@ -XXX,XX +XXX,XX @@ The virt board supports:
24
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
23
- Secure-World-only devices if the CPU has TrustZone:
25
* Up to 4 Cortex-A53 cores
24
26
* Generic Interrupt Controller (GICv3)
25
- A second PL011 UART
27
* 4 UARTs
26
+ - A second PL061 GPIO controller, with GPIO lines for triggering
28
+ * 3 USDHC Storage Controllers
27
+ a system reset or system poweroff
29
* Secure Non-Volatile Storage (SNVS) including an RTC
28
- A secure flash memory
30
* Clock Tree
29
- 16MB of secure RAM
31
30
32
@@ -XXX,XX +XXX,XX @@ Direct Linux Kernel Boot
31
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
33
32
index XXXXXXX..XXXXXXX 100644
34
Probably the easiest way to get started with a whole Linux system on the machine
33
--- a/include/hw/arm/virt.h
35
is to generate an image with Buildroot. Version 2024.11.1 is tested at the time
34
+++ b/include/hw/arm/virt.h
36
-of writing and involves two steps. First run the following commands in the
35
@@ -XXX,XX +XXX,XX @@ enum {
37
+of writing and involves three steps. First run the following commands in the
36
VIRT_GPIO,
38
toplevel directory of the Buildroot source tree:
37
VIRT_SECURE_UART,
39
38
VIRT_SECURE_MEM,
40
.. code-block:: bash
39
+ VIRT_SECURE_GPIO,
41
40
VIRT_PCDIMM_ACPI,
42
- $ echo "BR2_TARGET_ROOTFS_CPIO=y" >> configs/freescale_imx8mpevk_defconfig
41
VIRT_ACPI_GED,
43
$ make freescale_imx8mpevk_defconfig
42
VIRT_NVDIMM_ACPI,
44
$ make
43
@@ -XXX,XX +XXX,XX @@ struct VirtMachineClass {
45
44
bool kvm_no_adjvtime;
46
Once finished successfully there is an ``output/image`` subfolder. Navigate into
45
bool no_kvm_steal_time;
47
-it and patch the device tree with the following commands which will remove the
46
bool acpi_expose_flash;
48
-``cpu-idle-states`` properties from CPU nodes:
47
+ bool no_secure_gpio;
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,
48
};
85
};
49
86
50
struct VirtMachineState {
87
struct FslImx8mpState {
51
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
88
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
52
index XXXXXXX..XXXXXXX 100644
89
IMX8MPAnalogState analog;
53
--- a/hw/arm/virt.c
90
IMX7SNVSState snvs;
54
+++ b/hw/arm/virt.c
91
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
55
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry base_memmap[] = {
92
+ SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
56
[VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN },
93
};
57
[VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN},
94
58
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
95
enum FslImx8mpMemoryRegions {
59
+ [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
96
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpMemoryRegions {
60
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
97
};
61
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
98
62
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
99
enum FslImx8mpIrqs {
63
@@ -XXX,XX +XXX,XX @@ static void create_gpio_keys(const VirtMachineState *vms,
100
+ FSL_IMX8MP_USDHC1_IRQ = 22,
64
"gpios", phandle, 3, 0);
101
+ FSL_IMX8MP_USDHC2_IRQ = 23,
65
}
102
+ FSL_IMX8MP_USDHC3_IRQ = 24,
66
103
+
67
+#define SECURE_GPIO_POWEROFF 0
104
FSL_IMX8MP_UART1_IRQ = 26,
68
+#define SECURE_GPIO_RESET 1
105
FSL_IMX8MP_UART2_IRQ = 27,
69
+
106
FSL_IMX8MP_UART3_IRQ = 28,
70
+static void create_secure_gpio_pwr(const VirtMachineState *vms,
107
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
71
+ DeviceState *pl061_dev,
108
index XXXXXXX..XXXXXXX 100644
72
+ uint32_t phandle)
109
--- a/hw/arm/fsl-imx8mp.c
73
+{
110
+++ b/hw/arm/fsl-imx8mp.c
74
+ DeviceState *gpio_pwr_dev;
111
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
75
+
112
g_autofree char *name = g_strdup_printf("uart%d", i + 1);
76
+ /* gpio-pwr */
113
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
77
+ gpio_pwr_dev = sysbus_create_simple("gpio-pwr", -1, NULL);
114
}
78
+
115
+
79
+ /* connect secure pl061 to gpio-pwr */
116
+ for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
80
+ qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_RESET,
117
+ g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
81
+ qdev_get_gpio_in_named(gpio_pwr_dev, "reset", 0));
118
+ object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
82
+ qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_POWEROFF,
83
+ qdev_get_gpio_in_named(gpio_pwr_dev, "shutdown", 0));
84
+
85
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-poweroff");
86
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "compatible",
87
+ "gpio-poweroff");
88
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-poweroff",
89
+ "gpios", phandle, SECURE_GPIO_POWEROFF, 0);
90
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "status", "disabled");
91
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "secure-status",
92
+ "okay");
93
+
94
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-restart");
95
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "compatible",
96
+ "gpio-restart");
97
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-restart",
98
+ "gpios", phandle, SECURE_GPIO_RESET, 0);
99
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "status", "disabled");
100
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "secure-status",
101
+ "okay");
102
+}
103
+
104
static void create_gpio_devices(const VirtMachineState *vms, int gpio,
105
MemoryRegion *mem)
106
{
107
@@ -XXX,XX +XXX,XX @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
108
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
109
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
110
111
+ if (gpio != VIRT_GPIO) {
112
+ /* Mark as not usable by the normal world */
113
+ qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
114
+ qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
115
+ }
116
g_free(nodename);
117
118
/* Child gpio devices */
119
- create_gpio_keys(vms, pl061_dev, phandle);
120
+ if (gpio == VIRT_GPIO) {
121
+ create_gpio_keys(vms, pl061_dev, phandle);
122
+ } else {
123
+ create_secure_gpio_pwr(vms, pl061_dev, phandle);
124
+ }
119
+ }
125
}
120
}
126
121
127
static void create_virtio_devices(const VirtMachineState *vms)
122
static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
128
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
123
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
129
create_gpio_devices(vms, VIRT_GPIO, sysmem);
124
qdev_get_gpio_in(gicdev, serial_table[i].irq));
130
}
125
}
131
126
132
+ if (vms->secure && !vmc->no_secure_gpio) {
127
+ /* USDHCs */
133
+ create_gpio_devices(vms, VIRT_SECURE_GPIO, secure_sysmem);
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));
134
+ }
147
+ }
135
+
148
+
136
/* connect powerdown request */
149
/* SNVS */
137
vms->powerdown_notifier.notify = virt_powerdown_req;
150
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
138
qemu_register_powerdown_notifier(&vms->powerdown_notifier);
151
return;
139
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 0)
152
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
140
153
case FSL_IMX8MP_RAM:
141
static void virt_machine_5_2_options(MachineClass *mc)
154
case FSL_IMX8MP_SNVS_HP:
142
{
155
case FSL_IMX8MP_UART1 ... FSL_IMX8MP_UART4:
143
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
156
+ case FSL_IMX8MP_USDHC1 ... FSL_IMX8MP_USDHC3:
144
+
157
/* device implemented and treated above */
145
virt_machine_6_0_options(mc);
158
break;
146
compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
159
147
+ vmc->no_secure_gpio = true;
160
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
148
}
161
index XXXXXXX..XXXXXXX 100644
149
DEFINE_VIRT_MACHINE(5, 2)
162
--- a/hw/arm/imx8mp-evk.c
150
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
}
151
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
196
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
152
index XXXXXXX..XXXXXXX 100644
197
index XXXXXXX..XXXXXXX 100644
153
--- a/hw/arm/Kconfig
198
--- a/hw/arm/Kconfig
154
+++ b/hw/arm/Kconfig
199
+++ b/hw/arm/Kconfig
155
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
200
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
156
select PL011 # UART
201
select FSL_IMX8MP_ANALOG
157
select PL031 # RTC
202
select FSL_IMX8MP_CCM
158
select PL061 # GPIO
203
select IMX
159
+ select GPIO_PWR
204
+ select SDHCI
160
select PLATFORM_BUS
205
select UNIMP
161
select SMBIOS
206
162
select VIRTIO_MMIO
207
config FSL_IMX8MP_EVK
163
--
208
--
164
2.20.1
209
2.43.0
165
166
diff view generated by jsdifflib
1
From: Mihai Carabas <mihai.carabas@oracle.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
To ease the PCI device addition in next patches, split the code as follows:
3
Linux checks for the PLLs in the PHY to be locked, so implement a model
4
- generic code (read/write/setup) is being kept in pvpanic.c
4
emulating that.
5
- ISA dependent code moved to pvpanic-isa.c
6
5
7
Also, rename:
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
- ISA_PVPANIC_DEVICE -> PVPANIC_ISA_DEVICE.
7
Message-id: 20250223114708.1780-9-shentey@gmail.com
9
- TYPE_PVPANIC -> TYPE_PVPANIC_ISA.
10
- MemoryRegion io -> mr.
11
- pvpanic_ioport_* in pvpanic_*.
12
13
Update the build system with the new files and config structure.
14
15
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
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
include/hw/misc/pvpanic.h | 23 +++++++++-
11
MAINTAINERS | 2 +
20
hw/misc/pvpanic-isa.c | 94 +++++++++++++++++++++++++++++++++++++++
12
docs/system/arm/imx8mp-evk.rst | 1 +
21
hw/misc/pvpanic.c | 85 +++--------------------------------
13
include/hw/arm/fsl-imx8mp.h | 10 +++
22
hw/i386/Kconfig | 2 +-
14
include/hw/pci-host/fsl_imx8m_phy.h | 28 +++++++++
23
hw/misc/Kconfig | 6 ++-
15
hw/arm/fsl-imx8mp.c | 30 +++++++++
24
hw/misc/meson.build | 3 +-
16
hw/pci-host/fsl_imx8m_phy.c | 98 +++++++++++++++++++++++++++++
25
tests/qtest/meson.build | 2 +-
17
hw/arm/Kconfig | 3 +
26
7 files changed, 130 insertions(+), 85 deletions(-)
18
hw/pci-host/Kconfig | 3 +
27
create mode 100644 hw/misc/pvpanic-isa.c
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
28
23
29
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
24
diff --git a/MAINTAINERS b/MAINTAINERS
30
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/misc/pvpanic.h
26
--- a/MAINTAINERS
32
+++ b/include/hw/misc/pvpanic.h
27
+++ b/MAINTAINERS
28
@@ -XXX,XX +XXX,XX @@ S: Maintained
29
F: hw/arm/imx8mp-evk.c
30
F: hw/arm/fsl-imx8mp.c
31
F: hw/misc/imx8mp_*.c
32
+F: hw/pci-host/fsl_imx8m_phy.c
33
F: include/hw/arm/fsl-imx8mp.h
34
F: include/hw/misc/imx8mp_*.h
35
+F: include/hw/pci-host/fsl_imx8m_phy.h
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
33
@@ -XXX,XX +XXX,XX @@
55
@@ -XXX,XX +XXX,XX @@
34
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"
35
#include "qom/object.h"
62
#include "qom/object.h"
36
63
#include "qemu/units.h"
37
-#define TYPE_PVPANIC "pvpanic"
64
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
38
+#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
65
IMX7SNVSState snvs;
39
66
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
40
#define PVPANIC_IOPORT_PROP "ioport"
67
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
41
68
+ DesignwarePCIEHost pcie;
42
+/* The bit of supported pv event, TODO: include uapi header and remove this */
69
+ FslImx8mPciePhyState pcie_phy;
43
+#define PVPANIC_F_PANICKED 0
70
};
44
+#define PVPANIC_F_CRASHLOADED 1
71
45
+
72
enum FslImx8mpMemoryRegions {
46
+/* The pv event value */
73
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
47
+#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
74
FSL_IMX8MP_UART4_IRQ = 29,
48
+#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
75
FSL_IMX8MP_UART5_IRQ = 30,
49
+
76
FSL_IMX8MP_UART6_IRQ = 16,
50
+/*
77
+
51
+ * PVPanicState for any device type
78
+ FSL_IMX8MP_PCI_INTA_IRQ = 126,
52
+ */
79
+ FSL_IMX8MP_PCI_INTB_IRQ = 125,
53
+typedef struct PVPanicState PVPanicState;
80
+ FSL_IMX8MP_PCI_INTC_IRQ = 124,
54
+struct PVPanicState {
81
+ FSL_IMX8MP_PCI_INTD_IRQ = 123,
55
+ MemoryRegion mr;
82
+ FSL_IMX8MP_PCI_MSI_IRQ = 140,
56
+ uint8_t events;
83
};
57
+};
84
58
+
85
#endif /* FSL_IMX8MP_H */
59
+void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size);
86
diff --git a/include/hw/pci-host/fsl_imx8m_phy.h b/include/hw/pci-host/fsl_imx8m_phy.h
60
+
61
static inline uint16_t pvpanic_port(void)
62
{
63
- Object *o = object_resolve_path_type("", TYPE_PVPANIC, NULL);
64
+ Object *o = object_resolve_path_type("", TYPE_PVPANIC_ISA_DEVICE, NULL);
65
if (!o) {
66
return 0;
67
}
68
diff --git a/hw/misc/pvpanic-isa.c b/hw/misc/pvpanic-isa.c
69
new file mode 100644
87
new file mode 100644
70
index XXXXXXX..XXXXXXX
88
index XXXXXXX..XXXXXXX
71
--- /dev/null
89
--- /dev/null
72
+++ b/hw/misc/pvpanic-isa.c
90
+++ b/include/hw/pci-host/fsl_imx8m_phy.h
73
@@ -XXX,XX +XXX,XX @@
91
@@ -XXX,XX +XXX,XX @@
74
+/*
92
+/*
75
+ * QEMU simulated pvpanic device.
93
+ * i.MX8 PCIe PHY emulation
76
+ *
94
+ *
77
+ * Copyright Fujitsu, Corp. 2013
95
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
78
+ *
96
+ *
79
+ * Authors:
97
+ * SPDX-License-Identifier: GPL-2.0-or-later
80
+ * Wen Congyang <wency@cn.fujitsu.com>
98
+ */
81
+ * Hu Tao <hutao@cn.fujitsu.com>
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 @@
181
+/*
182
+ * i.MX8 PCIe PHY emulation
82
+ *
183
+ *
83
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
184
+ * Copyright (c) 2025 Bernhard Beschow <shentey@gmail.com>
84
+ * See the COPYING file in the top-level directory.
85
+ *
185
+ *
186
+ * SPDX-License-Identifier: GPL-2.0-or-later
86
+ */
187
+ */
87
+
188
+
88
+#include "qemu/osdep.h"
189
+#include "qemu/osdep.h"
89
+#include "qemu/log.h"
190
+#include "hw/pci-host/fsl_imx8m_phy.h"
90
+#include "qemu/module.h"
191
+#include "hw/resettable.h"
91
+#include "sysemu/runstate.h"
192
+#include "migration/vmstate.h"
92
+
193
+
93
+#include "hw/nvram/fw_cfg.h"
194
+#define CMN_REG075 0x1d4
94
+#include "hw/qdev-properties.h"
195
+#define ANA_PLL_LOCK_DONE BIT(1)
95
+#include "hw/misc/pvpanic.h"
196
+#define ANA_PLL_AFC_DONE BIT(0)
96
+#include "qom/object.h"
197
+
97
+#include "hw/isa/isa.h"
198
+static uint64_t fsl_imx8m_pcie_phy_read(void *opaque, hwaddr offset,
98
+
199
+ unsigned size)
99
+OBJECT_DECLARE_SIMPLE_TYPE(PVPanicISAState, PVPANIC_ISA_DEVICE)
200
+{
100
+
201
+ FslImx8mPciePhyState *s = opaque;
101
+/*
202
+
102
+ * PVPanicISAState for ISA device and
203
+ if (offset == CMN_REG075) {
103
+ * use ioport.
204
+ return s->data[offset] | ANA_PLL_LOCK_DONE | ANA_PLL_AFC_DONE;
104
+ */
205
+ }
105
+struct PVPanicISAState {
206
+
106
+ ISADevice parent_obj;
207
+ return s->data[offset];
107
+
208
+}
108
+ uint16_t ioport;
209
+
109
+ PVPanicState pvpanic;
210
+static void fsl_imx8m_pcie_phy_write(void *opaque, hwaddr offset,
211
+ uint64_t value, unsigned size)
212
+{
213
+ FslImx8mPciePhyState *s = opaque;
214
+
215
+ s->data[offset] = value;
216
+}
217
+
218
+static const MemoryRegionOps fsl_imx8m_pcie_phy_ops = {
219
+ .read = fsl_imx8m_pcie_phy_read,
220
+ .write = fsl_imx8m_pcie_phy_write,
221
+ .impl = {
222
+ .min_access_size = 1,
223
+ .max_access_size = 1,
224
+ },
225
+ .valid = {
226
+ .min_access_size = 1,
227
+ .max_access_size = 8,
228
+ },
229
+ .endianness = DEVICE_LITTLE_ENDIAN,
110
+};
230
+};
111
+
231
+
112
+static void pvpanic_isa_initfn(Object *obj)
232
+static void fsl_imx8m_pcie_phy_realize(DeviceState *dev, Error **errp)
113
+{
233
+{
114
+ PVPanicISAState *s = PVPANIC_ISA_DEVICE(obj);
234
+ FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(dev);
115
+
235
+
116
+ pvpanic_setup_io(&s->pvpanic, DEVICE(s), 1);
236
+ memory_region_init_io(&s->iomem, OBJECT(s), &fsl_imx8m_pcie_phy_ops, s,
117
+}
237
+ TYPE_FSL_IMX8M_PCIE_PHY, ARRAY_SIZE(s->data));
118
+
238
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
119
+static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
239
+}
120
+{
240
+
121
+ ISADevice *d = ISA_DEVICE(dev);
241
+static void fsl_imx8m_pcie_phy_reset_hold(Object *obj, ResetType type)
122
+ PVPanicISAState *s = PVPANIC_ISA_DEVICE(dev);
242
+{
123
+ PVPanicState *ps = &s->pvpanic;
243
+ FslImx8mPciePhyState *s = FSL_IMX8M_PCIE_PHY(obj);
124
+ FWCfgState *fw_cfg = fw_cfg_find();
244
+
125
+ uint16_t *pvpanic_port;
245
+ memset(s->data, 0, sizeof(s->data));
126
+
246
+}
127
+ if (!fw_cfg) {
247
+
128
+ return;
248
+static const VMStateDescription fsl_imx8m_pcie_phy_vmstate = {
129
+ }
249
+ .name = "fsl-imx8m-pcie-phy",
130
+
250
+ .version_id = 1,
131
+ pvpanic_port = g_malloc(sizeof(*pvpanic_port));
251
+ .minimum_version_id = 1,
132
+ *pvpanic_port = cpu_to_le16(s->ioport);
252
+ .fields = (const VMStateField[]) {
133
+ fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
253
+ VMSTATE_UINT8_ARRAY(data, FslImx8mPciePhyState,
134
+ sizeof(*pvpanic_port));
254
+ FSL_IMX8M_PCIE_PHY_DATA_SIZE),
135
+
255
+ VMSTATE_END_OF_LIST()
136
+ isa_register_ioport(d, &ps->mr, s->ioport);
256
+ }
137
+}
138
+
139
+static Property pvpanic_isa_properties[] = {
140
+ DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicISAState, ioport, 0x505),
141
+ DEFINE_PROP_UINT8("events", PVPanicISAState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
142
+ DEFINE_PROP_END_OF_LIST(),
143
+};
257
+};
144
+
258
+
145
+static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
259
+static void fsl_imx8m_pcie_phy_class_init(ObjectClass *klass, void *data)
146
+{
260
+{
147
+ DeviceClass *dc = DEVICE_CLASS(klass);
261
+ DeviceClass *dc = DEVICE_CLASS(klass);
148
+
262
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
149
+ dc->realize = pvpanic_isa_realizefn;
263
+
150
+ device_class_set_props(dc, pvpanic_isa_properties);
264
+ dc->realize = fsl_imx8m_pcie_phy_realize;
151
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
265
+ dc->vmsd = &fsl_imx8m_pcie_phy_vmstate;
152
+}
266
+ rc->phases.hold = fsl_imx8m_pcie_phy_reset_hold;
153
+
267
+}
154
+static TypeInfo pvpanic_isa_info = {
268
+
155
+ .name = TYPE_PVPANIC_ISA_DEVICE,
269
+static const TypeInfo fsl_imx8m_pcie_phy_types[] = {
156
+ .parent = TYPE_ISA_DEVICE,
270
+ {
157
+ .instance_size = sizeof(PVPanicISAState),
271
+ .name = TYPE_FSL_IMX8M_PCIE_PHY,
158
+ .instance_init = pvpanic_isa_initfn,
272
+ .parent = TYPE_SYS_BUS_DEVICE,
159
+ .class_init = pvpanic_isa_class_init,
273
+ .instance_size = sizeof(FslImx8mPciePhyState),
274
+ .class_init = fsl_imx8m_pcie_phy_class_init,
275
+ }
160
+};
276
+};
161
+
277
+
162
+static void pvpanic_register_types(void)
278
+DEFINE_TYPES(fsl_imx8m_pcie_phy_types)
163
+{
279
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
164
+ type_register_static(&pvpanic_isa_info);
280
index XXXXXXX..XXXXXXX 100644
165
+}
281
--- a/hw/arm/Kconfig
166
+
282
+++ b/hw/arm/Kconfig
167
+type_init(pvpanic_register_types)
283
@@ -XXX,XX +XXX,XX @@ config FSL_IMX7
168
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
284
169
index XXXXXXX..XXXXXXX 100644
285
config FSL_IMX8MP
170
--- a/hw/misc/pvpanic.c
171
+++ b/hw/misc/pvpanic.c
172
@@ -XXX,XX +XXX,XX @@
173
#include "hw/misc/pvpanic.h"
174
#include "qom/object.h"
175
176
-/* The bit of supported pv event, TODO: include uapi header and remove this */
177
-#define PVPANIC_F_PANICKED 0
178
-#define PVPANIC_F_CRASHLOADED 1
179
-
180
-/* The pv event value */
181
-#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
182
-#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
183
-
184
-typedef struct PVPanicState PVPanicState;
185
-DECLARE_INSTANCE_CHECKER(PVPanicState, ISA_PVPANIC_DEVICE,
186
- TYPE_PVPANIC)
187
-
188
static void handle_event(int event)
189
{
190
static bool logged;
191
@@ -XXX,XX +XXX,XX @@ static void handle_event(int event)
192
}
193
}
194
195
-#include "hw/isa/isa.h"
196
-
197
-struct PVPanicState {
198
- ISADevice parent_obj;
199
-
200
- MemoryRegion io;
201
- uint16_t ioport;
202
- uint8_t events;
203
-};
204
-
205
/* return supported events on read */
206
-static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
207
+static uint64_t pvpanic_read(void *opaque, hwaddr addr, unsigned size)
208
{
209
PVPanicState *pvp = opaque;
210
return pvp->events;
211
}
212
213
-static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val,
214
+static void pvpanic_write(void *opaque, hwaddr addr, uint64_t val,
215
unsigned size)
216
{
217
handle_event(val);
218
}
219
220
static const MemoryRegionOps pvpanic_ops = {
221
- .read = pvpanic_ioport_read,
222
- .write = pvpanic_ioport_write,
223
+ .read = pvpanic_read,
224
+ .write = pvpanic_write,
225
.impl = {
226
.min_access_size = 1,
227
.max_access_size = 1,
228
},
229
};
230
231
-static void pvpanic_isa_initfn(Object *obj)
232
+void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size)
233
{
234
- PVPanicState *s = ISA_PVPANIC_DEVICE(obj);
235
-
236
- memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1);
237
+ memory_region_init_io(&s->mr, OBJECT(dev), &pvpanic_ops, s, "pvpanic", size);
238
}
239
-
240
-static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
241
-{
242
- ISADevice *d = ISA_DEVICE(dev);
243
- PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
244
- FWCfgState *fw_cfg = fw_cfg_find();
245
- uint16_t *pvpanic_port;
246
-
247
- if (!fw_cfg) {
248
- return;
249
- }
250
-
251
- pvpanic_port = g_malloc(sizeof(*pvpanic_port));
252
- *pvpanic_port = cpu_to_le16(s->ioport);
253
- fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
254
- sizeof(*pvpanic_port));
255
-
256
- isa_register_ioport(d, &s->io, s->ioport);
257
-}
258
-
259
-static Property pvpanic_isa_properties[] = {
260
- DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
261
- DEFINE_PROP_UINT8("events", PVPanicState, events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
262
- DEFINE_PROP_END_OF_LIST(),
263
-};
264
-
265
-static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
266
-{
267
- DeviceClass *dc = DEVICE_CLASS(klass);
268
-
269
- dc->realize = pvpanic_isa_realizefn;
270
- device_class_set_props(dc, pvpanic_isa_properties);
271
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
272
-}
273
-
274
-static TypeInfo pvpanic_isa_info = {
275
- .name = TYPE_PVPANIC,
276
- .parent = TYPE_ISA_DEVICE,
277
- .instance_size = sizeof(PVPanicState),
278
- .instance_init = pvpanic_isa_initfn,
279
- .class_init = pvpanic_isa_class_init,
280
-};
281
-
282
-static void pvpanic_register_types(void)
283
-{
284
- type_register_static(&pvpanic_isa_info);
285
-}
286
-
287
-type_init(pvpanic_register_types)
288
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
289
index XXXXXXX..XXXXXXX 100644
290
--- a/hw/i386/Kconfig
291
+++ b/hw/i386/Kconfig
292
@@ -XXX,XX +XXX,XX @@ config PC
293
imply ISA_DEBUG
294
imply PARALLEL
295
imply PCI_DEVICES
296
- imply PVPANIC
297
+ imply PVPANIC_ISA
298
imply QXL
299
imply SEV
300
imply SGA
301
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
302
index XXXXXXX..XXXXXXX 100644
303
--- a/hw/misc/Kconfig
304
+++ b/hw/misc/Kconfig
305
@@ -XXX,XX +XXX,XX @@ config IOTKIT_SYSCTL
306
config IOTKIT_SYSINFO
307
bool
286
bool
308
287
+ imply PCI_DEVICES
309
-config PVPANIC
288
select ARM_GIC
310
+config PVPANIC_COMMON
289
select FSL_IMX8MP_ANALOG
290
select FSL_IMX8MP_CCM
291
select IMX
292
+ select PCI_EXPRESS_DESIGNWARE
293
+ select PCI_EXPRESS_FSL_IMX8M_PHY
294
select SDHCI
295
select UNIMP
296
297
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
298
index XXXXXXX..XXXXXXX 100644
299
--- a/hw/pci-host/Kconfig
300
+++ b/hw/pci-host/Kconfig
301
@@ -XXX,XX +XXX,XX @@ config ASTRO
302
bool
303
select PCI
304
305
+config PCI_EXPRESS_FSL_IMX8M_PHY
311
+ bool
306
+ bool
312
+
307
+
313
+config PVPANIC_ISA
308
config GT64120
314
bool
309
bool
315
depends on ISA_BUS
310
select PCI
316
+ select PVPANIC_COMMON
311
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
317
312
index XXXXXXX..XXXXXXX 100644
318
config AUX
313
--- a/hw/pci-host/meson.build
319
bool
314
+++ b/hw/pci-host/meson.build
320
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
315
@@ -XXX,XX +XXX,XX @@ pci_ss.add(when: 'CONFIG_ARTICIA', if_true: files('articia.c'))
321
index XXXXXXX..XXXXXXX 100644
316
pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c'))
322
--- a/hw/misc/meson.build
323
+++ b/hw/misc/meson.build
324
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
325
softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c'))
326
softmmu_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c'))
327
softmmu_ss.add(when: 'CONFIG_LED', if_true: files('led.c'))
328
+softmmu_ss.add(when: 'CONFIG_PVPANIC_COMMON', if_true: files('pvpanic.c'))
329
317
330
# ARM devices
318
# ARM devices
331
softmmu_ss.add(when: 'CONFIG_PL310', if_true: files('arm_l2x0.c'))
319
+pci_ss.add(when: 'CONFIG_PCI_EXPRESS_FSL_IMX8M_PHY', if_true: files('fsl_imx8m_phy.c'))
332
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true: files('iotkit-sysinfo.c')
320
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
333
softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
321
334
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
322
# HPPA devices
335
336
-softmmu_ss.add(when: 'CONFIG_PVPANIC', if_true: files('pvpanic.c'))
337
+softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
338
softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
339
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_scu.c', 'aspeed_sdmc.c', 'aspeed_xdma.c'))
340
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
341
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
342
index XXXXXXX..XXXXXXX 100644
343
--- a/tests/qtest/meson.build
344
+++ b/tests/qtest/meson.build
345
@@ -XXX,XX +XXX,XX @@ qtests_i386 = \
346
(config_host.has_key('CONFIG_LINUX') and \
347
config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \
348
(config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + \
349
- (config_all_devices.has_key('CONFIG_PVPANIC') ? ['pvpanic-test'] : []) + \
350
+ (config_all_devices.has_key('CONFIG_PVPANIC_ISA') ? ['pvpanic-test'] : []) + \
351
(config_all_devices.has_key('CONFIG_HDA') ? ['intel-hda-test'] : []) + \
352
(config_all_devices.has_key('CONFIG_I82801B11') ? ['i82801b11-test'] : []) + \
353
(config_all_devices.has_key('CONFIG_IOH3420') ? ['ioh3420-test'] : []) + \
354
--
323
--
355
2.20.1
324
2.43.0
356
357
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
In macOS 11, QEMU only gets access to Hypervisor.framework if it has the
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
respective entitlement. Add an entitlement template and automatically self
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
sign and apply the entitlement in the build.
5
Message-id: 20250223114708.1780-10-shentey@gmail.com
6
6
[PMM: drop static const from gpio_table for GCC 7.5]
7
Signed-off-by: Alexander Graf <agraf@csgraf.de>
8
Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
9
Tested-by: Roman Bolshakov <r.bolshakov@yadro.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
meson.build | 29 +++++++++++++++++++++++++----
9
docs/system/arm/imx8mp-evk.rst | 1 +
13
accel/hvf/entitlements.plist | 8 ++++++++
10
include/hw/arm/fsl-imx8mp.h | 14 +++++++++
14
scripts/entitlement.sh | 13 +++++++++++++
11
hw/arm/fsl-imx8mp.c | 55 ++++++++++++++++++++++++++++++++++
15
3 files changed, 46 insertions(+), 4 deletions(-)
12
3 files changed, 70 insertions(+)
16
create mode 100644 accel/hvf/entitlements.plist
17
create mode 100755 scripts/entitlement.sh
18
13
19
diff --git a/meson.build b/meson.build
14
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/meson.build
16
--- a/docs/system/arm/imx8mp-evk.rst
22
+++ b/meson.build
17
+++ b/docs/system/arm/imx8mp-evk.rst
23
@@ -XXX,XX +XXX,XX @@ foreach target : target_dirs
18
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
24
}]
19
* 4 UARTs
25
endif
20
* 3 USDHC Storage Controllers
26
foreach exe: execs
21
* 1 Designware PCI Express Controller
27
- emulators += {exe['name']:
22
+ * 5 GPIO Controllers
28
- executable(exe['name'], exe['sources'],
23
* Secure Non-Volatile Storage (SNVS) including an RTC
29
- install: true,
24
* Clock Tree
30
+ exe_name = exe['name']
25
31
+ exe_sign = 'CONFIG_HVF' in config_target
26
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
32
+ if exe_sign
27
index XXXXXXX..XXXXXXX 100644
33
+ exe_name += '-unsigned'
28
--- a/include/hw/arm/fsl-imx8mp.h
34
+ endif
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,
35
+
68
+
36
+ emulator = executable(exe_name, exe['sources'],
69
FSL_IMX8MP_PCI_INTA_IRQ = 126,
37
+ install: not exe_sign,
70
FSL_IMX8MP_PCI_INTB_IRQ = 125,
38
c_args: c_args,
71
FSL_IMX8MP_PCI_INTC_IRQ = 124,
39
dependencies: arch_deps + deps + exe['dependencies'],
72
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
40
objects: lib.extract_all_objects(recursive: true),
73
index XXXXXXX..XXXXXXX 100644
41
@@ -XXX,XX +XXX,XX @@ foreach target : target_dirs
74
--- a/hw/arm/fsl-imx8mp.c
42
link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
75
+++ b/hw/arm/fsl-imx8mp.c
43
link_args: link_args,
76
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
44
gui_app: exe['gui'])
77
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
45
- }
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
+ }
46
+
84
+
47
+ if exe_sign
85
for (i = 0; i < FSL_IMX8MP_NUM_USDHCS; i++) {
48
+ emulators += {exe['name'] : custom_target(exe['name'],
86
g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
49
+ install: true,
87
object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
50
+ install_dir: get_option('bindir'),
88
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
51
+ depends: emulator,
89
qdev_get_gpio_in(gicdev, serial_table[i].irq));
52
+ output: exe['name'],
90
}
53
+ command: [
91
54
+ meson.current_source_dir() / 'scripts/entitlement.sh',
92
+ /* GPIOs */
55
+ meson.current_build_dir() / exe_name,
93
+ for (i = 0; i < FSL_IMX8MP_NUM_GPIOS; i++) {
56
+ meson.current_build_dir() / exe['name'],
94
+ struct {
57
+ meson.current_source_dir() / 'accel/hvf/entitlements.plist'
95
+ hwaddr addr;
58
+ ])
96
+ unsigned int irq_low;
59
+ }
97
+ unsigned int irq_high;
60
+ else
98
+ } gpio_table[FSL_IMX8MP_NUM_GPIOS] = {
61
+ emulators += {exe['name']: emulator}
99
+ {
62
+ endif
100
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO1].addr,
63
101
+ FSL_IMX8MP_GPIO1_LOW_IRQ,
64
if 'CONFIG_TRACE_SYSTEMTAP' in config_host
102
+ FSL_IMX8MP_GPIO1_HIGH_IRQ
65
foreach stp: [
103
+ },
66
diff --git a/accel/hvf/entitlements.plist b/accel/hvf/entitlements.plist
104
+ {
67
new file mode 100644
105
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO2].addr,
68
index XXXXXXX..XXXXXXX
106
+ FSL_IMX8MP_GPIO2_LOW_IRQ,
69
--- /dev/null
107
+ FSL_IMX8MP_GPIO2_HIGH_IRQ
70
+++ b/accel/hvf/entitlements.plist
108
+ },
71
@@ -XXX,XX +XXX,XX @@
109
+ {
72
+<?xml version="1.0" encoding="UTF-8"?>
110
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO3].addr,
73
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
111
+ FSL_IMX8MP_GPIO3_LOW_IRQ,
74
+<plist version="1.0">
112
+ FSL_IMX8MP_GPIO3_HIGH_IRQ
75
+<dict>
113
+ },
76
+ <key>com.apple.security.hypervisor</key>
114
+ {
77
+ <true/>
115
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO4].addr,
78
+</dict>
116
+ FSL_IMX8MP_GPIO4_LOW_IRQ,
79
+</plist>
117
+ FSL_IMX8MP_GPIO4_HIGH_IRQ
80
diff --git a/scripts/entitlement.sh b/scripts/entitlement.sh
118
+ },
81
new file mode 100755
119
+ {
82
index XXXXXXX..XXXXXXX
120
+ fsl_imx8mp_memmap[FSL_IMX8MP_GPIO5].addr,
83
--- /dev/null
121
+ FSL_IMX8MP_GPIO5_LOW_IRQ,
84
+++ b/scripts/entitlement.sh
122
+ FSL_IMX8MP_GPIO5_HIGH_IRQ
85
@@ -XXX,XX +XXX,XX @@
123
+ },
86
+#!/bin/sh -e
124
+ };
87
+#
88
+# Helper script for the build process to apply entitlements
89
+
125
+
90
+SRC="$1"
126
+ object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", true,
91
+DST="$2"
127
+ &error_abort);
92
+ENTITLEMENT="$3"
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
+ }
93
+
133
+
94
+trap 'rm "$DST.tmp"' exit
134
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
95
+cp -af "$SRC" "$DST.tmp"
135
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
96
+codesign --entitlements "$ENTITLEMENT" --force -s - "$DST.tmp"
136
+ qdev_get_gpio_in(gicdev, gpio_table[i].irq_low));
97
+mv "$DST.tmp" "$DST"
137
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
98
+trap '' exit
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:
99
--
152
--
100
2.20.1
153
2.43.0
101
102
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Bernhard Beschow <shentey@gmail.com>
2
3
A workaround added in early days of 64-bit OSX forced x86_64 if the
4
host machine had 64-bit support. This creates issues when cross-
5
compiling for ARM64. Additionally, the user can always use --cpu=* to
6
manually set the host CPU and therefore this workaround should be
7
removed.
8
2
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Joelle van Dyne <j@getutm.app>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
11
Message-id: 20210126012457.39046-12-j@getutm.app
5
Message-id: 20250223114708.1780-11-shentey@gmail.com
6
[PMM: drop static const from i2c_table for GCC 7.5]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
8
---
14
configure | 11 -----------
9
docs/system/arm/imx8mp-evk.rst | 1 +
15
1 file changed, 11 deletions(-)
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(+)
16
14
17
diff --git a/configure b/configure
15
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
18
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
19
--- a/configure
17
--- a/docs/system/arm/imx8mp-evk.rst
20
+++ b/configure
18
+++ b/docs/system/arm/imx8mp-evk.rst
21
@@ -XXX,XX +XXX,XX @@ fi
19
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
22
# the correct CPU with the --cpu option.
20
* 3 USDHC Storage Controllers
23
case $targetos in
21
* 1 Designware PCI Express Controller
24
Darwin)
22
* 5 GPIO Controllers
25
- # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
23
+ * 6 I2C Controllers
26
- # run 64-bit userspace code.
24
* Secure Non-Volatile Storage (SNVS) including an RTC
27
- # If the user didn't specify a CPU explicitly and the kernel says this is
25
* Clock Tree
28
- # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
26
29
- if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
27
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
30
- cpu="x86_64"
28
index XXXXXXX..XXXXXXX 100644
31
- fi
29
--- a/include/hw/arm/fsl-imx8mp.h
32
HOST_DSOSUF=".dylib"
30
+++ b/include/hw/arm/fsl-imx8mp.h
33
;;
31
@@ -XXX,XX +XXX,XX @@
34
SunOS)
32
#include "cpu.h"
35
@@ -XXX,XX +XXX,XX @@ OpenBSD)
33
#include "hw/char/imx_serial.h"
36
Darwin)
34
#include "hw/gpio/imx_gpio.h"
37
bsd="yes"
35
+#include "hw/i2c/imx_i2c.h"
38
darwin="yes"
36
#include "hw/intc/arm_gicv3_common.h"
39
- if [ "$cpu" = "x86_64" ] ; then
37
#include "hw/misc/imx7_snvs.h"
40
- QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
38
#include "hw/misc/imx8mp_analog.h"
41
- QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS"
39
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
42
- fi
40
enum FslImx8mpConfiguration {
43
audio_drv_list="try-coreaudio try-sdl"
41
FSL_IMX8MP_NUM_CPUS = 4,
44
audio_possible_drivers="coreaudio sdl"
42
FSL_IMX8MP_NUM_GPIOS = 5,
45
# Disable attempts to use ObjectiveC features in os/object.h since they
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
46
--
149
--
47
2.20.1
150
2.43.0
48
49
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Bernhard Beschow <shentey@gmail.com>
2
3
Add objc to the Meson cross file as well as detection of Darwin.
4
2
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20250223114708.1780-12-shentey@gmail.com
8
Message-id: 20210126012457.39046-8-j@getutm.app
6
[PMM: drop static const from spi_table for GCC 7.5]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
8
---
11
configure | 4 ++++
9
docs/system/arm/imx8mp-evk.rst | 1 +
12
1 file changed, 4 insertions(+)
10
include/hw/arm/fsl-imx8mp.h | 8 ++++++++
11
hw/arm/fsl-imx8mp.c | 26 ++++++++++++++++++++++++++
12
3 files changed, 35 insertions(+)
13
13
14
diff --git a/configure b/configure
14
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
15
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
16
--- a/configure
16
--- a/docs/system/arm/imx8mp-evk.rst
17
+++ b/configure
17
+++ b/docs/system/arm/imx8mp-evk.rst
18
@@ -XXX,XX +XXX,XX @@ echo "cpp_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross
18
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
19
echo "[binaries]" >> $cross
19
* 1 Designware PCI Express Controller
20
echo "c = [$(meson_quote $cc)]" >> $cross
20
* 5 GPIO Controllers
21
test -n "$cxx" && echo "cpp = [$(meson_quote $cxx)]" >> $cross
21
* 6 I2C Controllers
22
+test -n "$objcc" && echo "objc = [$(meson_quote $objcc)]" >> $cross
22
+ * 3 SPI Controllers
23
echo "ar = [$(meson_quote $ar)]" >> $cross
23
* Secure Non-Volatile Storage (SNVS) including an RTC
24
echo "nm = [$(meson_quote $nm)]" >> $cross
24
* Clock Tree
25
echo "pkgconfig = [$(meson_quote $pkg_config_exe)]" >> $cross
25
26
@@ -XXX,XX +XXX,XX @@ if test "$cross_compile" = "yes"; then
26
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
27
if test "$linux" = "yes" ; then
27
index XXXXXXX..XXXXXXX 100644
28
echo "system = 'linux'" >> $cross
28
--- a/include/hw/arm/fsl-imx8mp.h
29
fi
29
+++ b/include/hw/arm/fsl-imx8mp.h
30
+ if test "$darwin" = "yes" ; then
30
@@ -XXX,XX +XXX,XX @@
31
+ echo "system = 'darwin'" >> $cross
31
#include "hw/pci-host/designware.h"
32
+ fi
32
#include "hw/pci-host/fsl_imx8m_phy.h"
33
case "$ARCH" in
33
#include "hw/sd/sdhci.h"
34
i386|x86_64)
34
+#include "hw/ssi/imx_spi.h"
35
echo "cpu_family = 'x86'" >> $cross
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:
36
--
117
--
37
2.20.1
118
2.43.0
38
39
diff view generated by jsdifflib
1
The old-style convenience function cmsdk_apb_timer_create() for
1
From: Bernhard Beschow <shentey@gmail.com>
2
creating CMSDK_APB_TIMER objects is used in only two places in
3
mps2.c. Most of the rest of the code in that file uses the new
4
"initialize in place" coding style.
5
2
6
We want to connect up a Clock object which should be done between the
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
object creation and realization; rather than adding a Clock* argument
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
to the convenience function, convert the timer creation code in
5
Message-id: 20250223114708.1780-13-shentey@gmail.com
9
mps2.c to the same style as is used already for the watchdog,
6
[PMM: drop static const from wdog_table for GCC 7.5]
10
dualtimer and other devices, and delete the now-unused convenience
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
function.
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(+)
12
14
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Luc Michel <luc@lmichel.fr>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20210128114145.20536-13-peter.maydell@linaro.org
18
Message-id: 20210121190622.22000-13-peter.maydell@linaro.org
19
---
20
include/hw/timer/cmsdk-apb-timer.h | 21 ---------------------
21
hw/arm/mps2.c | 18 ++++++++++++++++--
22
2 files changed, 16 insertions(+), 23 deletions(-)
23
24
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/timer/cmsdk-apb-timer.h
17
--- a/docs/system/arm/imx8mp-evk.rst
27
+++ b/include/hw/timer/cmsdk-apb-timer.h
18
+++ b/docs/system/arm/imx8mp-evk.rst
28
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
19
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
29
uint32_t intstatus;
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,
30
};
44
};
31
45
32
-/**
46
struct FslImx8mpState {
33
- * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER
47
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
34
- * @addr: location in system memory to map registers
48
IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
35
- * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
49
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
36
- */
50
SDHCIState usdhc[FSL_IMX8MP_NUM_USDHCS];
37
-static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr,
51
+ IMX2WdtState wdt[FSL_IMX8MP_NUM_WDTS];
38
- qemu_irq timerint,
52
DesignwarePCIEHost pcie;
39
- uint32_t pclk_frq)
53
FslImx8mPciePhyState pcie_phy;
40
-{
54
};
41
- DeviceState *dev;
55
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
42
- SysBusDevice *s;
56
FSL_IMX8MP_I2C5_IRQ = 76,
43
-
57
FSL_IMX8MP_I2C6_IRQ = 77,
44
- dev = qdev_new(TYPE_CMSDK_APB_TIMER);
58
45
- s = SYS_BUS_DEVICE(dev);
59
+ FSL_IMX8MP_WDOG1_IRQ = 78,
46
- qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
60
+ FSL_IMX8MP_WDOG2_IRQ = 79,
47
- sysbus_realize_and_unref(s, &error_fatal);
61
+ FSL_IMX8MP_WDOG3_IRQ = 10,
48
- sysbus_mmio_map(s, 0, addr);
62
+
49
- sysbus_connect_irq(s, 0, timerint);
63
FSL_IMX8MP_PCI_INTA_IRQ = 126,
50
- return dev;
64
FSL_IMX8MP_PCI_INTB_IRQ = 125,
51
-}
65
FSL_IMX8MP_PCI_INTC_IRQ = 124,
52
-
66
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
53
#endif
54
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
55
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/mps2.c
68
--- a/hw/arm/fsl-imx8mp.c
57
+++ b/hw/arm/mps2.c
69
+++ b/hw/arm/fsl-imx8mp.c
58
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineState {
70
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
59
/* CMSDK APB subsystem */
71
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
60
CMSDKAPBDualTimer dualtimer;
61
CMSDKAPBWatchdog watchdog;
62
+ CMSDKAPBTimer timer[2];
63
};
64
65
#define TYPE_MPS2_MACHINE "mps2"
66
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
67
}
72
}
68
73
69
/* CMSDK APB subsystem */
74
+ for (i = 0; i < FSL_IMX8MP_NUM_WDTS; i++) {
70
- cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
75
+ g_autofree char *name = g_strdup_printf("wdt%d", i);
71
- cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
76
+ object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
72
+ for (i = 0; i < ARRAY_SIZE(mms->timer); i++) {
73
+ g_autofree char *name = g_strdup_printf("timer%d", i);
74
+ hwaddr base = 0x40000000 + i * 0x1000;
75
+ int irqno = 8 + i;
76
+ SysBusDevice *sbd;
77
+
78
+ object_initialize_child(OBJECT(mms), name, &mms->timer[i],
79
+ TYPE_CMSDK_APB_TIMER);
80
+ sbd = SYS_BUS_DEVICE(&mms->timer[i]);
81
+ qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
82
+ sysbus_realize_and_unref(sbd, &error_fatal);
83
+ sysbus_mmio_map(sbd, 0, base);
84
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(armv7m, irqno));
85
+ }
77
+ }
86
+
78
+
87
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
79
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
88
TYPE_CMSDK_APB_DUALTIMER);
80
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
89
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
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
90
--
131
--
91
2.20.1
132
2.43.0
92
93
diff view generated by jsdifflib
1
Now no users are setting the frq properties on the CMSDK timer,
1
From: Bernhard Beschow <shentey@gmail.com>
2
dualtimer, watchdog or ARMSSE SoC devices, we can remove the
3
properties and the struct fields that back them.
4
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]
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210128114145.20536-25-peter.maydell@linaro.org
10
Message-id: 20210121190622.22000-25-peter.maydell@linaro.org
11
---
8
---
12
include/hw/arm/armsse.h | 2 --
9
docs/system/arm/imx8mp-evk.rst | 1 +
13
include/hw/timer/cmsdk-apb-dualtimer.h | 2 --
10
include/hw/arm/fsl-imx8mp.h | 11 +++++++
14
include/hw/timer/cmsdk-apb-timer.h | 2 --
11
include/hw/timer/imx_gpt.h | 1 +
15
include/hw/watchdog/cmsdk-apb-watchdog.h | 2 --
12
hw/arm/fsl-imx8mp.c | 53 ++++++++++++++++++++++++++++++++++
16
hw/arm/armsse.c | 2 --
13
hw/timer/imx_gpt.c | 25 ++++++++++++++++
17
hw/timer/cmsdk-apb-dualtimer.c | 6 ------
14
hw/arm/Kconfig | 1 +
18
hw/timer/cmsdk-apb-timer.c | 6 ------
15
6 files changed, 92 insertions(+)
19
hw/watchdog/cmsdk-apb-watchdog.c | 6 ------
20
8 files changed, 28 deletions(-)
21
16
22
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
23
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/armsse.h
19
--- a/docs/system/arm/imx8mp-evk.rst
25
+++ b/include/hw/arm/armsse.h
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
26
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@
27
* + Clock input "S32KCLK": slow 32KHz clock used for a few peripherals
34
#include "hw/misc/imx7_snvs.h"
28
* + QOM property "memory" is a MemoryRegion containing the devices provided
35
#include "hw/misc/imx8mp_analog.h"
29
* by the board model.
36
#include "hw/misc/imx8mp_ccm.h"
30
- * + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
37
+#include "hw/or-irq.h"
31
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
38
#include "hw/pci-host/designware.h"
32
* (In hardware, the SSE-200 permits the number of expansion interrupts
39
#include "hw/pci-host/fsl_imx8m_phy.h"
33
* for the two CPUs to be configured separately, but we restrict it to
40
#include "hw/sd/sdhci.h"
34
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
41
#include "hw/ssi/imx_spi.h"
35
/* Properties */
42
+#include "hw/timer/imx_gpt.h"
36
MemoryRegion *board_memory;
43
#include "hw/watchdog/wdt_imx2.h"
37
uint32_t exp_numirq;
44
#include "qom/object.h"
38
- uint32_t mainclk_frq;
45
#include "qemu/units.h"
39
uint32_t sram_addr_width;
46
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpConfiguration {
40
uint32_t init_svtor;
47
FSL_IMX8MP_NUM_CPUS = 4,
41
bool cpu_fpu[SSE_MAX_CPUS];
48
FSL_IMX8MP_NUM_ECSPIS = 3,
42
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
49
FSL_IMX8MP_NUM_GPIOS = 5,
43
index XXXXXXX..XXXXXXX 100644
50
+ FSL_IMX8MP_NUM_GPTS = 6,
44
--- a/include/hw/timer/cmsdk-apb-dualtimer.h
51
FSL_IMX8MP_NUM_I2CS = 6,
45
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
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
46
@@ -XXX,XX +XXX,XX @@
87
@@ -XXX,XX +XXX,XX @@
47
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
88
#define TYPE_IMX6_GPT "imx6.gpt"
48
*
89
#define TYPE_IMX6UL_GPT "imx6ul.gpt"
49
* QEMU interface:
90
#define TYPE_IMX7_GPT "imx7.gpt"
50
- * + QOM property "pclk-frq": frequency at which the timer is clocked
91
+#define TYPE_IMX8MP_GPT "imx8mp.gpt"
51
* + Clock input "TIMCLK": clock (for both timers)
92
52
* + sysbus MMIO region 0: the register bank
93
#define TYPE_IMX_GPT TYPE_IMX25_GPT
53
* + sysbus IRQ 0: combined timer interrupt TIMINTC
94
54
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBDualTimer {
95
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
55
/*< public >*/
96
index XXXXXXX..XXXXXXX 100644
56
MemoryRegion iomem;
97
--- a/hw/arm/fsl-imx8mp.c
57
qemu_irq timerintc;
98
+++ b/hw/arm/fsl-imx8mp.c
58
- uint32_t pclk_frq;
99
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_init(Object *obj)
59
Clock *timclk;
100
object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
60
61
CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
62
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/include/hw/timer/cmsdk-apb-timer.h
65
+++ b/include/hw/timer/cmsdk-apb-timer.h
66
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
67
68
/*
69
* QEMU interface:
70
- * + QOM property "pclk-frq": frequency at which the timer is clocked
71
* + Clock input "pclk": clock for the timer
72
* + sysbus MMIO region 0: the register bank
73
* + sysbus IRQ 0: timer interrupt TIMERINT
74
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
75
/*< public >*/
76
MemoryRegion iomem;
77
qemu_irq timerint;
78
- uint32_t pclk_frq;
79
struct ptimer_state *timer;
80
Clock *pclk;
81
82
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
83
index XXXXXXX..XXXXXXX 100644
84
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
85
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
86
@@ -XXX,XX +XXX,XX @@
87
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
88
*
89
* QEMU interface:
90
- * + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
91
* + Clock input "WDOGCLK": clock for the watchdog's timer
92
* + sysbus MMIO region 0: the register bank
93
* + sysbus IRQ 0: watchdog interrupt
94
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBWatchdog {
95
/*< public >*/
96
MemoryRegion iomem;
97
qemu_irq wdogint;
98
- uint32_t wdogclk_frq;
99
bool is_luminary;
100
struct ptimer_state *timer;
101
Clock *wdogclk;
102
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/hw/arm/armsse.c
105
+++ b/hw/arm/armsse.c
106
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
107
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
108
MemoryRegion *),
109
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
110
- DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
111
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
112
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
113
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
114
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
115
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
116
MemoryRegion *),
117
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
118
- DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
119
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
120
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
121
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
122
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/timer/cmsdk-apb-dualtimer.c
125
+++ b/hw/timer/cmsdk-apb-dualtimer.c
126
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
127
}
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 */
128
};
172
};
129
173
130
-static Property cmsdk_apb_dualtimer_properties[] = {
174
+static const IMXClk imx8mp_gpt_clocks[] = {
131
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
175
+ CLK_NONE, /* 000 No clock source */
132
- DEFINE_PROP_END_OF_LIST(),
176
+ CLK_IPG, /* 001 ipg_clk, 532MHz */
133
-};
177
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
134
-
178
+ CLK_EXT, /* 011 External clock */
135
static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
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)
136
{
187
{
137
DeviceClass *dc = DEVICE_CLASS(klass);
188
@@ -XXX,XX +XXX,XX @@ static void imx7_gpt_init(Object *obj)
138
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
189
s->clocks = imx7_gpt_clocks;
139
dc->realize = cmsdk_apb_dualtimer_realize;
140
dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
141
dc->reset = cmsdk_apb_dualtimer_reset;
142
- device_class_set_props(dc, cmsdk_apb_dualtimer_properties);
143
}
190
}
144
191
145
static const TypeInfo cmsdk_apb_dualtimer_info = {
192
+static void imx8mp_gpt_init(Object *obj)
146
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
193
+{
147
index XXXXXXX..XXXXXXX 100644
194
+ IMXGPTState *s = IMX_GPT(obj);
148
--- a/hw/timer/cmsdk-apb-timer.c
195
+
149
+++ b/hw/timer/cmsdk-apb-timer.c
196
+ s->clocks = imx8mp_gpt_clocks;
150
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_timer_vmstate = {
197
+}
151
}
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,
152
};
204
};
153
205
154
-static Property cmsdk_apb_timer_properties[] = {
206
+static const TypeInfo imx8mp_gpt_info = {
155
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTimer, pclk_frq, 0),
207
+ .name = TYPE_IMX8MP_GPT,
156
- DEFINE_PROP_END_OF_LIST(),
208
+ .parent = TYPE_IMX25_GPT,
157
-};
209
+ .instance_init = imx8mp_gpt_init,
158
-
210
+};
159
static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
211
+
212
static void imx_gpt_register_types(void)
160
{
213
{
161
DeviceClass *dc = DEVICE_CLASS(klass);
214
type_register_static(&imx25_gpt_info);
162
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
215
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_register_types(void)
163
dc->realize = cmsdk_apb_timer_realize;
216
type_register_static(&imx6_gpt_info);
164
dc->vmsd = &cmsdk_apb_timer_vmstate;
217
type_register_static(&imx6ul_gpt_info);
165
dc->reset = cmsdk_apb_timer_reset;
218
type_register_static(&imx7_gpt_info);
166
- device_class_set_props(dc, cmsdk_apb_timer_properties);
219
+ type_register_static(&imx8mp_gpt_info);
167
}
220
}
168
221
169
static const TypeInfo cmsdk_apb_timer_info = {
222
type_init(imx_gpt_register_types)
170
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
223
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
171
index XXXXXXX..XXXXXXX 100644
224
index XXXXXXX..XXXXXXX 100644
172
--- a/hw/watchdog/cmsdk-apb-watchdog.c
225
--- a/hw/arm/Kconfig
173
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
226
+++ b/hw/arm/Kconfig
174
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
227
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
175
}
228
select FSL_IMX8MP_CCM
176
};
229
select IMX
177
230
select IMX_I2C
178
-static Property cmsdk_apb_watchdog_properties[] = {
231
+ select OR_IRQ
179
- DEFINE_PROP_UINT32("wdogclk-frq", CMSDKAPBWatchdog, wdogclk_frq, 0),
232
select PCI_EXPRESS_DESIGNWARE
180
- DEFINE_PROP_END_OF_LIST(),
233
select PCI_EXPRESS_FSL_IMX8M_PHY
181
-};
234
select SDHCI
182
-
183
static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
184
{
185
DeviceClass *dc = DEVICE_CLASS(klass);
186
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
187
dc->realize = cmsdk_apb_watchdog_realize;
188
dc->vmsd = &cmsdk_apb_watchdog_vmstate;
189
dc->reset = cmsdk_apb_watchdog_reset;
190
- device_class_set_props(dc, cmsdk_apb_watchdog_properties);
191
}
192
193
static const TypeInfo cmsdk_apb_watchdog_info = {
194
--
235
--
195
2.20.1
236
2.43.0
196
197
diff view generated by jsdifflib
1
Create a fixed-frequency Clock object to be the SYSCLK, and wire it
1
From: Bernhard Beschow <shentey@gmail.com>
2
up to the devices that require it.
3
2
3
The i.MX 8M Plus SoC actually has two ethernet controllers, the usual ENET one
4
and a Designware one. There is no device model for the latter, so only add the
5
ENET one.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Message-id: 20250223114708.1780-15-shentey@gmail.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-14-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-14-peter.maydell@linaro.org
10
---
11
---
11
hw/arm/mps2.c | 9 +++++++++
12
docs/system/arm/imx8mp-evk.rst | 1 +
12
1 file changed, 9 insertions(+)
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(+)
13
18
14
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
19
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/mps2.c
21
--- a/docs/system/arm/imx8mp-evk.rst
17
+++ b/hw/arm/mps2.c
22
+++ b/docs/system/arm/imx8mp-evk.rst
23
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
24
* 4 UARTs
25
* 3 USDHC Storage Controllers
26
* 1 Designware PCI Express Controller
27
+ * 1 Ethernet Controller
28
* 5 GPIO Controllers
29
* 6 I2C Controllers
30
* 3 SPI Controllers
31
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/arm/fsl-imx8mp.h
34
+++ b/include/hw/arm/fsl-imx8mp.h
18
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
19
#include "hw/net/lan9118.h"
36
#include "hw/misc/imx7_snvs.h"
20
#include "net/net.h"
37
#include "hw/misc/imx8mp_analog.h"
21
#include "hw/watchdog/cmsdk-apb-watchdog.h"
38
#include "hw/misc/imx8mp_ccm.h"
22
+#include "hw/qdev-clock.h"
39
+#include "hw/net/imx_fec.h"
23
#include "qom/object.h"
40
#include "hw/or-irq.h"
24
41
#include "hw/pci-host/designware.h"
25
typedef enum MPS2FPGAType {
42
#include "hw/pci-host/fsl_imx8m_phy.h"
26
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineState {
43
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
27
CMSDKAPBDualTimer dualtimer;
44
IMXSPIState spi[FSL_IMX8MP_NUM_ECSPIS];
28
CMSDKAPBWatchdog watchdog;
45
IMXI2CState i2c[FSL_IMX8MP_NUM_I2CS];
29
CMSDKAPBTimer timer[2];
46
IMXSerialState uart[FSL_IMX8MP_NUM_UARTS];
30
+ Clock *sysclk;
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;
31
};
56
};
32
57
33
#define TYPE_MPS2_MACHINE "mps2"
58
enum FslImx8mpMemoryRegions {
34
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
59
@@ -XXX,XX +XXX,XX @@ enum FslImx8mpIrqs {
35
exit(EXIT_FAILURE);
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);
36
}
75
}
37
76
38
+ /* This clock doesn't need migration because it is fixed-frequency */
77
+ object_initialize_child(obj, "eth0", &s->enet, TYPE_IMX_ENET);
39
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
40
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
41
+
78
+
42
/* The FPGA images have an odd combination of different RAMs,
79
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
43
* because in hardware they are different implementations and
80
object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
44
* connected to different buses, giving varying performance/size
81
TYPE_FSL_IMX8M_PCIE_PHY);
45
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
82
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
46
TYPE_CMSDK_APB_TIMER);
83
qdev_get_gpio_in(gicdev, spi_table[i].irq));
47
sbd = SYS_BUS_DEVICE(&mms->timer[i]);
84
}
48
qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
85
49
+ qdev_connect_clock_in(DEVICE(&mms->timer[i]), "pclk", mms->sysclk);
86
+ /* ENET1 */
50
sysbus_realize_and_unref(sbd, &error_fatal);
87
+ object_property_set_uint(OBJECT(&s->enet), "phy-num", s->phy_num,
51
sysbus_mmio_map(sbd, 0, base);
88
+ &error_abort);
52
sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(armv7m, irqno));
89
+ object_property_set_uint(OBJECT(&s->enet), "tx-ring-num", 3, &error_abort);
53
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
90
+ qemu_configure_nic_device(DEVICE(&s->enet), true, NULL);
54
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
91
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->enet), errp)) {
55
TYPE_CMSDK_APB_DUALTIMER);
92
+ return;
56
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
93
+ }
57
+ qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->sysclk);
94
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0,
58
sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
95
+ fsl_imx8mp_memmap[FSL_IMX8MP_ENET1].addr);
59
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
96
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0,
60
qdev_get_gpio_in(armv7m, 10));
97
+ qdev_get_gpio_in(gicdev, FSL_IMX8MP_ENET1_MAC_IRQ));
61
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
98
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1,
62
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
99
+ qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IRQ));
63
TYPE_CMSDK_APB_WATCHDOG);
100
+
64
qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
101
/* SNVS */
65
+ qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->sysclk);
102
if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
66
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
103
return;
67
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
104
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
68
qdev_get_gpio_in_named(armv7m, "NMI", 0));
105
case FSL_IMX8MP_GIC_REDIST:
106
case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
107
case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
108
+ case FSL_IMX8MP_ENET1:
109
case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
110
case FSL_IMX8MP_PCIE1:
111
case FSL_IMX8MP_PCIE_PHY1:
112
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
113
}
114
}
115
116
+static const Property fsl_imx8mp_properties[] = {
117
+ DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mpState, phy_num, 0),
118
+ DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mpState, phy_connected, true),
119
+};
120
+
121
static void fsl_imx8mp_class_init(ObjectClass *oc, void *data)
122
{
123
DeviceClass *dc = DEVICE_CLASS(oc);
124
125
+ device_class_set_props(dc, fsl_imx8mp_properties);
126
dc->realize = fsl_imx8mp_realize;
127
128
dc->desc = "i.MX 8M Plus SoC";
129
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/imx8mp-evk.c
132
+++ b/hw/arm/imx8mp-evk.c
133
@@ -XXX,XX +XXX,XX @@ static void imx8mp_evk_init(MachineState *machine)
134
135
s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP));
136
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
137
+ object_property_set_uint(OBJECT(s), "fec1-phy-num", 1, &error_fatal);
138
qdev_realize(DEVICE(s), NULL, &error_fatal);
139
140
memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
141
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hw/arm/Kconfig
144
+++ b/hw/arm/Kconfig
145
@@ -XXX,XX +XXX,XX @@ config FSL_IMX8MP
146
select FSL_IMX8MP_ANALOG
147
select FSL_IMX8MP_CCM
148
select IMX
149
+ select IMX_FEC
150
select IMX_I2C
151
select OR_IRQ
152
select PCI_EXPRESS_DESIGNWARE
69
--
153
--
70
2.20.1
154
2.43.0
71
72
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Meson will find CoreFoundation, IOKit, and Cocoa as needed.
3
Split the USB MMIO regions to better keep track of the implemented vs.
4
unimplemented regions.
4
5
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Message-id: 20210126012457.39046-7-j@getutm.app
8
Message-id: 20250223114708.1780-16-shentey@gmail.com
9
[PMM: drop "static const" from usb_table for GCC 7.5]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
configure | 1 -
12
docs/system/arm/imx8mp-evk.rst | 1 +
11
1 file changed, 1 deletion(-)
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(-)
12
17
13
diff --git a/configure b/configure
18
diff --git a/docs/system/arm/imx8mp-evk.rst b/docs/system/arm/imx8mp-evk.rst
14
index XXXXXXX..XXXXXXX 100755
19
index XXXXXXX..XXXXXXX 100644
15
--- a/configure
20
--- a/docs/system/arm/imx8mp-evk.rst
16
+++ b/configure
21
+++ b/docs/system/arm/imx8mp-evk.rst
17
@@ -XXX,XX +XXX,XX @@ Darwin)
22
@@ -XXX,XX +XXX,XX @@ The ``imx8mp-evk`` machine implements the following devices:
18
fi
23
* 3 USDHC Storage Controllers
19
audio_drv_list="coreaudio try-sdl"
24
* 1 Designware PCI Express Controller
20
audio_possible_drivers="coreaudio sdl"
25
* 1 Ethernet Controller
21
- QEMU_LDFLAGS="-framework CoreFoundation -framework IOKit $QEMU_LDFLAGS"
26
+ * 2 Designware USB 3 Controllers
22
# Disable attempts to use ObjectiveC features in os/object.h since they
27
* 5 GPIO Controllers
23
# won't work when we're compiling with gcc as a C compiler.
28
* 6 I2C Controllers
24
QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
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
25
--
162
--
26
2.20.1
163
2.43.0
27
28
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
3
This was defined at some point before ARMv8.4, and will
4
shortly be used by new processor descriptions.
5
2
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Message-id: 20210120204400.1056582-1-richard.henderson@linaro.org
5
Message-id: 20250223114708.1780-18-shentey@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
7
---
11
target/arm/cpu.h | 1 +
8
include/hw/arm/fsl-imx8mp.h | 1 +
12
target/arm/helper.c | 4 ++--
9
hw/arm/fsl-imx8mp.c | 11 +++++++++++
13
target/arm/kvm64.c | 2 ++
10
2 files changed, 12 insertions(+)
14
3 files changed, 5 insertions(+), 2 deletions(-)
15
11
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
14
--- a/include/hw/arm/fsl-imx8mp.h
19
+++ b/target/arm/cpu.h
15
+++ b/include/hw/arm/fsl-imx8mp.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
16
@@ -XXX,XX +XXX,XX @@ struct FslImx8mpState {
21
uint32_t id_mmfr4;
17
DesignwarePCIEHost pcie;
22
uint32_t id_pfr0;
18
FslImx8mPciePhyState pcie_phy;
23
uint32_t id_pfr1;
19
OrIRQState gpt5_gpt6_irq;
24
+ uint32_t id_pfr2;
20
+ MemoryRegion ocram;
25
uint32_t mvfr0;
21
26
uint32_t mvfr1;
22
uint32_t phy_num;
27
uint32_t mvfr2;
23
bool phy_connected;
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
24
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
29
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper.c
26
--- a/hw/arm/fsl-imx8mp.c
31
+++ b/target/arm/helper.c
27
+++ b/hw/arm/fsl-imx8mp.c
32
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
28
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
33
.access = PL1_R, .type = ARM_CP_CONST,
29
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
34
.accessfn = access_aa64_tid3,
30
fsl_imx8mp_memmap[FSL_IMX8MP_PCIE_PHY1].addr);
35
.resetvalue = 0 },
31
36
- { .name = "MVFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
32
+ /* On-Chip RAM */
37
+ { .name = "ID_PFR2", .state = ARM_CP_STATE_BOTH,
33
+ if (!memory_region_init_ram(&s->ocram, NULL, "imx8mp.ocram",
38
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4,
34
+ fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].size,
39
.access = PL1_R, .type = ARM_CP_CONST,
35
+ errp)) {
40
.accessfn = access_aa64_tid3,
36
+ return;
41
- .resetvalue = 0 },
37
+ }
42
+ .resetvalue = cpu->isar.id_pfr2 },
38
+ memory_region_add_subregion(get_system_memory(),
43
{ .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
39
+ fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].addr,
44
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
40
+ &s->ocram);
45
.access = PL1_R, .type = ARM_CP_CONST,
41
+
46
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
42
/* Unimplemented devices */
47
index XXXXXXX..XXXXXXX 100644
43
for (i = 0; i < ARRAY_SIZE(fsl_imx8mp_memmap); i++) {
48
--- a/target/arm/kvm64.c
44
switch (i) {
49
+++ b/target/arm/kvm64.c
45
@@ -XXX,XX +XXX,XX @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
50
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
46
case FSL_IMX8MP_ECSPI1 ... FSL_IMX8MP_ECSPI3:
51
ARM64_SYS_REG(3, 0, 0, 1, 0));
47
case FSL_IMX8MP_ENET1:
52
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1,
48
case FSL_IMX8MP_I2C1 ... FSL_IMX8MP_I2C6:
53
ARM64_SYS_REG(3, 0, 0, 1, 1));
49
+ case FSL_IMX8MP_OCRAM:
54
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2,
50
case FSL_IMX8MP_PCIE1:
55
+ ARM64_SYS_REG(3, 0, 0, 3, 4));
51
case FSL_IMX8MP_PCIE_PHY1:
56
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
52
case FSL_IMX8MP_RAM:
57
ARM64_SYS_REG(3, 0, 0, 1, 2));
58
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
59
--
53
--
60
2.20.1
54
2.43.0
61
62
diff view generated by jsdifflib
Deleted patch
1
Move the preadv availability check to meson.build. This is what we
2
want to be doing for host-OS-feature-checks anyway, but it also fixes
3
a problem with building for macOS with the most recent XCode SDK on a
4
Catalina host.
5
1
6
On that configuration, 'preadv()' is provided as a weak symbol, so
7
that programs can be built with optional support for it and make a
8
runtime availability check to see whether the preadv() they have is a
9
working one or one which they must not call because it will
10
runtime-assert. QEMU's configure test passes (unless you're building
11
with --enable-werror) because the test program using preadv()
12
compiles, but then QEMU crashes at runtime when preadv() is called,
13
with errors like:
14
15
dyld: lazy symbol binding failed: Symbol not found: _preadv
16
Referenced from: /Users/pm215/src/qemu/./build/x86/tests/test-replication
17
Expected in: /usr/lib/libSystem.B.dylib
18
19
dyld: Symbol not found: _preadv
20
Referenced from: /Users/pm215/src/qemu/./build/x86/tests/test-replication
21
Expected in: /usr/lib/libSystem.B.dylib
22
23
Meson's own function availability check has a special case for macOS
24
which adds '-Wl,-no_weak_imports' to the compiler flags, which forces
25
the test to require the real function, not the macOS-version-too-old
26
stub.
27
28
So this commit fixes the bug where macOS builds on Catalina currently
29
require --disable-werror.
30
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
33
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
34
Message-id: 20210126155846.17109-1-peter.maydell@linaro.org
35
---
36
configure | 16 ----------------
37
meson.build | 4 +++-
38
2 files changed, 3 insertions(+), 17 deletions(-)
39
40
diff --git a/configure b/configure
41
index XXXXXXX..XXXXXXX 100755
42
--- a/configure
43
+++ b/configure
44
@@ -XXX,XX +XXX,XX @@ if compile_prog "" "" ; then
45
iovec=yes
46
fi
47
48
-##########################################
49
-# preadv probe
50
-cat > $TMPC <<EOF
51
-#include <sys/types.h>
52
-#include <sys/uio.h>
53
-#include <unistd.h>
54
-int main(void) { return preadv(0, 0, 0, 0); }
55
-EOF
56
-preadv=no
57
-if compile_prog "" "" ; then
58
- preadv=yes
59
-fi
60
-
61
##########################################
62
# fdt probe
63
64
@@ -XXX,XX +XXX,XX @@ fi
65
if test "$iovec" = "yes" ; then
66
echo "CONFIG_IOVEC=y" >> $config_host_mak
67
fi
68
-if test "$preadv" = "yes" ; then
69
- echo "CONFIG_PREADV=y" >> $config_host_mak
70
-fi
71
if test "$membarrier" = "yes" ; then
72
echo "CONFIG_MEMBARRIER=y" >> $config_host_mak
73
fi
74
diff --git a/meson.build b/meson.build
75
index XXXXXXX..XXXXXXX 100644
76
--- a/meson.build
77
+++ b/meson.build
78
@@ -XXX,XX +XXX,XX @@ config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
79
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
80
config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
81
82
+config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
83
+
84
ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
85
arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
86
strings = ['HOST_DSOSUF', 'CONFIG_IASL']
87
@@ -XXX,XX +XXX,XX @@ summary_info += {'PIE': get_option('b_pie')}
88
summary_info += {'static build': config_host.has_key('CONFIG_STATIC')}
89
summary_info += {'malloc trim support': has_malloc_trim}
90
summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')}
91
-summary_info += {'preadv support': config_host.has_key('CONFIG_PREADV')}
92
+summary_info += {'preadv support': config_host_data.get('CONFIG_PREADV')}
93
summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')}
94
summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')}
95
summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
Deleted patch
1
From: Joelle van Dyne <j@getutm.app>
2
1
3
The iOS toolchain does not use the host prefix naming convention. So we
4
need to enable cross-compile options while allowing the PREFIX to be
5
blank.
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Joelle van Dyne <j@getutm.app>
9
Message-id: 20210126012457.39046-3-j@getutm.app
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
configure | 6 ++++--
13
1 file changed, 4 insertions(+), 2 deletions(-)
14
15
diff --git a/configure b/configure
16
index XXXXXXX..XXXXXXX 100755
17
--- a/configure
18
+++ b/configure
19
@@ -XXX,XX +XXX,XX @@ cpu=""
20
iasl="iasl"
21
interp_prefix="/usr/gnemul/qemu-%M"
22
static="no"
23
+cross_compile="no"
24
cross_prefix=""
25
audio_drv_list=""
26
block_drv_rw_whitelist=""
27
@@ -XXX,XX +XXX,XX @@ for opt do
28
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
29
case "$opt" in
30
--cross-prefix=*) cross_prefix="$optarg"
31
+ cross_compile="yes"
32
;;
33
--cc=*) CC="$optarg"
34
;;
35
@@ -XXX,XX +XXX,XX @@ $(echo Deprecated targets: $deprecated_targets_list | \
36
--target-list-exclude=LIST exclude a set of targets from the default target-list
37
38
Advanced options (experts only):
39
- --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
40
+ --cross-prefix=PREFIX use PREFIX for compile tools, PREFIX can be blank [$cross_prefix]
41
--cc=CC use C compiler CC [$cc]
42
--iasl=IASL use ACPI compiler IASL [$iasl]
43
--host-cc=CC use C compiler CC [$host_cc] for code run at
44
@@ -XXX,XX +XXX,XX @@ if has $sdl2_config; then
45
fi
46
echo "strip = [$(meson_quote $strip)]" >> $cross
47
echo "windres = [$(meson_quote $windres)]" >> $cross
48
-if test -n "$cross_prefix"; then
49
+if test "$cross_compile" = "yes"; then
50
cross_arg="--cross-file config-meson.cross"
51
echo "[host_machine]" >> $cross
52
if test "$mingw32" = "yes" ; then
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Joelle van Dyne <j@getutm.app>
2
1
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
Signed-off-by: Joelle van Dyne <j@getutm.app>
5
Message-id: 20210126012457.39046-9-j@getutm.app
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
configure | 5 ++++-
9
1 file changed, 4 insertions(+), 1 deletion(-)
10
11
diff --git a/configure b/configure
12
index XXXXXXX..XXXXXXX 100755
13
--- a/configure
14
+++ b/configure
15
@@ -XXX,XX +XXX,XX @@ if test "$cross_compile" = "yes"; then
16
echo "system = 'darwin'" >> $cross
17
fi
18
case "$ARCH" in
19
- i386|x86_64)
20
+ i386)
21
echo "cpu_family = 'x86'" >> $cross
22
;;
23
+ x86_64)
24
+ echo "cpu_family = 'x86_64'" >> $cross
25
+ ;;
26
ppc64le)
27
echo "cpu_family = 'ppc64'" >> $cross
28
;;
29
--
30
2.20.1
31
32
diff view generated by jsdifflib